• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = {{}};
16 
17 struct calculator : proto::callable_context<calculator const>
18 {
19     typedef int result_type;
20 
calculatorcalculator21     calculator(int i)
22       : i_(i)
23     {}
24 
operator ()calculator25     int operator ()(proto::tag::terminal, placeholder) const
26     {
27         return this->i_;
28     }
29 
operator ()calculator30     int operator ()(proto::tag::terminal, int j) const
31     {
32         return j;
33     }
34 
35     template<typename Left, typename Right>
operator ()calculator36     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>
operator ()calculator42     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>
operator ()calculator48     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>
operator ()calculator54     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 
functionalfunctional68     functional(Expr const &expr)
69       : expr_(expr)
70     {}
71 
72     template<typename T>
operator ()functional73     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>
as(Expr const & expr)84 functional<Fun, Expr> as(Expr const &expr)
85 {
86     return functional<Fun, Expr>(expr);
87 }
88 
test_calculator()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 //
init_unit_test_suite(int argc,char * argv[])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