debug.hpp 10 KB

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