]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/include/phoenix1_operators.hpp> | |
15 | #include <boost/spirit/include/phoenix1_primitives.hpp> | |
16 | #include <boost/spirit/include/phoenix1_composite.hpp> | |
17 | #include <boost/spirit/include/phoenix1_special_ops.hpp> | |
18 | #include <boost/spirit/include/phoenix1_statements.hpp> | |
19 | #include <boost/spirit/include/phoenix1_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 | ||
20effc67 | 483 | #if !defined(__BORLANDC__) || defined(__clang__) |
7c673cae FG |
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 | } |