You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
264 lines
9.9 KiB
264 lines
9.9 KiB
/////////////////////////////////////////////////////////////////////////////// |
|
/// \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_; |
|
}; |
|
|
|
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
|
|
|