• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <sstream>
11 
12 
13 template<typename T>
14 using term = boost::yap::terminal<boost::yap::expression, T>;
15 
16 template<typename T>
17 using ref = boost::yap::expression_ref<boost::yap::expression, T>;
18 
19 namespace yap = boost::yap;
20 namespace bh = boost::hana;
21 
22 
23 namespace user {
24 
25     struct number
26     {
operator doubleuser::number27         explicit operator double() const { return value; }
28 
29         double value;
30     };
31 
naxpy(number a,number x,number y)32     number naxpy(number a, number x, number y)
33     {
34         return number{a.value * x.value + y.value + 10.0};
35     }
36 
37     struct tag_type
38     {};
39 
tag_function(double a,double b)40     inline number tag_function(double a, double b) { return number{a + b}; }
41 
42     struct eval_xform_tag
43     {
operator ()user::eval_xform_tag44         decltype(auto) operator()(
45             yap::expr_tag<yap::expr_kind::call>, tag_type, number a, double b)
46         {
47             return tag_function(a.value, b);
48         }
49 
operator ()user::eval_xform_tag50         int operator()(
51             yap::expr_tag<yap::expr_kind::call>, tag_type, double a, double b)
52         {
53             return 42;
54         }
55 
operator ()user::eval_xform_tag56         char const * operator()() { return "42"; }
57     };
58 
59     struct empty_xform
60     {};
61 
62     struct eval_xform_expr
63     {
operator ()user::eval_xform_expr64         decltype(auto) operator()(yap::expression<
65                                   yap::expr_kind::call,
66                                   bh::tuple<
67                                       ref<term<user::tag_type>>,
68                                       term<user::number>,
69                                       term<int>>> const & expr)
70         {
71             using namespace boost::hana::literals;
72             return tag_function(
73                 (double)yap::value(expr.elements[1_c]).value,
74                 (double)yap::value(expr.elements[2_c]));
75         }
76 
operator ()user::eval_xform_expr77         decltype(auto) operator()(yap::expression<
78                                   yap::expr_kind::call,
79                                   bh::tuple<
80                                       ref<term<user::tag_type>>,
81                                       ref<term<user::number>>,
82                                       term<int>>> const & expr)
83         {
84             using namespace boost::hana::literals;
85             return tag_function(
86                 (double)yap::value(expr.elements[1_c]).value,
87                 (double)yap::value(expr.elements[2_c]));
88         }
89     };
90 
91     struct eval_xform_both
92     {
operator ()user::eval_xform_both93         decltype(auto) operator()(
94             yap::expr_tag<yap::expr_kind::call>,
95             tag_type,
96             user::number a,
97             double b)
98         {
99             return tag_function(a.value, b);
100         }
101 
operator ()user::eval_xform_both102         decltype(auto) operator()(yap::expression<
103                                   yap::expr_kind::call,
104                                   bh::tuple<
105                                       ref<term<user::tag_type>>,
106                                       term<user::number>,
107                                       term<int>>> const & expr)
108         {
109             using namespace boost::hana::literals;
110             throw std::logic_error("Oops!  Picked the wrong overload!");
111             return tag_function(
112                 (double)yap::value(expr.elements[1_c]).value,
113                 (double)yap::value(expr.elements[2_c]));
114         }
115 
operator ()user::eval_xform_both116         decltype(auto) operator()(yap::expression<
117                                   yap::expr_kind::call,
118                                   bh::tuple<
119                                       ref<term<user::tag_type>>,
120                                       ref<term<user::number>>,
121                                       term<int>>> const & expr)
122         {
123             using namespace boost::hana::literals;
124             throw std::logic_error("Oops!  Picked the wrong overload!");
125             return tag_function(
126                 (double)yap::value(expr.elements[1_c]).value,
127                 (double)yap::value(expr.elements[2_c]));
128         }
129     };
130 }
131 
132 
test_main(int,char * [])133 int test_main(int, char * [])
134 {
135     {
136         using namespace boost::yap::literals;
137 
138         {
139             auto plus = yap::make_terminal(user::tag_type{});
140             auto expr = plus(user::number{13}, 1);
141 
142             {
143                 transform(expr, user::empty_xform{});
144             }
145 
146             {
147                 user::number result = transform(expr, user::eval_xform_tag{});
148                 BOOST_CHECK(result.value == 14);
149             }
150 
151             {
152                 user::number result = transform(expr, user::eval_xform_expr{});
153                 BOOST_CHECK(result.value == 14);
154             }
155 
156             {
157                 user::number result = transform(expr, user::eval_xform_both{});
158                 BOOST_CHECK(result.value == 14);
159             }
160         }
161 
162         {
163             auto plus = yap::make_terminal(user::tag_type{});
164             auto thirteen = yap::make_terminal(user::number{13});
165             auto expr = plus(thirteen, 1);
166 
167             {
168                 user::number result = transform(expr, user::eval_xform_tag{});
169                 BOOST_CHECK(result.value == 14);
170             }
171 
172             {
173                 user::number result = transform(expr, user::eval_xform_expr{});
174                 BOOST_CHECK(result.value == 14);
175             }
176 
177             {
178                 user::number result = transform(expr, user::eval_xform_both{});
179                 BOOST_CHECK(result.value == 14);
180             }
181         }
182 
183         {
184             term<user::number> a{{1.0}};
185             term<user::number> x{{42.0}};
186             term<user::number> y{{3.0}};
187             auto n = yap::make_terminal(user::naxpy);
188 
189             auto expr = n(a, x, y);
190             {
191                 user::number result = evaluate(expr);
192                 BOOST_CHECK(result.value == 55);
193             }
194         }
195     }
196 
197     return 0;
198 }
199