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