1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // calculator.hpp |
3 | // |
4 | // Copyright 2008 Eric Niebler. Distributed under the Boost |
5 | // Software License, Version 1.0. (See accompanying file |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #include <boost/proto/core.hpp> |
9 | #include <boost/proto/context.hpp> |
10 | #include <boost/test/unit_test.hpp> |
11 | |
12 | using namespace boost; |
13 | |
14 | struct placeholder {}; |
15 | proto::terminal<placeholder>::type const _1 = {.child0: {}}; |
16 | |
17 | struct calculator : proto::callable_context<calculator const> |
18 | { |
19 | typedef int result_type; |
20 | |
21 | calculator(int i) |
22 | : i_(i) |
23 | {} |
24 | |
25 | int operator ()(proto::tag::terminal, placeholder) const |
26 | { |
27 | return this->i_; |
28 | } |
29 | |
30 | int operator ()(proto::tag::terminal, int j) const |
31 | { |
32 | return j; |
33 | } |
34 | |
35 | template<typename Left, typename Right> |
36 | int operator ()(proto::tag::plus, Left const &left, Right const &right) const |
37 | { |
38 | return proto::eval(left, *this) + proto::eval(right, *this); |
39 | } |
40 | |
41 | template<typename Left, typename Right> |
42 | int operator ()(proto::tag::minus, Left const &left, Right const &right) const |
43 | { |
44 | return proto::eval(left, *this) - proto::eval(right, *this); |
45 | } |
46 | |
47 | template<typename Left, typename Right> |
48 | int operator ()(proto::tag::multiplies, Left const &left, Right const &right) const |
49 | { |
50 | return proto::eval(left, *this) * proto::eval(right, *this); |
51 | } |
52 | |
53 | template<typename Left, typename Right> |
54 | int operator ()(proto::tag::divides, Left const &left, Right const &right) const |
55 | { |
56 | return proto::eval(left, *this) / proto::eval(right, *this); |
57 | } |
58 | |
59 | private: |
60 | int i_; |
61 | }; |
62 | |
63 | template<typename Fun, typename Expr> |
64 | struct functional |
65 | { |
66 | typedef typename proto::result_of::eval<Expr, Fun>::type result_type; |
67 | |
68 | functional(Expr const &expr) |
69 | : expr_(expr) |
70 | {} |
71 | |
72 | template<typename T> |
73 | result_type operator ()(T const &t) const |
74 | { |
75 | Fun fun(t); |
76 | return proto::eval(this->expr_, fun); |
77 | } |
78 | |
79 | private: |
80 | Expr const &expr_; |
81 | }; |
82 | |
83 | template<typename Fun, typename Expr> |
84 | functional<Fun, Expr> as(Expr const &expr) |
85 | { |
86 | return functional<Fun, Expr>(expr); |
87 | } |
88 | |
89 | void test_calculator() |
90 | { |
91 | BOOST_CHECK_EQUAL(10, proto::eval(((_1 + 42)-3)/4, calculator(1))); |
92 | BOOST_CHECK_EQUAL(11, proto::eval(((_1 + 42)-3)/4, calculator(5))); |
93 | |
94 | BOOST_CHECK_EQUAL(10, as<calculator>(((_1 + 42)-3)/4)(1)); |
95 | BOOST_CHECK_EQUAL(11, as<calculator>(((_1 + 42)-3)/4)(5)); |
96 | } |
97 | |
98 | using namespace unit_test; |
99 | /////////////////////////////////////////////////////////////////////////////// |
100 | // init_unit_test_suite |
101 | // |
102 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
103 | { |
104 | test_suite *test = BOOST_TEST_SUITE("test immediate evaluation of proto parse trees" ); |
105 | |
106 | test->add(BOOST_TEST_CASE(&test_calculator)); |
107 | |
108 | return test; |
109 | } |
110 | |