debug.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 <iomanip>
  11. #include <iostream>
  12. #include <typeinfo>
  13. #include <boost/preprocessor/stringize.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 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. };
  88. template<typename Tag>
  89. std::ostream &operator <<(ostream_wrapper sout_wrap, Tag const &)
  90. {
  91. return sout_wrap.sout_ << typeid(Tag).name();
  92. }
  93. }
  94. namespace functional
  95. {
  96. /// \brief Pretty-print a Proto expression tree.
  97. ///
  98. /// A PolymorphicFunctionObject which accepts a Proto expression
  99. /// tree and pretty-prints it to an \c ostream for debugging
  100. /// purposes.
  101. struct display_expr
  102. {
  103. BOOST_PROTO_CALLABLE()
  104. typedef void result_type;
  105. /// \param sout The \c ostream to which the expression tree
  106. /// will be written.
  107. /// \param depth The starting indentation depth for this node.
  108. /// Children nodes will be displayed at a starting
  109. /// depth of <tt>depth+4</tt>.
  110. explicit display_expr(std::ostream &sout = std::cout, int depth = 0)
  111. : depth_(depth)
  112. , first_(true)
  113. , sout_(sout)
  114. {}
  115. /// \brief Pretty-print the current node in a Proto expression
  116. /// tree.
  117. template<typename Expr>
  118. void operator()(Expr const &expr) const
  119. {
  120. this->impl(expr, mpl::long_<arity_of<Expr>::value>());
  121. }
  122. private:
  123. display_expr(display_expr const &);
  124. display_expr &operator =(display_expr const &);
  125. template<typename Expr>
  126. void impl(Expr const &expr, mpl::long_<0>) const
  127. {
  128. using namespace hidden_detail_;
  129. typedef typename tag_of<Expr>::type tag;
  130. this->sout_ << std::setw(this->depth_) << (this->first_? "" : ", ");
  131. this->sout_ << tag() << "(" << proto::value(expr) << ")\n";
  132. this->first_ = false;
  133. }
  134. template<typename Expr, typename Arity>
  135. void impl(Expr const &expr, Arity) const
  136. {
  137. using namespace hidden_detail_;
  138. typedef typename tag_of<Expr>::type tag;
  139. this->sout_ << std::setw(this->depth_) << (this->first_? "" : ", ");
  140. this->sout_ << tag() << "(\n";
  141. display_expr display(this->sout_, this->depth_ + 4);
  142. fusion::for_each(expr, display);
  143. this->sout_ << std::setw(this->depth_) << "" << ")\n";
  144. this->first_ = false;
  145. }
  146. int depth_;
  147. mutable bool first_;
  148. std::ostream &sout_;
  149. };
  150. }
  151. /// \brief Pretty-print a Proto expression tree.
  152. ///
  153. /// \note Equivalent to <tt>functional::display_expr(0, sout)(expr)</tt>
  154. /// \param expr The Proto expression tree to pretty-print
  155. /// \param sout The \c ostream to which the output should be
  156. /// written. If not specified, defaults to
  157. /// <tt>std::cout</tt>.
  158. template<typename Expr>
  159. void display_expr(Expr const &expr, std::ostream &sout)
  160. {
  161. functional::display_expr(sout, 0)(expr);
  162. }
  163. /// \overload
  164. ///
  165. template<typename Expr>
  166. void display_expr(Expr const &expr)
  167. {
  168. functional::display_expr()(expr);
  169. }
  170. /// \brief Assert at compile time that a particular expression
  171. /// matches the specified grammar.
  172. ///
  173. /// \note Equivalent to <tt>BOOST_MPL_ASSERT((proto::matches\<Expr, Grammar\>))</tt>
  174. /// \param expr The Proto expression to check againts <tt>Grammar</tt>
  175. template<typename Grammar, typename Expr>
  176. void assert_matches(Expr const & /*expr*/)
  177. {
  178. BOOST_MPL_ASSERT((proto::matches<Expr, Grammar>));
  179. }
  180. /// \brief Assert at compile time that a particular expression
  181. /// does not match the specified grammar.
  182. ///
  183. /// \note Equivalent to <tt>BOOST_MPL_ASSERT_NOT((proto::matches\<Expr, Grammar\>))</tt>
  184. /// \param expr The Proto expression to check againts <tt>Grammar</tt>
  185. template<typename Grammar, typename Expr>
  186. void assert_matches_not(Expr const & /*expr*/)
  187. {
  188. BOOST_MPL_ASSERT_NOT((proto::matches<Expr, Grammar>));
  189. }
  190. /// \brief Assert at compile time that a particular expression
  191. /// matches the specified grammar.
  192. ///
  193. /// \note Equivalent to <tt>proto::assert_matches\<Grammar\>(Expr)</tt>
  194. /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
  195. /// \param Grammar The grammar used to validate Expr.
  196. #define BOOST_PROTO_ASSERT_MATCHES(Expr, Grammar) \
  197. (true ? (void)0 : boost::proto::assert_matches<Grammar>(Expr))
  198. /// \brief Assert at compile time that a particular expression
  199. /// does not match the specified grammar.
  200. ///
  201. /// \note Equivalent to <tt>proto::assert_matches_not\<Grammar\>(Expr)</tt>
  202. /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
  203. /// \param Grammar The grammar used to validate Expr.
  204. #define BOOST_PROTO_ASSERT_MATCHES_NOT(Expr, Grammar) \
  205. (true ? (void)0 : boost::proto::assert_matches_not<Grammar>(Expr))
  206. }}
  207. #endif