1 /*==============================================================================
2 Copyright (c) 2005-2010 Joel de Guzman
3 Copyright (c) 2010 Thomas Heller
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8
9 #include <boost/phoenix/phoenix.hpp>
10 #include <boost/proto/proto.hpp>
11 #include <boost/proto/debug.hpp>
12
13 namespace phoenix = boost::phoenix;
14 namespace proto = boost::proto;
15
16 using phoenix::evaluator;
17
18 #ifdef _MSC_VER
19 // redifining evaluator, this is because MSVC chokes on function types like:
20 // F(G(...))
21 #define evaluator(A0, A1) proto::call<phoenix::evaluator(A0, A1)>
22 #endif
23
24 struct invert_actions
25 {
26 template <typename Rule>
27 struct when
28 : proto::nary_expr<
29 proto::_
30 , proto::vararg<
31 proto::when<proto::_, evaluator(proto::_, phoenix::_context)>
32 >
33 >
34 {};
35 };
36
37 template <>
38 struct invert_actions::when<phoenix::rule::plus>
39 : proto::call<
40 phoenix::functional::make_minus(
41 evaluator(proto::_left, phoenix::_context)
42 , evaluator(proto::_right, phoenix::_context)
43 )
44 >
45 {};
46
47 template <>
48 struct invert_actions::when<phoenix::rule::minus>
49 : proto::call<
50 phoenix::functional::make_plus(
51 evaluator(proto::_left, phoenix::_context)
52 , evaluator(proto::_right, phoenix::_context)
53 )
54 >
55 {};
56
57 template <>
58 struct invert_actions::when<phoenix::rule::multiplies>
59 : proto::call<
60 phoenix::functional::make_divides(
61 evaluator(proto::_left, phoenix::_context)
62 , evaluator(proto::_right, phoenix::_context)
63 )
64 >
65 {};
66
67 template <>
68 struct invert_actions::when<phoenix::rule::divides>
69 : proto::call<
70 phoenix::functional::make_multiplies(
71 evaluator(proto::_left, phoenix::_context)
72 , evaluator(proto::_right, phoenix::_context)
73 )
74 >
75 {};
76
77 #ifdef _MSC_VER
78 #undef evaluator
79 #endif
80
81 template <typename Expr>
print_expr(Expr const & expr)82 void print_expr(Expr const & expr)
83 {
84 std::cout << "before inversion:\n";
85 proto::display_expr(expr);
86 std::cout << "after inversion:\n";
87 proto::display_expr(
88 phoenix::eval(
89 expr
90 , phoenix::context(
91 phoenix::nothing
92 , invert_actions()
93 )
94 )
95 );
96 std::cout << "\n";
97 }
98
99 template <typename Expr>
100 typename
101 boost::phoenix::result_of::eval<
102 Expr const&
103 , phoenix::result_of::make_context<
104 phoenix::result_of::make_env<>::type
105 , invert_actions
106 >::type
107 >::type
invert(Expr const & expr)108 invert(Expr const & expr)
109 {
110 return
111 phoenix::eval(
112 expr
113 , phoenix::make_context(
114 phoenix::make_env()
115 , invert_actions()
116 )
117 );
118 }
119
main()120 int main()
121 {
122 using phoenix::placeholders::_1;
123 using phoenix::placeholders::_2;
124 using phoenix::placeholders::_3;
125 using phoenix::placeholders::_4;
126
127 print_expr(_1);
128 print_expr(_1 + _2);
129 print_expr(_1 + _2 - _3);
130 print_expr(_1 * _2);
131 print_expr(_1 * _2 / _3);
132 print_expr(_1 * _2 + _3);
133 print_expr(_1 * _2 - _3);
134 print_expr(if_(_1 * _4)[_2 - _3]);
135
136 print_expr(_1 * invert(_2 - _3));
137 }
138
139