]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2005-2010 Joel de Guzman | |
3 | Copyright (c) 2010 Eric Niebler | |
4 | Copyright (c) 2010 Thomas Heller | |
5 | Copyright (c) 2014 John Fletcher | |
6 | ||
7 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | ==============================================================================*/ | |
10 | #ifndef BOOST_PHOENIX_CORE_ACTOR_HPP | |
11 | #define BOOST_PHOENIX_CORE_ACTOR_HPP | |
12 | ||
13 | #include <boost/phoenix/core/limits.hpp> | |
14 | ||
15 | #include <boost/is_placeholder.hpp> | |
16 | #include <boost/mpl/identity.hpp> | |
17 | #include <boost/mpl/eval_if.hpp> | |
18 | #include <boost/phoenix/core/domain.hpp> | |
19 | #include <boost/phoenix/core/environment.hpp> | |
20 | #include <boost/phoenix/core/is_nullary.hpp> | |
21 | #include <boost/phoenix/core/meta_grammar.hpp> | |
22 | #include <boost/phoenix/support/iterate.hpp> | |
23 | #include <boost/phoenix/support/vector.hpp> | |
24 | #include <boost/proto/extends.hpp> | |
25 | #include <boost/proto/make_expr.hpp> | |
26 | #include <boost/utility/result_of.hpp> | |
27 | #include <boost/mpl/void.hpp> | |
28 | #include <cstring> | |
29 | #ifndef BOOST_PHOENIX_NO_VARIADIC_ACTOR | |
30 | # include <boost/mpl/if.hpp> | |
31 | # include <boost/type_traits/is_reference.hpp> | |
32 | # include <boost/phoenix/core/detail/index_sequence.hpp> | |
33 | #endif | |
34 | ||
35 | #ifdef BOOST_MSVC | |
36 | #pragma warning(push) | |
37 | #pragma warning(disable: 4522) // 'this' used in base member initializer list | |
38 | #pragma warning(disable: 4510) // default constructor could not be generated | |
39 | #pragma warning(disable: 4610) // can never be instantiated - user defined cons | |
40 | #endif | |
41 | ||
42 | namespace boost { namespace phoenix | |
43 | { | |
44 | template <typename Expr> | |
45 | struct actor; | |
46 | ||
47 | namespace detail | |
48 | { | |
49 | struct error_expecting_arguments | |
50 | { | |
51 | template <typename T> | |
52 | error_expecting_arguments(T const&) {} | |
53 | }; | |
54 | ||
55 | struct error_invalid_lambda_expr | |
56 | { | |
57 | template <typename T> | |
58 | error_invalid_lambda_expr(T const&) {} | |
59 | }; | |
60 | ||
61 | template <typename T> | |
62 | struct result_type_deduction_helper | |
63 | { | |
64 | typedef T const & type; | |
65 | }; | |
66 | ||
67 | template <typename T> | |
68 | struct result_type_deduction_helper<T &> | |
69 | { | |
70 | typedef T & type; | |
71 | }; | |
72 | ||
73 | template <typename T> | |
74 | struct result_type_deduction_helper<T const &> | |
75 | { | |
76 | typedef T const & type; | |
77 | }; | |
78 | ||
79 | struct do_assign | |
80 | { | |
81 | BOOST_PROTO_CALLABLE() | |
82 | ||
83 | typedef void result_type; | |
84 | ||
85 | template <typename T1, typename T2> | |
86 | void operator()(T1 & t1, T2 const & t2) const | |
87 | { | |
88 | proto::value(t1) = proto::value(t2); | |
89 | } | |
90 | }; | |
91 | ||
92 | #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR | |
93 | #include <boost/phoenix/core/detail/cpp03/assign.hpp> | |
94 | #else | |
95 | struct assign : proto::transform<assign> | |
96 | { | |
97 | typedef assign proto_grammer; | |
98 | ||
99 | template <typename Expr, typename State, typename Data | |
100 | , typename Indices = typename detail::make_index_sequence<proto::arity_of<Expr>::value>::type > | |
101 | struct impl; | |
102 | ||
103 | template <std::size_t> | |
104 | struct proto_expr { typedef proto::_ type; }; | |
105 | ||
106 | template <std::size_t Index> | |
107 | struct nth_assign | |
108 | { | |
109 | typedef | |
110 | assign type( | |
111 | proto::_child_c<Index> | |
112 | , proto::call<proto::_child_c<Index>(proto::_state)> | |
113 | ) | |
114 | ; | |
115 | }; | |
116 | ||
117 | template <typename Expr, typename State, typename Data> | |
118 | struct impl<Expr, State, Data, detail::index_sequence<> > | |
119 | : proto::when< | |
120 | proto::terminal<proto::_> | |
121 | , do_assign(proto::_, proto::_state) | |
122 | >::template impl<Expr, State, Data> | |
123 | { | |
124 | }; | |
125 | ||
126 | template <typename Expr, typename State, typename Data | |
127 | , std::size_t... Indices> | |
128 | struct impl<Expr, State, Data, detail::index_sequence<Indices...> > | |
129 | : proto::when< | |
130 | proto::nary_expr<typename proto_expr<Indices>::type...> | |
131 | , proto::and_<typename nth_assign<Indices>::type...> | |
132 | >::template impl<Expr, State, Data> | |
133 | { | |
134 | }; | |
135 | }; | |
136 | #endif | |
137 | } | |
138 | ||
139 | namespace result_of | |
140 | { | |
141 | #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR | |
142 | // Bring in the result_of::actor<> | |
143 | #include <boost/phoenix/core/detail/cpp03/actor_result_of.hpp> | |
144 | #else | |
145 | template <typename Expr, typename... A> | |
146 | struct actor_impl | |
147 | { | |
148 | typedef | |
149 | typename boost::phoenix::evaluator::impl< | |
150 | Expr const& | |
151 | , vector2< | |
152 | typename vector_chooser<sizeof...(A) + 1>:: | |
153 | template apply<const ::boost::phoenix::actor<Expr> *, A...>::type& | |
154 | , default_actions | |
155 | > const & | |
156 | , proto::empty_env | |
157 | >::result_type | |
158 | type; | |
159 | }; | |
160 | ||
161 | template <typename Expr, typename... A> | |
162 | struct actor : actor_impl<Expr, A...> {}; | |
163 | ||
164 | template <typename Expr> | |
165 | struct nullary_actor_result : actor_impl<Expr> {}; | |
166 | #endif | |
167 | ||
168 | template <typename Expr> | |
169 | struct actor<Expr> | |
170 | { | |
171 | typedef | |
172 | // avoid calling result_of::actor when this is false | |
173 | typename mpl::eval_if_c< | |
174 | result_of::is_nullary<Expr>::value | |
175 | , nullary_actor_result<Expr> | |
176 | , mpl::identity<detail::error_expecting_arguments> | |
177 | >::type | |
178 | type; | |
179 | }; | |
180 | } | |
181 | ||
182 | //////////////////////////////////////////////////////////////////////////// | |
183 | // | |
184 | // actor | |
185 | // | |
186 | // The actor class. The main thing! In phoenix, everything is an actor | |
187 | // This class is responsible for full function evaluation. Partial | |
188 | // function evaluation involves creating a hierarchy of actor objects. | |
189 | // | |
190 | //////////////////////////////////////////////////////////////////////////// | |
191 | template <typename Expr> | |
192 | struct actor | |
193 | { | |
194 | typedef typename | |
195 | mpl::eval_if_c< | |
196 | mpl::or_< | |
197 | is_custom_terminal<Expr> | |
198 | , mpl::bool_<is_placeholder<Expr>::value> | |
199 | >::value | |
200 | , proto::terminal<Expr> | |
201 | , mpl::identity<Expr> | |
202 | >::type | |
203 | expr_type; | |
204 | ||
205 | BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<expr_type>, phoenix_domain) | |
206 | ||
207 | // providing operator= to be assignable | |
208 | actor& operator=(actor const& other) | |
209 | { | |
210 | detail::assign()(*this, other); | |
211 | return *this; | |
212 | } | |
213 | actor& operator=(actor & other) | |
214 | { | |
215 | detail::assign()(*this, other); | |
216 | return *this; | |
217 | } | |
218 | ||
219 | template <typename A0> | |
220 | typename proto::result_of::make_expr< | |
221 | proto::tag::assign | |
222 | , phoenix_domain | |
223 | , proto_base_expr | |
224 | , A0 | |
225 | >::type const | |
226 | operator=(A0 const & a0) const | |
227 | { | |
228 | return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0); | |
229 | } | |
230 | ||
231 | template <typename A0> | |
232 | typename proto::result_of::make_expr< | |
233 | proto::tag::assign | |
234 | , phoenix_domain | |
235 | , proto_base_expr | |
236 | , A0 | |
237 | >::type const | |
238 | operator=(A0 & a0) const | |
239 | { | |
240 | return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0); | |
241 | } | |
242 | ||
243 | template <typename A0> | |
244 | typename proto::result_of::make_expr< | |
245 | proto::tag::subscript | |
246 | , phoenix_domain | |
247 | , proto_base_expr | |
248 | , A0 | |
249 | >::type const | |
250 | operator[](A0 const & a0) const | |
251 | { | |
252 | return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0); | |
253 | } | |
254 | ||
255 | template <typename A0> | |
256 | typename proto::result_of::make_expr< | |
257 | proto::tag::subscript | |
258 | , phoenix_domain | |
259 | , proto_base_expr | |
260 | , A0 | |
261 | >::type const | |
262 | operator[](A0 & a0) const | |
263 | { | |
264 | return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0); | |
265 | } | |
266 | ||
267 | template <typename Sig> | |
268 | struct result; | |
269 | ||
270 | typename result_of::actor<proto_base_expr>::type | |
271 | operator()() | |
272 | { | |
273 | typedef vector1<const actor<Expr> *> env_type; | |
274 | env_type env = {this}; | |
275 | ||
276 | return phoenix::eval(*this, phoenix::context(env, default_actions())); | |
277 | } | |
278 | ||
279 | typename result_of::actor<proto_base_expr>::type | |
280 | operator()() const | |
281 | { | |
282 | typedef vector1<const actor<Expr> *> env_type; | |
283 | env_type env = {this}; | |
284 | ||
285 | return phoenix::eval(*this, phoenix::context(env, default_actions())); | |
286 | } | |
287 | ||
288 | template <typename Env> | |
289 | typename evaluator::impl< | |
290 | proto_base_expr const & | |
291 | , typename result_of::context< | |
292 | Env const & | |
293 | , default_actions const & | |
294 | >::type | |
295 | , proto::empty_env | |
296 | >::result_type | |
297 | eval(Env const & env) const | |
298 | { | |
299 | return phoenix::eval(*this, phoenix::context(env, default_actions())); | |
300 | } | |
301 | ||
302 | #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR | |
303 | // Bring in the rest | |
304 | #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp> | |
305 | #else | |
306 | template <typename This, typename... A> | |
307 | struct result<This(A...)> | |
308 | : result_of::actor< | |
309 | proto_base_expr | |
310 | , typename mpl::if_<is_reference<A>, A, A const &>::type... | |
311 | > | |
312 | {}; | |
313 | ||
314 | template <typename... A> | |
315 | typename result<actor(A...)>::type | |
316 | operator()(A &&... a) | |
317 | { | |
318 | typedef | |
319 | typename vector_chooser<sizeof...(A) + 1>::template apply< | |
320 | const actor<Expr> * | |
321 | , typename mpl::if_<is_reference<A>, A, A const &>::type... | |
322 | >::type | |
323 | env_type; | |
324 | ||
325 | env_type env = {this, a...}; | |
326 | return phoenix::eval(*this, phoenix::context(env, default_actions())); | |
327 | } | |
328 | ||
329 | template <typename... A> | |
330 | typename result<actor(A...)>::type | |
331 | operator()(A &&... a) const | |
332 | { | |
333 | typedef | |
334 | typename vector_chooser<sizeof...(A) + 1>::template apply< | |
335 | const actor<Expr> * | |
336 | , typename mpl::if_<is_reference<A>, A, A const &>::type... | |
337 | >::type | |
338 | env_type; | |
339 | ||
340 | env_type env = {this, a...}; | |
341 | return phoenix::eval(*this, phoenix::context(env, default_actions())); | |
342 | } | |
343 | #endif | |
344 | }; | |
345 | }} | |
346 | ||
347 | namespace boost | |
348 | { | |
349 | // specialize boost::result_of to return the proper result type | |
350 | template <typename Expr> | |
351 | struct result_of<phoenix::actor<Expr>()> | |
352 | : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> | |
353 | {}; | |
354 | ||
355 | template <typename Expr> | |
356 | struct result_of<phoenix::actor<Expr> const()> | |
357 | : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> | |
358 | {}; | |
359 | } | |
360 | ||
361 | ||
362 | #ifdef BOOST_MSVC | |
363 | #pragma warning(pop) | |
364 | #endif | |
365 | ||
366 | #endif | |
367 |