Chris@16
|
1 /*==============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2010 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2004 Daniel Wallin
|
Chris@16
|
4 Copyright (c) 2010 Thomas Heller
|
Chris@101
|
5 Copyright (c) 2015 John Fletcher
|
Chris@16
|
6
|
Chris@16
|
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 ==============================================================================*/
|
Chris@16
|
10 #ifndef BOOST_PHOENIX_SCOPE_LET_HPP
|
Chris@16
|
11 #define BOOST_PHOENIX_SCOPE_LET_HPP
|
Chris@16
|
12
|
Chris@101
|
13 //#include <boost/assert.hpp>
|
Chris@101
|
14 //#include <sstream>
|
Chris@16
|
15 #include <boost/phoenix/core/limits.hpp>
|
Chris@16
|
16 #include <boost/fusion/include/transform.hpp>
|
Chris@16
|
17 #include <boost/fusion/include/as_vector.hpp>
|
Chris@16
|
18 #include <boost/phoenix/core/call.hpp>
|
Chris@16
|
19 #include <boost/phoenix/core/expression.hpp>
|
Chris@16
|
20 #include <boost/phoenix/core/meta_grammar.hpp>
|
Chris@16
|
21 #include <boost/phoenix/scope/scoped_environment.hpp>
|
Chris@16
|
22 #include <boost/phoenix/scope/local_variable.hpp>
|
Chris@16
|
23 #include <boost/phoenix/support/iterate.hpp>
|
Chris@16
|
24 #include <boost/phoenix/support/vector.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 BOOST_PHOENIX_DEFINE_EXPRESSION(
|
Chris@16
|
27 (boost)(phoenix)(let_)
|
Chris@16
|
28 , (proto::terminal<proto::_>) // Locals
|
Chris@16
|
29 (proto::terminal<proto::_>) // Map
|
Chris@16
|
30 (meta_grammar)
|
Chris@16
|
31 )
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost { namespace phoenix
|
Chris@16
|
34 {
|
Chris@16
|
35 struct let_eval
|
Chris@16
|
36 {
|
Chris@16
|
37 template <typename Sig>
|
Chris@16
|
38 struct result;
|
Chris@16
|
39
|
Chris@16
|
40 template <typename This, typename Vars, typename Map, typename Expr, typename Context>
|
Chris@16
|
41 struct result<This(Vars, Map, Expr, Context)>
|
Chris@16
|
42 {
|
Chris@16
|
43 typedef
|
Chris@16
|
44 typename proto::detail::uncvref<
|
Chris@16
|
45 typename result_of::env<Context>::type
|
Chris@16
|
46 >::type
|
Chris@16
|
47 env_type;
|
Chris@16
|
48 typedef
|
Chris@16
|
49 typename proto::detail::uncvref<
|
Chris@16
|
50 typename result_of::actions<Context>::type
|
Chris@16
|
51 >::type
|
Chris@16
|
52 actions_type;
|
Chris@16
|
53 typedef
|
Chris@16
|
54 typename proto::detail::uncvref<
|
Chris@16
|
55 typename proto::result_of::value<Vars>::type
|
Chris@16
|
56 >::type
|
Chris@16
|
57 vars_type;
|
Chris@16
|
58 typedef
|
Chris@16
|
59 typename proto::detail::uncvref<
|
Chris@16
|
60 typename proto::result_of::value<Map>::type
|
Chris@16
|
61 >::type
|
Chris@16
|
62 map_type;
|
Chris@101
|
63
|
Chris@101
|
64 typedef
|
Chris@101
|
65 typename proto::detail::uncvref<Expr>::type
|
Chris@101
|
66 expr_type;
|
Chris@16
|
67
|
Chris@101
|
68 typedef typename
|
Chris@16
|
69 detail::result_of::initialize_locals<
|
Chris@16
|
70 vars_type
|
Chris@16
|
71 , Context
|
Chris@16
|
72 >::type
|
Chris@16
|
73 locals_type;
|
Chris@16
|
74
|
Chris@16
|
75 typedef typename
|
Chris@16
|
76 result_of::eval<
|
Chris@101
|
77 expr_type
|
Chris@16
|
78 , typename result_of::context<
|
Chris@16
|
79 scoped_environment<
|
Chris@16
|
80 env_type
|
Chris@16
|
81 , env_type
|
Chris@16
|
82 , locals_type
|
Chris@16
|
83 , map_type
|
Chris@16
|
84 >
|
Chris@16
|
85 , actions_type
|
Chris@16
|
86 >::type
|
Chris@16
|
87 >::type
|
Chris@16
|
88 type;
|
Chris@16
|
89 };
|
Chris@16
|
90
|
Chris@16
|
91 template <typename Vars, typename Map, typename Expr, typename Context>
|
Chris@16
|
92 typename result<let_eval(Vars const&, Map const&, Expr const &, Context const &)>::type const
|
Chris@16
|
93 operator()(Vars const & vars, Map, Expr const & expr, Context const & ctx) const
|
Chris@16
|
94 {
|
Chris@101
|
95 Vars vars_(vars);
|
Chris@101
|
96
|
Chris@16
|
97 typedef
|
Chris@16
|
98 typename proto::detail::uncvref<
|
Chris@16
|
99 typename result_of::env<Context>::type
|
Chris@16
|
100 >::type
|
Chris@16
|
101 env_type;
|
Chris@16
|
102 typedef
|
Chris@16
|
103 typename proto::detail::uncvref<
|
Chris@16
|
104 typename proto::result_of::value<Vars>::type
|
Chris@16
|
105 >::type
|
Chris@16
|
106 vars_type;
|
Chris@16
|
107 typedef
|
Chris@16
|
108 typename proto::detail::uncvref<
|
Chris@16
|
109 typename proto::result_of::value<Map>::type
|
Chris@16
|
110 >::type
|
Chris@16
|
111 map_type;
|
Chris@16
|
112
|
Chris@16
|
113 typedef typename
|
Chris@16
|
114 detail::result_of::initialize_locals<
|
Chris@16
|
115 vars_type
|
Chris@16
|
116 , Context
|
Chris@16
|
117 >::type
|
Chris@16
|
118 locals_type;
|
Chris@16
|
119
|
Chris@101
|
120 locals_type locals = initialize_locals(proto::value(vars_), ctx);
|
Chris@101
|
121
|
Chris@101
|
122 typedef typename result<let_eval(Vars const&, Map const&, Expr const &, Context const &)>::type result_type;
|
Chris@16
|
123
|
Chris@16
|
124 scoped_environment<
|
Chris@16
|
125 env_type
|
Chris@16
|
126 , env_type
|
Chris@16
|
127 , locals_type
|
Chris@16
|
128 , map_type
|
Chris@16
|
129 >
|
Chris@16
|
130 env(phoenix::env(ctx), phoenix::env(ctx), locals);
|
Chris@16
|
131
|
Chris@101
|
132 // Fix for bugs (trial)
|
Chris@101
|
133 // The idea is to do something which will not be optimised away.
|
Chris@101
|
134 //int vsize = boost::fusion::size(vars);
|
Chris@101
|
135 //std::stringstream strm;
|
Chris@101
|
136 //strm << vsize << std::endl;
|
Chris@101
|
137 //int size = strm.str().length();
|
Chris@101
|
138 //BOOST_ASSERT(size >= 0);
|
Chris@101
|
139 result_type r = eval(expr, phoenix::context(env, phoenix::actions(ctx)));
|
Chris@101
|
140 // typedef is_value<result_type> is_val;
|
Chris@101
|
141 //if(is_val::value) This seems always to be true
|
Chris@101
|
142 //{
|
Chris@101
|
143 // std::cout << "let result has value type" << std::endl;
|
Chris@101
|
144 // }
|
Chris@101
|
145 //if (is_val(r) ) std::cout << "let returns val" << std::endl;
|
Chris@101
|
146 //std::cout << "result is " << r << std::endl;
|
Chris@101
|
147 return r;
|
Chris@16
|
148 }
|
Chris@16
|
149 };
|
Chris@16
|
150
|
Chris@16
|
151 template <typename Dummy>
|
Chris@16
|
152 struct default_actions::when<rule::let_, Dummy>
|
Chris@16
|
153 : call<let_eval, Dummy>
|
Chris@16
|
154 {};
|
Chris@16
|
155
|
Chris@16
|
156 template <typename Locals, typename Map>
|
Chris@16
|
157 struct let_actor_gen
|
Chris@16
|
158 {
|
Chris@101
|
159 let_actor_gen(Locals const & locals_)
|
Chris@101
|
160 : locals(locals_)
|
Chris@16
|
161 {}
|
Chris@16
|
162
|
Chris@16
|
163 let_actor_gen(let_actor_gen const & o)
|
Chris@16
|
164 : locals(o.locals)
|
Chris@16
|
165 {}
|
Chris@16
|
166
|
Chris@16
|
167 template <typename Expr>
|
Chris@16
|
168 typename expression::let_<
|
Chris@16
|
169 Locals
|
Chris@16
|
170 , Map
|
Chris@16
|
171 , Expr
|
Chris@16
|
172 >::type const
|
Chris@16
|
173 operator[](Expr const & expr) const
|
Chris@16
|
174 {
|
Chris@101
|
175 typedef typename expression::let_<
|
Chris@101
|
176 Locals
|
Chris@101
|
177 , Map
|
Chris@101
|
178 , Expr
|
Chris@101
|
179 >::type let_type;
|
Chris@101
|
180 //typedef is_value<let_type> is_val;
|
Chris@101
|
181
|
Chris@101
|
182 let_type let_exp = expression::let_<Locals, Map, Expr>::make(locals, Map(), expr);
|
Chris@101
|
183 //if(is_val::value) //This seems always to be true
|
Chris@101
|
184 //{
|
Chris@101
|
185 // std::cout << "let has value type" << std::endl;
|
Chris@101
|
186 //}
|
Chris@101
|
187 return let_exp;
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 Locals locals;
|
Chris@16
|
191 };
|
Chris@16
|
192
|
Chris@16
|
193 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_NAME let_actor_gen
|
Chris@16
|
194 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_FUNCTION let
|
Chris@16
|
195 #define BOOST_PHOENIX_SCOPE_ACTOR_GEN_CONST
|
Chris@16
|
196 #include <boost/phoenix/scope/detail/local_gen.hpp>
|
Chris@16
|
197 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_NAME
|
Chris@16
|
198 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_FUNCTION
|
Chris@16
|
199 #undef BOOST_PHOENIX_SCOPE_ACTOR_GEN_CONST
|
Chris@16
|
200
|
Chris@16
|
201 template <typename Dummy>
|
Chris@16
|
202 struct is_nullary::when<rule::let_, Dummy>
|
Chris@16
|
203 : proto::make<
|
Chris@16
|
204 mpl::and_<
|
Chris@16
|
205 proto::fold<
|
Chris@16
|
206 proto::call<proto::_value(proto::_child_c<0>)>
|
Chris@16
|
207 , proto::make<mpl::true_()>
|
Chris@16
|
208 , proto::make<
|
Chris@16
|
209 mpl::and_<
|
Chris@16
|
210 proto::_state
|
Chris@16
|
211 , proto::call<
|
Chris@16
|
212 evaluator(
|
Chris@16
|
213 proto::_
|
Chris@16
|
214 , _context
|
Chris@16
|
215 , proto::make<proto::empty_env()>
|
Chris@16
|
216 )
|
Chris@16
|
217 >
|
Chris@16
|
218 >()
|
Chris@16
|
219 >
|
Chris@16
|
220 >
|
Chris@16
|
221 , evaluator(
|
Chris@16
|
222 proto::_child_c<2>
|
Chris@16
|
223 , proto::call<
|
Chris@16
|
224 functional::context(
|
Chris@16
|
225 proto::make<
|
Chris@16
|
226 mpl::true_()
|
Chris@16
|
227 >
|
Chris@16
|
228 , proto::make<
|
Chris@16
|
229 detail::scope_is_nullary_actions()
|
Chris@16
|
230 >
|
Chris@16
|
231 )
|
Chris@16
|
232 >
|
Chris@16
|
233 , proto::make<
|
Chris@16
|
234 proto::empty_env()
|
Chris@16
|
235 >
|
Chris@16
|
236 )
|
Chris@16
|
237 >()
|
Chris@16
|
238 >
|
Chris@16
|
239 {};
|
Chris@16
|
240 }}
|
Chris@16
|
241
|
Chris@16
|
242 #endif
|