139 lines
3.3 KiB
C++
139 lines
3.3 KiB
C++
/*==============================================================================
|
|
Copyright (c) 2005-2010 Joel de Guzman
|
|
Copyright (c) 2010 Thomas Heller
|
|
|
|
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)
|
|
==============================================================================*/
|
|
|
|
#include <boost/phoenix/phoenix.hpp>
|
|
#include <boost/proto/proto.hpp>
|
|
#include <boost/proto/debug.hpp>
|
|
|
|
namespace phoenix = boost::phoenix;
|
|
namespace proto = boost::proto;
|
|
|
|
using phoenix::evaluator;
|
|
|
|
#ifdef _MSC_VER
|
|
// redifining evaluator, this is because MSVC chokes on function types like:
|
|
// F(G(...))
|
|
#define evaluator(A0, A1) proto::call<phoenix::evaluator(A0, A1)>
|
|
#endif
|
|
|
|
struct invert_actions
|
|
{
|
|
template <typename Rule>
|
|
struct when
|
|
: proto::nary_expr<
|
|
proto::_
|
|
, proto::vararg<
|
|
proto::when<proto::_, evaluator(proto::_, phoenix::_context)>
|
|
>
|
|
>
|
|
{};
|
|
};
|
|
|
|
template <>
|
|
struct invert_actions::when<phoenix::rule::plus>
|
|
: proto::call<
|
|
phoenix::functional::make_minus(
|
|
evaluator(proto::_left, phoenix::_context)
|
|
, evaluator(proto::_right, phoenix::_context)
|
|
)
|
|
>
|
|
{};
|
|
|
|
template <>
|
|
struct invert_actions::when<phoenix::rule::minus>
|
|
: proto::call<
|
|
phoenix::functional::make_plus(
|
|
evaluator(proto::_left, phoenix::_context)
|
|
, evaluator(proto::_right, phoenix::_context)
|
|
)
|
|
>
|
|
{};
|
|
|
|
template <>
|
|
struct invert_actions::when<phoenix::rule::multiplies>
|
|
: proto::call<
|
|
phoenix::functional::make_divides(
|
|
evaluator(proto::_left, phoenix::_context)
|
|
, evaluator(proto::_right, phoenix::_context)
|
|
)
|
|
>
|
|
{};
|
|
|
|
template <>
|
|
struct invert_actions::when<phoenix::rule::divides>
|
|
: proto::call<
|
|
phoenix::functional::make_multiplies(
|
|
evaluator(proto::_left, phoenix::_context)
|
|
, evaluator(proto::_right, phoenix::_context)
|
|
)
|
|
>
|
|
{};
|
|
|
|
#ifdef _MSC_VER
|
|
#undef evaluator
|
|
#endif
|
|
|
|
template <typename Expr>
|
|
void print_expr(Expr const & expr)
|
|
{
|
|
std::cout << "before inversion:\n";
|
|
proto::display_expr(expr);
|
|
std::cout << "after inversion:\n";
|
|
proto::display_expr(
|
|
phoenix::eval(
|
|
expr
|
|
, phoenix::context(
|
|
phoenix::nothing
|
|
, invert_actions()
|
|
)
|
|
)
|
|
);
|
|
std::cout << "\n";
|
|
}
|
|
|
|
template <typename Expr>
|
|
typename
|
|
boost::phoenix::result_of::eval<
|
|
Expr const&
|
|
, phoenix::result_of::make_context<
|
|
phoenix::result_of::make_env<>::type
|
|
, invert_actions
|
|
>::type
|
|
>::type
|
|
invert(Expr const & expr)
|
|
{
|
|
return
|
|
phoenix::eval(
|
|
expr
|
|
, phoenix::make_context(
|
|
phoenix::make_env()
|
|
, invert_actions()
|
|
)
|
|
);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
using phoenix::placeholders::_1;
|
|
using phoenix::placeholders::_2;
|
|
using phoenix::placeholders::_3;
|
|
using phoenix::placeholders::_4;
|
|
|
|
print_expr(_1);
|
|
print_expr(_1 + _2);
|
|
print_expr(_1 + _2 - _3);
|
|
print_expr(_1 * _2);
|
|
print_expr(_1 * _2 / _3);
|
|
print_expr(_1 * _2 + _3);
|
|
print_expr(_1 * _2 - _3);
|
|
print_expr(if_(_1 * _4)[_2 - _3]);
|
|
|
|
print_expr(_1 * invert(_2 - _3));
|
|
}
|
|
|