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 
local_tuplephoenix::local_tuple40     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 
getphoenix::local_var_result84     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
evalphoenix::local_var121     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> >
parentphoenix::local_var128     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>
evalphoenix::local_func_result174     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
evalphoenix::local_function_actor214     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 
local_function_actorphoenix::local_function_actor233     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
evalphoenix::local_function_actor240     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> >
operator ()phoenix::local_function290     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
operator ()phoenix::local_function297     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>
parentphoenix::local_function304     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 
context_compositephoenix::context_composite349     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
evalphoenix::context_composite354     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 
context_genphoenix::context_gen379     context_gen(LocsT const& locals_)
380     :   locals(locals_) {}
381 
382     template <typename ActorT>
383     actor<context_composite<typename as_actor<ActorT>::type, LocsT> >
operator []phoenix::context_gen384     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> >
context()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> >
context(T1 const & _1=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> >
context(T1 const & _1=T1 (),T2 const & _2=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> >
context(T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=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> >
context(T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=T3 (),T4 const & _4=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
main()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 }
526