• 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 //[ transform_terminals
7 #include <boost/yap/yap.hpp>
8 
9 
10 struct iota_terminal_transform
11 {
12     // Base case. Note that we're not treating placeholders specially for this
13     // example (they're easy to special-case if necessary).
14     template<typename T>
operator ()iota_terminal_transform15     auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::terminal>, T && t)
16     {
17         // Like the std::iota() algorithm, we create replacement int terminals
18         // with the values index_, index_ + 1, index_ + 2, etc.
19         return boost::yap::make_terminal(index_++);
20     }
21 
22     // Recursive case: Match any call expression.
23     template<typename CallableExpr, typename... Arg>
operator ()iota_terminal_transform24     auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::call>,
25                     CallableExpr callable, Arg &&... arg)
26     {
27         // Even though the callable in a call expression is technically a
28         // terminal, it doesn't make a lot of sense to replace it with an int,
29         // so we'll only transform the argument subexpressions.
30         return boost::yap::make_expression<boost::yap::expr_kind::call>(
31             boost::yap::as_expr(callable),
32             boost::yap::transform(boost::yap::as_expr(arg), *this)...);
33     }
34 
35     int index_;
36 };
37 
sum(int a,int b)38 int sum(int a, int b) { return a + b; }
39 
main()40 int main()
41 {
42     {
43         // This simple sum(8, 8) expression requires both overloads of
44         // iota_terminal_transform.
45         auto expr = boost::yap::make_terminal(sum)(8, 8);
46         assert(evaluate(expr) == 16);
47 
48         auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{1});
49         assert(evaluate(iota_expr) == 3);
50     }
51 
52     {
53         // This expression requires only the terminal case of
54         // iota_terminal_transform.
55         auto expr = -(boost::yap::make_terminal(8) + 8);
56         assert(evaluate(expr) == -16);
57 
58         auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{0});
59         assert(evaluate(iota_expr) == -1);
60     }
61 
62     {
63         // Like the first expression above, this expression requires both
64         // overloads of iota_terminal_transform.
65         auto expr = boost::yap::make_terminal(sum)(-(boost::yap::make_terminal(8) + 8), 0);
66         assert(evaluate(expr) == -16);
67 
68         auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{0});
69         assert(evaluate(iota_expr) == -3);
70     }
71 }
72 //]
73