1 | /*============================================================================= |
---|
2 | Phoenix V1.2.1 |
---|
3 | Copyright (c) 2001-2003 Joel de Guzman |
---|
4 | |
---|
5 | Use, modification and distribution is subject to the Boost Software |
---|
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
7 | http://www.boost.org/LICENSE_1_0.txt) |
---|
8 | ==============================================================================*/ |
---|
9 | #include <vector> |
---|
10 | #include <algorithm> |
---|
11 | #include <iostream> |
---|
12 | |
---|
13 | #define PHOENIX_LIMIT 5 |
---|
14 | #include <boost/spirit/phoenix/operators.hpp> |
---|
15 | #include <boost/spirit/phoenix/primitives.hpp> |
---|
16 | #include <boost/spirit/phoenix/composite.hpp> |
---|
17 | #include <boost/spirit/phoenix/special_ops.hpp> |
---|
18 | #include <boost/spirit/phoenix/statements.hpp> |
---|
19 | #include <boost/spirit/phoenix/functions.hpp> |
---|
20 | |
---|
21 | namespace phoenix { |
---|
22 | |
---|
23 | /////////////////////////////////////////////////////////////////////////////// |
---|
24 | // |
---|
25 | // local_tuple |
---|
26 | // |
---|
27 | // This *is a* tuple like the one we see in TupleT in any actor |
---|
28 | // base class' eval member function. local_tuple should look and |
---|
29 | // feel the same as a tupled-args, that's why it is derived from |
---|
30 | // TupleArgsT. It has an added member, locs which is another tuple |
---|
31 | // where the local variables will be stored. locs is mutable to |
---|
32 | // allow read-write access to our locals regardless of |
---|
33 | // local_tuple's constness (The eval member function accepts it as |
---|
34 | // a const argument). |
---|
35 | // |
---|
36 | /////////////////////////////////////////////////////////////////////////////// |
---|
37 | template <typename TupleArgsT, typename TupleLocsT> |
---|
38 | struct local_tuple : public TupleArgsT { |
---|
39 | |
---|
40 | local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) |
---|
41 | : TupleArgsT(args), locs(locs_) {} |
---|
42 | |
---|
43 | mutable TupleLocsT locs; |
---|
44 | }; |
---|
45 | |
---|
46 | /////////////////////////////////////////////////////////////////////////////// |
---|
47 | // |
---|
48 | // local_var_result |
---|
49 | // |
---|
50 | // This is a return type computer. Given a constant integer N, a |
---|
51 | // parent index and a tuple, get the Nth local variable type. The |
---|
52 | // parent index is an integer specifying which parent scope to |
---|
53 | // access; 0==current scope, 1==parent scope, 2==parent's parent |
---|
54 | // scope etc. |
---|
55 | // |
---|
56 | // This is a metaprogram with partial specializations. There is a |
---|
57 | // general case, a special case for local_tuples and a terminating |
---|
58 | // special case for local_tuples. |
---|
59 | // |
---|
60 | // General case: If TupleT is not really a local_tuple, we just return nil_t. |
---|
61 | // |
---|
62 | // local_tuples case: |
---|
63 | // Parent index is 0: We get the Nth local variable. |
---|
64 | // Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT> |
---|
65 | // |
---|
66 | /////////////////////////////////////////////////////////////////////////////// |
---|
67 | template <int N, int Parent, typename TupleT> |
---|
68 | struct local_var_result { |
---|
69 | |
---|
70 | typedef nil_t type; |
---|
71 | }; |
---|
72 | |
---|
73 | ////////////////////////////////// |
---|
74 | template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> |
---|
75 | struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > |
---|
76 | : public local_var_result<N, Parent-1, TupleArgsT> {}; |
---|
77 | |
---|
78 | ////////////////////////////////// |
---|
79 | template <int N, typename TupleArgsT, typename TupleLocsT> |
---|
80 | struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { |
---|
81 | |
---|
82 | typedef typename tuple_element<N, TupleLocsT>::type& type; |
---|
83 | |
---|
84 | static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple) |
---|
85 | { return tuple.locs[tuple_index<N>()]; } |
---|
86 | }; |
---|
87 | |
---|
88 | /////////////////////////////////////////////////////////////////////////////// |
---|
89 | // |
---|
90 | // local_var |
---|
91 | // |
---|
92 | // This class looks so curiously like the argument class. local_var |
---|
93 | // provides access to the Nth local variable packed in the tuple |
---|
94 | // duo local_tuple above. Parent specifies the Nth parent scope. |
---|
95 | // 0==current scope, 1==parent scope, 2==parent's parent scope etc. |
---|
96 | // The member function parent<N>() may be called to provide access |
---|
97 | // to outer scopes. |
---|
98 | // |
---|
99 | // Note that the member function eval expects a local_tuple |
---|
100 | // argument. Otherwise there will be acompile-time error. local_var |
---|
101 | // primitives only work within the context of a context_composite |
---|
102 | // (see below). |
---|
103 | // |
---|
104 | // Provided are some predefined local_var actors for 0..N local |
---|
105 | // variable access: lvar1..locN. |
---|
106 | // |
---|
107 | /////////////////////////////////////////////////////////////////////////////// |
---|
108 | template <int N, int Parent = 0> |
---|
109 | struct local_var { |
---|
110 | |
---|
111 | typedef local_var<N, Parent> self_t; |
---|
112 | |
---|
113 | template <typename TupleT> |
---|
114 | struct result { |
---|
115 | |
---|
116 | typedef typename local_var_result<N, Parent, TupleT>::type type; |
---|
117 | }; |
---|
118 | |
---|
119 | template <typename TupleT> |
---|
120 | typename actor_result<self_t, TupleT>::type |
---|
121 | eval(TupleT const& tuple) const |
---|
122 | { |
---|
123 | return local_var_result<N, Parent, TupleT>::get(tuple); |
---|
124 | } |
---|
125 | |
---|
126 | template <int PIndex> |
---|
127 | actor<local_var<N, Parent+PIndex> > |
---|
128 | parent() const |
---|
129 | { |
---|
130 | return local_var<N, Parent+PIndex>(); |
---|
131 | } |
---|
132 | }; |
---|
133 | |
---|
134 | ////////////////////////////////// |
---|
135 | namespace locals { |
---|
136 | |
---|
137 | actor<local_var<0> > const result = local_var<0>(); |
---|
138 | actor<local_var<1> > const lvar1 = local_var<1>(); |
---|
139 | actor<local_var<2> > const lvar2 = local_var<2>(); |
---|
140 | actor<local_var<3> > const lvar3 = local_var<3>(); |
---|
141 | actor<local_var<4> > const lvar4 = local_var<4>(); |
---|
142 | } |
---|
143 | |
---|
144 | |
---|
145 | |
---|
146 | |
---|
147 | |
---|
148 | |
---|
149 | |
---|
150 | |
---|
151 | |
---|
152 | /////////////////////////////////////////////////////////////////////////////// |
---|
153 | template <int N, int Parent, typename TupleT> |
---|
154 | struct local_func_result { |
---|
155 | |
---|
156 | typedef nil_t type; |
---|
157 | }; |
---|
158 | |
---|
159 | ////////////////////////////////// |
---|
160 | template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> |
---|
161 | struct local_func_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > |
---|
162 | : public local_func_result<N, Parent-1, TupleArgsT> {}; |
---|
163 | |
---|
164 | ////////////////////////////////// |
---|
165 | template <int N, typename TupleArgsT, typename TupleLocsT> |
---|
166 | struct local_func_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { |
---|
167 | |
---|
168 | typedef typename actor_result< |
---|
169 | typename tuple_element<N, TupleLocsT>::type, |
---|
170 | local_tuple<TupleArgsT, TupleLocsT> |
---|
171 | >::type type; |
---|
172 | |
---|
173 | template <typename ArgsT> |
---|
174 | static type eval(local_tuple<ArgsT, TupleLocsT> const& tuple) |
---|
175 | { return tuple.locs[tuple_index<N>()].eval(tuple); } |
---|
176 | }; |
---|
177 | |
---|
178 | |
---|
179 | |
---|
180 | |
---|
181 | |
---|
182 | |
---|
183 | |
---|
184 | |
---|
185 | template < |
---|
186 | int N, int Parent, |
---|
187 | typename A0 = nil_t, |
---|
188 | typename A1 = nil_t, |
---|
189 | typename A2 = nil_t, |
---|
190 | typename A3 = nil_t, |
---|
191 | typename A4 = nil_t |
---|
192 | > |
---|
193 | struct local_function_actor; |
---|
194 | |
---|
195 | ////////////////////////////////// |
---|
196 | template <int N, int Parent> |
---|
197 | struct local_function_base { |
---|
198 | |
---|
199 | template <typename TupleT> |
---|
200 | struct result { |
---|
201 | |
---|
202 | typedef typename local_func_result<N, Parent, TupleT>::type type; |
---|
203 | }; |
---|
204 | }; |
---|
205 | |
---|
206 | ////////////////////////////////// |
---|
207 | template <int N, int Parent> |
---|
208 | struct local_function_actor<N, Parent, nil_t, nil_t, nil_t, nil_t, nil_t> |
---|
209 | : public local_function_base<N, Parent> { |
---|
210 | |
---|
211 | template <typename TupleArgsT, typename TupleLocsT> |
---|
212 | typename local_func_result< |
---|
213 | N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type |
---|
214 | eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const |
---|
215 | { |
---|
216 | typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; |
---|
217 | typedef tuple<> tuple_t; |
---|
218 | tuple_t local_args; |
---|
219 | |
---|
220 | local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); |
---|
221 | return local_func_result< |
---|
222 | N, Parent, local_tuple_t> |
---|
223 | ::eval(local_context); |
---|
224 | } |
---|
225 | }; |
---|
226 | |
---|
227 | ////////////////////////////////// |
---|
228 | template <int N, int Parent, |
---|
229 | typename A0> |
---|
230 | struct local_function_actor<N, Parent, A0, nil_t, nil_t, nil_t, nil_t> |
---|
231 | : public local_function_base<N, Parent> { |
---|
232 | |
---|
233 | local_function_actor( |
---|
234 | A0 const& _0) |
---|
235 | : a0(_0) {} |
---|
236 | |
---|
237 | template <typename TupleArgsT, typename TupleLocsT> |
---|
238 | typename local_func_result< |
---|
239 | N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type |
---|
240 | eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const |
---|
241 | { |
---|
242 | typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; |
---|
243 | typename actor_result<A0, local_tuple_t>::type r0 = a0.eval(args); |
---|
244 | |
---|
245 | typedef tuple< |
---|
246 | typename actor_result<A0, local_tuple_t>::type |
---|
247 | > tuple_t; |
---|
248 | tuple_t local_args(r0); |
---|
249 | |
---|
250 | local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); |
---|
251 | return local_func_result< |
---|
252 | N, Parent, local_tuple_t> |
---|
253 | ::eval(local_context); |
---|
254 | } |
---|
255 | |
---|
256 | A0 a0; // actors |
---|
257 | }; |
---|
258 | |
---|
259 | namespace impl { |
---|
260 | |
---|
261 | template < |
---|
262 | int N, int Parent, |
---|
263 | typename T0 = nil_t, |
---|
264 | typename T1 = nil_t, |
---|
265 | typename T2 = nil_t, |
---|
266 | typename T3 = nil_t, |
---|
267 | typename T4 = nil_t |
---|
268 | > |
---|
269 | struct make_local_function_actor { |
---|
270 | |
---|
271 | typedef local_function_actor< |
---|
272 | N, Parent, |
---|
273 | typename as_actor<T0>::type, |
---|
274 | typename as_actor<T1>::type, |
---|
275 | typename as_actor<T2>::type, |
---|
276 | typename as_actor<T3>::type, |
---|
277 | typename as_actor<T4>::type |
---|
278 | > composite_type; |
---|
279 | |
---|
280 | typedef actor<composite_type> type; |
---|
281 | }; |
---|
282 | } |
---|
283 | |
---|
284 | |
---|
285 | |
---|
286 | template <int N, int Parent = 0> |
---|
287 | struct local_function { |
---|
288 | |
---|
289 | actor<local_function_actor<N, Parent> > |
---|
290 | operator()() const |
---|
291 | { |
---|
292 | return local_function_actor<N, Parent>(); |
---|
293 | } |
---|
294 | |
---|
295 | template <typename T0> |
---|
296 | typename impl::make_local_function_actor<N, Parent, T0>::type |
---|
297 | operator()(T0 const& _0) const |
---|
298 | { |
---|
299 | return impl::make_local_function_actor<N, Parent, T0>::composite_type(_0); |
---|
300 | } |
---|
301 | |
---|
302 | template <int PIndex> |
---|
303 | local_function<N, Parent+PIndex> |
---|
304 | parent() const |
---|
305 | { |
---|
306 | return local_function<N, Parent+PIndex>(); |
---|
307 | } |
---|
308 | }; |
---|
309 | |
---|
310 | ////////////////////////////////// |
---|
311 | namespace locals { |
---|
312 | |
---|
313 | local_function<1> const lfun1 = local_function<1>(); |
---|
314 | local_function<2> const lfun2 = local_function<2>(); |
---|
315 | local_function<3> const lfun3 = local_function<3>(); |
---|
316 | local_function<4> const lfun4 = local_function<4>(); |
---|
317 | } |
---|
318 | |
---|
319 | |
---|
320 | |
---|
321 | |
---|
322 | |
---|
323 | |
---|
324 | /////////////////////////////////////////////////////////////////////////////// |
---|
325 | // |
---|
326 | // context_composite |
---|
327 | // |
---|
328 | // This class encapsulates an actor and some local variable |
---|
329 | // initializers packed in a tuple. |
---|
330 | // |
---|
331 | // context_composite is just like a proxy and delegates the actual |
---|
332 | // evaluation to the actor. The actor does the actual work. In the |
---|
333 | // eval member function, before invoking the embedded actor's eval |
---|
334 | // member function, we first stuff an instance of our locals and |
---|
335 | // bundle both 'args' and 'locals' in a local_tuple. This |
---|
336 | // local_tuple instance is created in the stack initializing it |
---|
337 | // with our locals member. We then pass this local_tuple instance |
---|
338 | // as an argument to the actor's eval member function. |
---|
339 | // |
---|
340 | /////////////////////////////////////////////////////////////////////////////// |
---|
341 | template <typename ActorT, typename LocsT> |
---|
342 | struct context_composite { |
---|
343 | |
---|
344 | typedef context_composite<ActorT, LocsT> self_t; |
---|
345 | |
---|
346 | template <typename TupleT> |
---|
347 | struct result { typedef typename tuple_element<0, LocsT>::type type; }; |
---|
348 | |
---|
349 | context_composite(ActorT const& actor_, LocsT const& locals_) |
---|
350 | : actor(actor_), locals(locals_) {} |
---|
351 | |
---|
352 | template <typename TupleT> |
---|
353 | typename tuple_element<0, LocsT>::type |
---|
354 | eval(TupleT const& args) const |
---|
355 | { |
---|
356 | local_tuple<TupleT, LocsT> local_context(args, locals); |
---|
357 | actor.eval(local_context); |
---|
358 | return local_context.locs[tuple_index<0>()]; |
---|
359 | } |
---|
360 | |
---|
361 | ActorT actor; |
---|
362 | LocsT locals; |
---|
363 | }; |
---|
364 | |
---|
365 | /////////////////////////////////////////////////////////////////////////////// |
---|
366 | // |
---|
367 | // context_gen |
---|
368 | // |
---|
369 | // At construction time, this class is given some local var- |
---|
370 | // initializers packed in a tuple. We just store this for later. |
---|
371 | // The operator[] of this class creates the actual context_composite |
---|
372 | // given an actor. This is responsible for the construct |
---|
373 | // context<types>[actor]. |
---|
374 | // |
---|
375 | /////////////////////////////////////////////////////////////////////////////// |
---|
376 | template <typename LocsT> |
---|
377 | struct context_gen { |
---|
378 | |
---|
379 | context_gen(LocsT const& locals_) |
---|
380 | : locals(locals_) {} |
---|
381 | |
---|
382 | template <typename ActorT> |
---|
383 | actor<context_composite<typename as_actor<ActorT>::type, LocsT> > |
---|
384 | operator[](ActorT const& actor) |
---|
385 | { |
---|
386 | return context_composite<typename as_actor<ActorT>::type, LocsT> |
---|
387 | (as_actor<ActorT>::convert(actor), locals); |
---|
388 | } |
---|
389 | |
---|
390 | LocsT locals; |
---|
391 | }; |
---|
392 | |
---|
393 | /////////////////////////////////////////////////////////////////////////////// |
---|
394 | // |
---|
395 | // Front end generator functions. These generators are overloaded for |
---|
396 | // 1..N local variables. context<T0,... TN>(i0,...iN) generate |
---|
397 | // context_gen objects (see above). |
---|
398 | // |
---|
399 | /////////////////////////////////////////////////////////////////////////////// |
---|
400 | template <typename T0> |
---|
401 | inline context_gen<tuple<T0> > |
---|
402 | context() |
---|
403 | { |
---|
404 | typedef tuple<T0> tuple_t; |
---|
405 | return context_gen<tuple_t>(tuple_t(T0())); |
---|
406 | } |
---|
407 | |
---|
408 | ////////////////////////////////// |
---|
409 | template <typename T0, typename T1> |
---|
410 | inline context_gen<tuple<T0, T1> > |
---|
411 | context( |
---|
412 | T1 const& _1 = T1() |
---|
413 | ) |
---|
414 | { |
---|
415 | typedef tuple<T0, T1> tuple_t; |
---|
416 | return context_gen<tuple_t>(tuple_t(T0(), _1)); |
---|
417 | } |
---|
418 | |
---|
419 | ////////////////////////////////// |
---|
420 | template <typename T0, typename T1, typename T2> |
---|
421 | inline context_gen<tuple<T0, T1, T2> > |
---|
422 | context( |
---|
423 | T1 const& _1 = T1(), |
---|
424 | T2 const& _2 = T2() |
---|
425 | ) |
---|
426 | { |
---|
427 | typedef tuple<T0, T1, T2> tuple_t; |
---|
428 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2)); |
---|
429 | } |
---|
430 | |
---|
431 | ////////////////////////////////// |
---|
432 | template <typename T0, typename T1, typename T2, typename T3> |
---|
433 | inline context_gen<tuple<T0, T1, T2, T3> > |
---|
434 | context( |
---|
435 | T1 const& _1 = T1(), |
---|
436 | T2 const& _2 = T2(), |
---|
437 | T3 const& _3 = T3() |
---|
438 | ) |
---|
439 | { |
---|
440 | typedef tuple<T0, T1, T2, T3> tuple_t; |
---|
441 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3)); |
---|
442 | } |
---|
443 | |
---|
444 | ////////////////////////////////// |
---|
445 | template <typename T0, typename T1, typename T2, typename T3, typename T4> |
---|
446 | inline context_gen<tuple<T0, T1, T2, T3, T4> > |
---|
447 | context( |
---|
448 | T1 const& _1 = T1(), |
---|
449 | T2 const& _2 = T2(), |
---|
450 | T3 const& _3 = T3(), |
---|
451 | T4 const& _4 = T4() |
---|
452 | ) |
---|
453 | { |
---|
454 | typedef tuple<T0, T1, T2, T3, T4> tuple_t; |
---|
455 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4)); |
---|
456 | } |
---|
457 | |
---|
458 | |
---|
459 | |
---|
460 | |
---|
461 | |
---|
462 | |
---|
463 | |
---|
464 | |
---|
465 | |
---|
466 | |
---|
467 | |
---|
468 | |
---|
469 | /////////////////////////////////////////////////////////////////////////////// |
---|
470 | } |
---|
471 | |
---|
472 | ////////////////////////////////// |
---|
473 | using namespace std; |
---|
474 | using namespace phoenix; |
---|
475 | using namespace phoenix::locals; |
---|
476 | |
---|
477 | ////////////////////////////////// |
---|
478 | int |
---|
479 | main() |
---|
480 | { |
---|
481 | int _10 = 10; |
---|
482 | |
---|
483 | #ifndef __BORLANDC__ |
---|
484 | |
---|
485 | context<nil_t> |
---|
486 | ( |
---|
487 | 1000, // lvar1: local int variable |
---|
488 | cout << arg1 << '\n', // lfun2: local function w/ 1 argument (arg1) |
---|
489 | lvar1 * 2, // lfun3: local function that accesses local variable lvar1 |
---|
490 | lfun2(2 * arg1) // lfun4: local function that calls local function lfun2 |
---|
491 | ) |
---|
492 | [ |
---|
493 | lfun2(arg1 + 2000), |
---|
494 | lfun2(val(5000) * 2), |
---|
495 | lfun2(lvar1 + lfun3()), |
---|
496 | lfun4(val(55)), |
---|
497 | cout << lvar1 << '\n', |
---|
498 | cout << lfun3() << '\n', |
---|
499 | cout << val("bye bye\n") |
---|
500 | ] |
---|
501 | |
---|
502 | (_10); |
---|
503 | |
---|
504 | #else // Borland does not like local variables w/ local functions |
---|
505 | // we can have local variables (see sample 7..9) *OR* |
---|
506 | // local functions (this: sample 10) but not both |
---|
507 | // Sigh... Borland :-{ |
---|
508 | |
---|
509 | context<nil_t> |
---|
510 | ( |
---|
511 | 12345, |
---|
512 | cout << arg1 << '\n' |
---|
513 | ) |
---|
514 | [ |
---|
515 | lfun2(arg1 + 687), |
---|
516 | lfun2(val(9999) * 2), |
---|
517 | cout << val("bye bye\n") |
---|
518 | ] |
---|
519 | |
---|
520 | (_10); |
---|
521 | |
---|
522 | #endif |
---|
523 | |
---|
524 | return 0; |
---|
525 | } |
---|