Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:32

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file debug.hpp
0003 /// Utilities for debugging Proto expression trees
0004 //
0005 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0006 //  Software License, Version 1.0. (See accompanying file
0007 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #ifndef BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006
0010 #define BOOST_PROTO_DEBUG_HPP_EAN_12_31_2006
0011 
0012 #include <iostream>
0013 #include <boost/preprocessor/stringize.hpp>
0014 #include <boost/core/ref.hpp>
0015 #include <boost/core/typeinfo.hpp>
0016 #include <boost/mpl/assert.hpp>
0017 #include <boost/proto/proto_fwd.hpp>
0018 #include <boost/proto/traits.hpp>
0019 #include <boost/proto/matches.hpp>
0020 #include <boost/proto/fusion.hpp>
0021 #include <boost/fusion/algorithm/iteration/for_each.hpp>
0022 
0023 namespace boost { namespace proto
0024 {
0025     namespace tagns_ { namespace tag
0026     {
0027     #define BOOST_PROTO_DEFINE_TAG_INSERTION(Tag)                               \
0028         /** \brief INTERNAL ONLY */                                             \
0029         inline std::ostream &operator <<(std::ostream &sout, Tag const &)       \
0030         {                                                                       \
0031             return sout << BOOST_PP_STRINGIZE(Tag);                             \
0032         }                                                                       \
0033         /**/
0034 
0035         BOOST_PROTO_DEFINE_TAG_INSERTION(terminal)
0036         BOOST_PROTO_DEFINE_TAG_INSERTION(unary_plus)
0037         BOOST_PROTO_DEFINE_TAG_INSERTION(negate)
0038         BOOST_PROTO_DEFINE_TAG_INSERTION(dereference)
0039         BOOST_PROTO_DEFINE_TAG_INSERTION(complement)
0040         BOOST_PROTO_DEFINE_TAG_INSERTION(address_of)
0041         BOOST_PROTO_DEFINE_TAG_INSERTION(logical_not)
0042         BOOST_PROTO_DEFINE_TAG_INSERTION(pre_inc)
0043         BOOST_PROTO_DEFINE_TAG_INSERTION(pre_dec)
0044         BOOST_PROTO_DEFINE_TAG_INSERTION(post_inc)
0045         BOOST_PROTO_DEFINE_TAG_INSERTION(post_dec)
0046         BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left)
0047         BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right)
0048         BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies)
0049         BOOST_PROTO_DEFINE_TAG_INSERTION(divides)
0050         BOOST_PROTO_DEFINE_TAG_INSERTION(modulus)
0051         BOOST_PROTO_DEFINE_TAG_INSERTION(plus)
0052         BOOST_PROTO_DEFINE_TAG_INSERTION(minus)
0053         BOOST_PROTO_DEFINE_TAG_INSERTION(less)
0054         BOOST_PROTO_DEFINE_TAG_INSERTION(greater)
0055         BOOST_PROTO_DEFINE_TAG_INSERTION(less_equal)
0056         BOOST_PROTO_DEFINE_TAG_INSERTION(greater_equal)
0057         BOOST_PROTO_DEFINE_TAG_INSERTION(equal_to)
0058         BOOST_PROTO_DEFINE_TAG_INSERTION(not_equal_to)
0059         BOOST_PROTO_DEFINE_TAG_INSERTION(logical_or)
0060         BOOST_PROTO_DEFINE_TAG_INSERTION(logical_and)
0061         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and)
0062         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or)
0063         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor)
0064         BOOST_PROTO_DEFINE_TAG_INSERTION(comma)
0065         BOOST_PROTO_DEFINE_TAG_INSERTION(mem_ptr)
0066         BOOST_PROTO_DEFINE_TAG_INSERTION(assign)
0067         BOOST_PROTO_DEFINE_TAG_INSERTION(shift_left_assign)
0068         BOOST_PROTO_DEFINE_TAG_INSERTION(shift_right_assign)
0069         BOOST_PROTO_DEFINE_TAG_INSERTION(multiplies_assign)
0070         BOOST_PROTO_DEFINE_TAG_INSERTION(divides_assign)
0071         BOOST_PROTO_DEFINE_TAG_INSERTION(modulus_assign)
0072         BOOST_PROTO_DEFINE_TAG_INSERTION(plus_assign)
0073         BOOST_PROTO_DEFINE_TAG_INSERTION(minus_assign)
0074         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_and_assign)
0075         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_or_assign)
0076         BOOST_PROTO_DEFINE_TAG_INSERTION(bitwise_xor_assign)
0077         BOOST_PROTO_DEFINE_TAG_INSERTION(subscript)
0078         BOOST_PROTO_DEFINE_TAG_INSERTION(member)
0079         BOOST_PROTO_DEFINE_TAG_INSERTION(if_else_)
0080         BOOST_PROTO_DEFINE_TAG_INSERTION(function)
0081 
0082     #undef BOOST_PROTO_DEFINE_TAG_INSERTION
0083     }}
0084 
0085     namespace hidden_detail_
0086     {
0087         struct ostream_wrapper
0088         {
0089             ostream_wrapper(std::ostream &sout)
0090               : sout_(sout)
0091             {}
0092 
0093             std::ostream &sout_;
0094 
0095             BOOST_DELETED_FUNCTION(ostream_wrapper &operator =(ostream_wrapper const &))
0096         };
0097 
0098         struct named_any
0099         {
0100             template<typename T>
0101             named_any(T const &)
0102               : name_(BOOST_CORE_TYPEID(T).name())
0103             {}
0104 
0105             char const *name_;
0106         };
0107 
0108         inline std::ostream &operator <<(ostream_wrapper sout_wrap, named_any t)
0109         {
0110             return sout_wrap.sout_ << t.name_;
0111         }
0112     }
0113 
0114     namespace detail
0115     {
0116         // copyable functor to pass by value to fusion::foreach
0117         struct display_expr_impl;
0118         struct display_expr_impl_functor
0119         {
0120             display_expr_impl_functor(display_expr_impl const& impl): impl_(impl)
0121             {}
0122 
0123             template<typename Expr>
0124             void operator()(Expr const &expr) const
0125             {
0126                 this->impl_(expr);
0127             }
0128 
0129         private:
0130             display_expr_impl const& impl_;
0131         };
0132 
0133         struct display_expr_impl
0134         {
0135             explicit display_expr_impl(std::ostream &sout, int depth = 0)
0136               : depth_(depth)
0137               , first_(true)
0138               , sout_(sout)
0139             {}
0140 
0141             template<typename Expr>
0142             void operator()(Expr const &expr) const
0143             {
0144                 this->impl(expr, mpl::long_<arity_of<Expr>::value>());
0145             }
0146 
0147             BOOST_DELETED_FUNCTION(display_expr_impl(display_expr_impl const &))
0148             BOOST_DELETED_FUNCTION(display_expr_impl &operator =(display_expr_impl const &))
0149         private:
0150 
0151             template<typename Expr>
0152             void impl(Expr const &expr, mpl::long_<0>) const
0153             {
0154                 using namespace hidden_detail_;
0155                 typedef typename tag_of<Expr>::type tag;
0156                 this->sout_.width(this->depth_);
0157                 this->sout_ << (this->first_? "" : ", ");
0158                 this->sout_ << tag() << "(" << proto::value(expr) << ")\n";
0159                 this->first_ = false;
0160             }
0161 
0162             template<typename Expr, typename Arity>
0163             void impl(Expr const &expr, Arity) const
0164             {
0165                 using namespace hidden_detail_;
0166                 typedef typename tag_of<Expr>::type tag;
0167                 this->sout_.width(this->depth_);
0168                 this->sout_ << (this->first_? "" : ", ");
0169                 this->sout_ << tag() << "(\n";
0170                 display_expr_impl display(this->sout_, this->depth_ + 4);
0171                 fusion::for_each(expr, display_expr_impl_functor(display));
0172                 this->sout_.width(this->depth_);
0173                 this->sout_ << "" << ")\n";
0174                 this->first_ = false;
0175             }
0176 
0177             int depth_;
0178             mutable bool first_;
0179             std::ostream &sout_;
0180         };
0181     }
0182 
0183     namespace functional
0184     {
0185         /// \brief Pretty-print a Proto expression tree.
0186         ///
0187         /// A PolymorphicFunctionObject which accepts a Proto expression
0188         /// tree and pretty-prints it to an \c ostream for debugging
0189         /// purposes.
0190         struct display_expr
0191         {
0192             BOOST_PROTO_CALLABLE()
0193 
0194             typedef void result_type;
0195 
0196             /// \param sout  The \c ostream to which the expression tree
0197             ///              will be written.
0198             /// \param depth The starting indentation depth for this node.
0199             ///              Children nodes will be displayed at a starting
0200             ///              depth of <tt>depth+4</tt>.
0201             explicit display_expr(std::ostream &sout = std::cout, int depth = 0)
0202               : depth_(depth)
0203               , sout_(sout)
0204             {}
0205 
0206             /// \brief Pretty-print the current node in a Proto expression
0207             /// tree.
0208             template<typename Expr>
0209             void operator()(Expr const &expr) const
0210             {
0211                 detail::display_expr_impl(this->sout_, this->depth_)(expr);
0212             }
0213 
0214         private:
0215             int depth_;
0216             reference_wrapper<std::ostream> sout_;
0217         };
0218     }
0219 
0220     /// \brief Pretty-print a Proto expression tree.
0221     ///
0222     /// \note Equivalent to <tt>functional::display_expr(0, sout)(expr)</tt>
0223     /// \param expr The Proto expression tree to pretty-print
0224     /// \param sout The \c ostream to which the output should be
0225     ///             written. If not specified, defaults to
0226     ///             <tt>std::cout</tt>.
0227     template<typename Expr>
0228     void display_expr(Expr const &expr, std::ostream &sout)
0229     {
0230         functional::display_expr(sout, 0)(expr);
0231     }
0232 
0233     /// \overload
0234     ///
0235     template<typename Expr>
0236     void display_expr(Expr const &expr)
0237     {
0238         functional::display_expr()(expr);
0239     }
0240 
0241     /// \brief Assert at compile time that a particular expression
0242     ///        matches the specified grammar.
0243     ///
0244     /// \note Equivalent to <tt>BOOST_MPL_ASSERT((proto::matches\<Expr, Grammar\>))</tt>
0245     /// \param expr The Proto expression to check againts <tt>Grammar</tt>
0246     template<typename Grammar, typename Expr>
0247     void assert_matches(Expr const & /*expr*/)
0248     {
0249         BOOST_MPL_ASSERT((proto::matches<Expr, Grammar>));
0250     }
0251 
0252     /// \brief Assert at compile time that a particular expression
0253     ///        does not match the specified grammar.
0254     ///
0255     /// \note Equivalent to <tt>BOOST_MPL_ASSERT_NOT((proto::matches\<Expr, Grammar\>))</tt>
0256     /// \param expr The Proto expression to check againts <tt>Grammar</tt>
0257     template<typename Grammar, typename Expr>
0258     void assert_matches_not(Expr const & /*expr*/)
0259     {
0260         BOOST_MPL_ASSERT_NOT((proto::matches<Expr, Grammar>));
0261     }
0262 
0263     /// \brief Assert at compile time that a particular expression
0264     ///        matches the specified grammar.
0265     ///
0266     /// \note Equivalent to <tt>proto::assert_matches\<Grammar\>(Expr)</tt>
0267     /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
0268     /// \param Grammar The grammar used to validate Expr.
0269     #define BOOST_PROTO_ASSERT_MATCHES(Expr, Grammar)                                               \
0270         (true ? (void)0 : boost::proto::assert_matches<Grammar>(Expr))
0271 
0272     /// \brief Assert at compile time that a particular expression
0273     ///        does not match the specified grammar.
0274     ///
0275     /// \note Equivalent to <tt>proto::assert_matches_not\<Grammar\>(Expr)</tt>
0276     /// \param Expr The Proto expression to check againts <tt>Grammar</tt>
0277     /// \param Grammar The grammar used to validate Expr.
0278     #define BOOST_PROTO_ASSERT_MATCHES_NOT(Expr, Grammar)                                           \
0279         (true ? (void)0 : boost::proto::assert_matches_not<Grammar>(Expr))
0280 
0281 }}
0282 
0283 #endif