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