]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/proto/debug.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / proto / debug.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file debug.hpp
3 /// Utilities for debugging Proto expression trees
4 //
5 // Copyright 2008 Eric Niebler. Distributed under the Boost
6 // Software License, Version 1.0. (See accompanying file
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9 #ifndef BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006
10 #define BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006
11
12 #include <iostream>
13 #include <boost/preprocessor/stringize.hpp>
14 #include <boost/core/ref.hpp>
15 #include <boost/core/typeinfo.hpp>
16 #include <boost/mpl/assert.hpp>
17 #include <boost/proto/proto_fwd.hpp>
18 #include <boost/proto/traits.hpp>
19 #include <boost/proto/matches.hpp>
20 #include <boost/proto/fusion.hpp>
21 #include <boost/fusion/algorithm/iteration/for_each.hpp>
22
23 namespace boost { namespace proto
24 {
25 namespace tagns_ { namespace tag
26 {
27 #define BOOST_PROTO_DEFINE_TAG_INSERTION(Tag) \
28 /** \brief INTERNAL ONLY */ \
29 inline std::ostream &operator <<(std::ostream &sout, Tag const &) \
30 { \
31 return sout << BOOST_PP_STRINGIZE(Tag); \
32 } \
33 /**/
34
35 BOOST_PROTO_DEFINE_TAG_INSERTION(terminal)
36 BOOST_PROTO_DEFINE_TAG_INSERTION(unary_plus)
37 BOOST_PROTO_DEFINE_TAG_INSERTION(negate)
38 BOOST_PROTO_DEFINE_TAG_INSERTION(dereference)
39 BOOST_PROTO_DEFINE_TAG_INSERTION(complement)
40 BOOST_PROTO_DEFINE_TAG_INSERTION(address_of)
41 BOOST_PROTO_DEFINE_TAG_INSERTION(logical_not)
42 BOOST_PROTO_DEFINE_TAG_INSERTION(pre_inc)
43 BOOST_PROTO_DEFINE_TAG_INSERTION(pre_dec)
44 BOOST_PROTO_DEFINE_TAG_INSERTION(post_inc)
45 BOOST_PROTO_DEFINE_TAG_INSERTION(post_dec)
46 BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left)
47 BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right)
48 BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies)
49 BOOST_PROTO_DEFINE_TAG_INSERTION(divides)
50 BOOST_PROTO_DEFINE_TAG_INSERTION(modulus)
51 BOOST_PROTO_DEFINE_TAG_INSERTION(plus)
52 BOOST_PROTO_DEFINE_TAG_INSERTION(minus)
53 BOOST_PROTO_DEFINE_TAG_INSERTION(less)
54 BOOST_PROTO_DEFINE_TAG_INSERTION(greater)
55 BOOST_PROTO_DEFINE_TAG_INSERTION(less_equal)
56 BOOST_PROTO_DEFINE_TAG_INSERTION(greater_equal)
57 BOOST_PROTO_DEFINE_TAG_INSERTION(equal_to)
58 BOOST_PROTO_DEFINE_TAG_INSERTION(not_equal_to)
59 BOOST_PROTO_DEFINE_TAG_INSERTION(logical_or)
60 BOOST_PROTO_DEFINE_TAG_INSERTION(logical_and)
61 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and)
62 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or)
63 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor)
64 BOOST_PROTO_DEFINE_TAG_INSERTION(comma)
65 BOOST_PROTO_DEFINE_TAG_INSERTION(mem_ptr)
66 BOOST_PROTO_DEFINE_TAG_INSERTION(assign)
67 BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left_assign)
68 BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right_assign)
69 BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies_assign)
70 BOOST_PROTO_DEFINE_TAG_INSERTION(divides_assign)
71 BOOST_PROTO_DEFINE_TAG_INSERTION(modulus_assign)
72 BOOST_PROTO_DEFINE_TAG_INSERTION(plus_assign)
73 BOOST_PROTO_DEFINE_TAG_INSERTION(minus_assign)
74 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and_assign)
75 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or_assign)
76 BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor_assign)
77 BOOST_PROTO_DEFINE_TAG_INSERTION(subscript)
78 BOOST_PROTO_DEFINE_TAG_INSERTION(member)
79 BOOST_PROTO_DEFINE_TAG_INSERTION(if_else_)
80 BOOST_PROTO_DEFINE_TAG_INSERTION(function)
81
82 #undef BOOST_PROTO_DEFINE_TAG_INSERTION
83 }}
84
85 namespace hidden_detail_
86 {
87 struct ostream_wrapper
88 {
89 ostream_wrapper(std::ostream &sout)
90 : sout_(sout)
91 {}
92
93 std::ostream &sout_;
94
95 BOOST_DELETED_FUNCTION(ostream_wrapper &operator =(ostream_wrapper const &))
96 };
97
98 struct named_any
99 {
100 template<typename T>
101 named_any(T const &)
102 : name_(BOOST_CORE_TYPEID(T).name())
103 {}
104
105 char const *name_;
106 };
107
108 inline std::ostream &operator <<(ostream_wrapper sout_wrap, named_any t)
109 {
110 return sout_wrap.sout_ << t.name_;
111 }
112 }
113
114 namespace detail
115 {
116 // copyable functor to pass by value to fusion::foreach
117 struct display_expr_impl;
118 struct display_expr_impl_functor
119 {
120 display_expr_impl_functor(display_expr_impl const& impl): impl_(impl)
121 {}
122
123 template<typename Expr>
124 void operator()(Expr const &expr) const
125 {
126 this->impl_(expr);
127 }
128
129 private:
130 display_expr_impl const& impl_;
131 };
132
133 struct display_expr_impl
134 {
135 explicit display_expr_impl(std::ostream &sout, int depth = 0)
136 : depth_(depth)
137 , first_(true)
138 , sout_(sout)
139 {}
140
141 template<typename Expr>
142 void operator()(Expr const &expr) const
143 {
144 this->impl(expr, mpl::long_<arity_of<Expr>::value>());
145 }
146
147 BOOST_DELETED_FUNCTION(display_expr_impl(display_expr_impl const &))
148 BOOST_DELETED_FUNCTION(display_expr_impl &operator =(display_expr_impl const &))
149 private:
150
151 template<typename Expr>
152 void impl(Expr const &expr, mpl::long_<0>) const
153 {
154 using namespace hidden_detail_;
155 typedef typename tag_of<Expr>::type tag;
156 this->sout_.width(this->depth_);
157 this->sout_ << (this->first_? "" : ", ");
158 this->sout_ << tag() << "(" << proto::value(expr) << ")\n";
159 this->first_ = false;
160 }
161
162 template<typename Expr, typename Arity>
163 void impl(Expr const &expr, Arity) const
164 {
165 using namespace hidden_detail_;
166 typedef typename tag_of<Expr>::type tag;
167 this->sout_.width(this->depth_);
168 this->sout_ << (this->first_? "" : ", ");
169 this->sout_ << tag() << "(\n";
170 display_expr_impl display(this->sout_, this->depth_ + 4);
171 fusion::for_each(expr, display_expr_impl_functor(display));
172 this->sout_.width(this->depth_);
173 this->sout_ << "" << ")\n";
174 this->first_ = false;
175 }
176
177 int depth_;
178 mutable bool first_;
179 std::ostream &sout_;
180 };
181 }
182
183 namespace functional
184 {
185 /// \brief Pretty-print a Proto expression tree.
186 ///
187 /// A PolymorphicFunctionObject which accepts a Proto expression
188 /// tree and pretty-prints it to an \c ostream for debugging
189 /// purposes.
190 struct display_expr
191 {
192 BOOST_PROTO_CALLABLE()
193
194 typedef void result_type;
195
196 /// \param sout The \c ostream to which the expression tree
197 /// will be written.
198 /// \param depth The starting indentation depth for this node.
199 /// Children nodes will be displayed at a starting
200 /// depth of <tt>depth+4</tt>.
201 explicit display_expr(std::ostream &sout = std::cout, int depth = 0)
202 : depth_(depth)
203 , sout_(sout)
204 {}
205
206 /// \brief Pretty-print the current node in a Proto expression
207 /// tree.
208 template<typename Expr>
209 void operator()(Expr const &expr) const
210 {
211 detail::display_expr_impl(this->sout_, this->depth_)(expr);
212 }
213
214 private:
215 int depth_;
216 reference_wrapper<std::ostream> sout_;
217 };
218 }
219
220 /// \brief Pretty-print a Proto expression tree.
221 ///
222 /// \note Equivalent to <tt>functional::display_expr(0, sout)(expr)</tt>
223 /// \param expr The Proto expression tree to pretty-print
224 /// \param sout The \c ostream to which the output should be
225 /// written. If not specified, defaults to
226 /// <tt>std::cout</tt>.
227 template<typename Expr>
228 void display_expr(Expr const &expr, std::ostream &sout)
229 {
230 functional::display_expr(sout, 0)(expr);
231 }
232
233 /// \overload
234 ///
235 template<typename Expr>
236 void display_expr(Expr const &expr)
237 {
238 functional::display_expr()(expr);
239 }
240
241 /// \brief Assert at compile time that a particular expression
242 /// matches the specified grammar.
243 ///
244 /// \note Equivalent to <tt>BOOST_MPL_ASSERT((proto::matches\<Expr, Grammar\>))</tt>
245 /// \param expr The Proto expression to check againts <tt>Grammar</tt>
246 template<typename Grammar, typename Expr>
247 void assert_matches(Expr const & /*expr*/)
248 {
249 BOOST_MPL_ASSERT((proto::matches<Expr, Grammar>));
250 }
251
252 /// \brief Assert at compile time that a particular expression
253 /// does not match the specified grammar.
254 ///
255 /// \note Equivalent to <tt>BOOST_MPL_ASSERT_NOT((proto::matches\<Expr, Grammar\>))</tt>
256 /// \param expr The Proto expression to check againts <tt>Grammar</tt>
257 template<typename Grammar, typename Expr>
258 void assert_matches_not(Expr const & /*expr*/)
259 {
260 BOOST_MPL_ASSERT_NOT((proto::matches<Expr, Grammar>));
261 }
262
263 /// \brief Assert at compile time that a particular expression
264 /// matches the specified grammar.
265 ///
266 /// \note Equivalent to <tt>proto::assert_matches\<Grammar\>(Expr)</tt>
267 /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
268 /// \param Grammar The grammar used to validate Expr.
269 #define BOOST_PROTO_ASSERT_MATCHES(Expr, Grammar) \
270 (true ? (void)0 : boost::proto::assert_matches<Grammar>(Expr))
271
272 /// \brief Assert at compile time that a particular expression
273 /// does not match the specified grammar.
274 ///
275 /// \note Equivalent to <tt>proto::assert_matches_not\<Grammar\>(Expr)</tt>
276 /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
277 /// \param Grammar The grammar used to validate Expr.
278 #define BOOST_PROTO_ASSERT_MATCHES_NOT(Expr, Grammar) \
279 (true ? (void)0 : boost::proto::assert_matches_not<Grammar>(Expr))
280
281 }}
282
283 #endif