123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /*==============================================================================
- 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));
- }
|