1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/yap/expression.hpp>
7
8 #include <boost/test/minimal.hpp>
9
10
11 template<typename T>
12 using term = boost::yap::terminal<boost::yap::expression, T>;
13
14 template<typename T>
15 using ref = boost::yap::expression_ref<boost::yap::expression, T>;
16
17 namespace yap = boost::yap;
18 namespace bh = boost::hana;
19
20
21 namespace user {
22
23 struct number
24 {
25 double value;
26 };
27
28 struct eval_xform
29 {
30 auto
operator ()user::eval_xform31 operator()(yap::expr_tag<yap::expr_kind::terminal>, number const & n)
32 {
33 return n;
34 }
35
36 template<typename Expr>
operator ()user::eval_xform37 decltype(auto) operator()(
38 yap::expression<yap::expr_kind::negate, bh::tuple<Expr>> const &
39 expr)
40 {
41 number const n = transform(yap::value(expr), *this);
42 return number{-n.value};
43 }
44
45 template<typename Expr1, typename Expr2>
operator ()user::eval_xform46 decltype(auto) operator()(yap::expression<
47 yap::expr_kind::plus,
48 bh::tuple<Expr1, Expr2>> const & expr)
49 {
50 number const lhs = transform(yap::left(expr), *this);
51 number const rhs = transform(yap::right(expr), *this);
52 return number{lhs.value + rhs.value};
53 }
54 };
55 }
56
57 template<typename Expr>
make_ref(Expr && expr)58 auto make_ref(Expr && expr)
59 {
60 using type = yap::detail::operand_type_t<yap::expression, Expr>;
61 return yap::detail::make_operand<type>{}(static_cast<Expr &&>(expr));
62 }
63
test_main(int,char * [])64 int test_main(int, char * [])
65 {
66 {
67 {
68 term<user::number> a{{1.0}};
69
70 {
71 user::number result = transform(a, user::eval_xform{});
72 BOOST_CHECK(result.value == 1);
73 }
74
75 {
76 user::number result = transform(make_ref(a), user::eval_xform{});
77 BOOST_CHECK(result.value == 1);
78 }
79
80 {
81 user::number result = transform(-a, user::eval_xform{});
82 BOOST_CHECK(result.value == -1);
83 }
84
85 {
86 auto expr = make_ref(a);
87 user::number result = transform(-expr, user::eval_xform{});
88 BOOST_CHECK(result.value == -1);
89 }
90
91 {
92 auto expr = -a;
93 user::number result = transform(expr, user::eval_xform{});
94 BOOST_CHECK(result.value == -1);
95 }
96
97 {
98 auto expr1 = make_ref(a);
99 auto expr2 = make_ref(expr1);
100 user::number result = transform(expr2, user::eval_xform{});
101 BOOST_CHECK(result.value == 1);
102 }
103
104 {
105 auto expr1 = -a;
106 auto expr2 = make_ref(expr1);
107 user::number result = transform(expr2, user::eval_xform{});
108 BOOST_CHECK(result.value == -1);
109 }
110
111 {
112 auto expr1 = make_ref(a);
113 auto expr2 = -expr1;
114 user::number result = transform(expr2, user::eval_xform{});
115 BOOST_CHECK(result.value == -1);
116 }
117
118 {
119 auto expr1 = a;
120 auto expr2 = make_ref(expr1);
121 auto expr3 = make_ref(expr2);
122 user::number result = transform(expr3, user::eval_xform{});
123 BOOST_CHECK(result.value == 1);
124 }
125
126 {
127 auto expr1 = -a;
128 auto expr2 = make_ref(expr1);
129 auto expr3 = make_ref(expr2);
130 user::number result = transform(expr3, user::eval_xform{});
131 BOOST_CHECK(result.value == -1);
132 }
133
134 {
135 auto expr1 = make_ref(a);
136 auto expr2 = -expr1;
137 auto expr3 = make_ref(expr2);
138 user::number result = transform(expr3, user::eval_xform{});
139 BOOST_CHECK(result.value == -1);
140 }
141
142 {
143 auto expr1 = make_ref(a);
144 auto expr2 = make_ref(expr1);
145 auto expr3 = -expr2;
146 user::number result = transform(expr3, user::eval_xform{});
147 BOOST_CHECK(result.value == -1);
148 }
149 }
150
151 {
152 user::number result =
153 transform(-term<user::number>{{1.0}}, user::eval_xform{});
154 BOOST_CHECK(result.value == -1);
155 }
156 }
157
158 {
159 term<user::number> a{{1.0}};
160 term<user::number> x{{41.0}};
161
162 {
163 user::number result = transform(a + x, user::eval_xform{});
164 BOOST_CHECK(result.value == 42);
165 }
166
167
168 {
169 user::number result =
170 transform(make_ref(a) + make_ref(x), user::eval_xform{});
171 BOOST_CHECK(result.value == 42);
172 }
173
174 {
175 user::number result = transform(make_ref(a) + x, user::eval_xform{});
176 BOOST_CHECK(result.value == 42);
177 }
178
179 {
180 user::number result = transform(a + make_ref(x), user::eval_xform{});
181 BOOST_CHECK(result.value == 42);
182 }
183
184 {
185 user::number result = transform(a + x, user::eval_xform{});
186 BOOST_CHECK(result.value == 42);
187 }
188
189
190 {
191 user::number result =
192 transform(-make_ref(a) + make_ref(x), user::eval_xform{});
193 BOOST_CHECK(result.value == 40);
194 }
195
196 {
197 user::number result = transform(-make_ref(a) + x, user::eval_xform{});
198 BOOST_CHECK(result.value == 40);
199 }
200
201 {
202 user::number result = transform(-a + make_ref(x), user::eval_xform{});
203 BOOST_CHECK(result.value == 40);
204 }
205
206 {
207 user::number result = transform(-a + x, user::eval_xform{});
208 BOOST_CHECK(result.value == 40);
209 }
210
211
212 {
213 user::number result =
214 transform(make_ref(a) + -make_ref(x), user::eval_xform{});
215 BOOST_CHECK(result.value == -40);
216 }
217
218 {
219 user::number result = transform(make_ref(a) + -x, user::eval_xform{});
220 BOOST_CHECK(result.value == -40);
221 }
222
223 {
224 user::number result = transform(a + -make_ref(x), user::eval_xform{});
225 BOOST_CHECK(result.value == -40);
226 }
227
228 {
229 user::number result = transform(a + -x, user::eval_xform{});
230 BOOST_CHECK(result.value == -40);
231 }
232
233
234 {
235 user::number result =
236 transform(-make_ref(a) + -make_ref(x), user::eval_xform{});
237 BOOST_CHECK(result.value == -42);
238 }
239
240 {
241 user::number result = transform(-make_ref(a) + -x, user::eval_xform{});
242 BOOST_CHECK(result.value == -42);
243 }
244
245 {
246 user::number result = transform(-a + -make_ref(x), user::eval_xform{});
247 BOOST_CHECK(result.value == -42);
248 }
249
250 {
251 user::number result = transform(-a + -x, user::eval_xform{});
252 BOOST_CHECK(result.value == -42);
253 }
254 }
255
256 return 0;
257 }
258