Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file debug.hpp Chris@16: /// Utilities for debugging Proto expression trees Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006 Chris@16: #define BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace proto Chris@16: { Chris@16: namespace tagns_ { namespace tag Chris@16: { Chris@16: #define BOOST_PROTO_DEFINE_TAG_INSERTION(Tag) \ Chris@16: /** \brief INTERNAL ONLY */ \ Chris@16: inline std::ostream &operator <<(std::ostream &sout, Tag const &) \ Chris@16: { \ Chris@16: return sout << BOOST_PP_STRINGIZE(Tag); \ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(terminal) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(unary_plus) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(negate) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(dereference) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(complement) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(address_of) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(logical_not) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(pre_inc) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(pre_dec) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(post_inc) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(post_dec) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(divides) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(modulus) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(plus) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(minus) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(less) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(greater) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(less_equal) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(greater_equal) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(equal_to) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(not_equal_to) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(logical_or) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(logical_and) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(comma) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(mem_ptr) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(divides_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(modulus_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(plus_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(minus_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor_assign) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(subscript) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(member) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(if_else_) Chris@16: BOOST_PROTO_DEFINE_TAG_INSERTION(function) Chris@16: Chris@16: #undef BOOST_PROTO_DEFINE_TAG_INSERTION Chris@16: }} Chris@16: Chris@16: namespace hidden_detail_ Chris@16: { Chris@16: struct ostream_wrapper Chris@16: { Chris@16: ostream_wrapper(std::ostream &sout) Chris@16: : sout_(sout) Chris@16: {} Chris@16: Chris@16: std::ostream &sout_; Chris@16: Chris@16: private: Chris@16: ostream_wrapper &operator =(ostream_wrapper const &); Chris@16: }; Chris@16: Chris@16: struct named_any Chris@16: { Chris@16: template Chris@16: named_any(T const &) Chris@16: : name_(BOOST_SP_TYPEID(T).name()) Chris@16: {} Chris@16: Chris@16: char const *name_; Chris@16: }; Chris@16: Chris@16: inline std::ostream &operator <<(ostream_wrapper sout_wrap, named_any t) Chris@16: { Chris@16: return sout_wrap.sout_ << t.name_; Chris@16: } Chris@16: } Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: struct display_expr_impl Chris@16: { Chris@16: explicit display_expr_impl(std::ostream &sout, int depth = 0) Chris@16: : depth_(depth) Chris@16: , first_(true) Chris@16: , sout_(sout) Chris@16: {} Chris@16: Chris@16: template Chris@16: void operator()(Expr const &expr) const Chris@16: { Chris@16: this->impl(expr, mpl::long_::value>()); Chris@16: } Chris@16: Chris@16: private: Chris@16: display_expr_impl(display_expr_impl const &); Chris@16: display_expr_impl &operator =(display_expr_impl const &); Chris@16: Chris@16: template Chris@16: void impl(Expr const &expr, mpl::long_<0>) const Chris@16: { Chris@16: using namespace hidden_detail_; Chris@16: typedef typename tag_of::type tag; Chris@16: this->sout_.width(this->depth_); Chris@16: this->sout_ << (this->first_? "" : ", "); Chris@16: this->sout_ << tag() << "(" << proto::value(expr) << ")\n"; Chris@16: this->first_ = false; Chris@16: } Chris@16: Chris@16: template Chris@16: void impl(Expr const &expr, Arity) const Chris@16: { Chris@16: using namespace hidden_detail_; Chris@16: typedef typename tag_of::type tag; Chris@16: this->sout_.width(this->depth_); Chris@16: this->sout_ << (this->first_? "" : ", "); Chris@16: this->sout_ << tag() << "(\n"; Chris@16: display_expr_impl display(this->sout_, this->depth_ + 4); Chris@16: fusion::for_each(expr, display); Chris@16: this->sout_.width(this->depth_); Chris@16: this->sout_ << "" << ")\n"; Chris@16: this->first_ = false; Chris@16: } Chris@16: Chris@16: int depth_; Chris@16: mutable bool first_; Chris@16: std::ostream &sout_; Chris@16: }; Chris@16: } Chris@16: Chris@16: namespace functional Chris@16: { Chris@16: /// \brief Pretty-print a Proto expression tree. Chris@16: /// Chris@16: /// A PolymorphicFunctionObject which accepts a Proto expression Chris@16: /// tree and pretty-prints it to an \c ostream for debugging Chris@16: /// purposes. Chris@16: struct display_expr Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: typedef void result_type; Chris@16: Chris@16: /// \param sout The \c ostream to which the expression tree Chris@16: /// will be written. Chris@16: /// \param depth The starting indentation depth for this node. Chris@16: /// Children nodes will be displayed at a starting Chris@16: /// depth of depth+4. Chris@16: explicit display_expr(std::ostream &sout = std::cout, int depth = 0) Chris@16: : depth_(depth) Chris@16: , sout_(sout) Chris@16: {} Chris@16: Chris@16: /// \brief Pretty-print the current node in a Proto expression Chris@16: /// tree. Chris@16: template Chris@16: void operator()(Expr const &expr) const Chris@16: { Chris@16: detail::display_expr_impl(this->sout_, this->depth_)(expr); Chris@16: } Chris@16: Chris@16: private: Chris@16: int depth_; Chris@16: reference_wrapper sout_; Chris@16: }; Chris@16: } Chris@16: Chris@16: /// \brief Pretty-print a Proto expression tree. Chris@16: /// Chris@16: /// \note Equivalent to functional::display_expr(0, sout)(expr) Chris@16: /// \param expr The Proto expression tree to pretty-print Chris@16: /// \param sout The \c ostream to which the output should be Chris@16: /// written. If not specified, defaults to Chris@16: /// std::cout. Chris@16: template Chris@16: void display_expr(Expr const &expr, std::ostream &sout) Chris@16: { Chris@16: functional::display_expr(sout, 0)(expr); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: void display_expr(Expr const &expr) Chris@16: { Chris@16: functional::display_expr()(expr); Chris@16: } Chris@16: Chris@16: /// \brief Assert at compile time that a particular expression Chris@16: /// matches the specified grammar. Chris@16: /// Chris@16: /// \note Equivalent to BOOST_MPL_ASSERT((proto::matches\)) Chris@16: /// \param expr The Proto expression to check againts Grammar Chris@16: template Chris@16: void assert_matches(Expr const & /*expr*/) Chris@16: { Chris@16: BOOST_MPL_ASSERT((proto::matches)); Chris@16: } Chris@16: Chris@16: /// \brief Assert at compile time that a particular expression Chris@16: /// does not match the specified grammar. Chris@16: /// Chris@16: /// \note Equivalent to BOOST_MPL_ASSERT_NOT((proto::matches\)) Chris@16: /// \param expr The Proto expression to check againts Grammar Chris@16: template Chris@16: void assert_matches_not(Expr const & /*expr*/) Chris@16: { Chris@16: BOOST_MPL_ASSERT_NOT((proto::matches)); Chris@16: } Chris@16: Chris@16: /// \brief Assert at compile time that a particular expression Chris@16: /// matches the specified grammar. Chris@16: /// Chris@16: /// \note Equivalent to proto::assert_matches\(Expr) Chris@16: /// \param Expr The Proto expression to check againts Grammar Chris@16: /// \param Grammar The grammar used to validate Expr. Chris@16: #define BOOST_PROTO_ASSERT_MATCHES(Expr, Grammar) \ Chris@16: (true ? (void)0 : boost::proto::assert_matches(Expr)) Chris@16: Chris@16: /// \brief Assert at compile time that a particular expression Chris@16: /// does not match the specified grammar. Chris@16: /// Chris@16: /// \note Equivalent to proto::assert_matches_not\(Expr) Chris@16: /// \param Expr The Proto expression to check againts Grammar Chris@16: /// \param Grammar The grammar used to validate Expr. Chris@16: #define BOOST_PROTO_ASSERT_MATCHES_NOT(Expr, Grammar) \ Chris@16: (true ? (void)0 : boost::proto::assert_matches_not(Expr)) Chris@16: Chris@16: }} Chris@16: Chris@16: #endif