1 /*=============================================================================
3 Copyright (c) 2001-2003 Joel de Guzman
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 ==============================================================================*/
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>
23 ///////////////////////////////////////////////////////////////////////////////
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
36 ///////////////////////////////////////////////////////////////////////////////
37 template <typename TupleArgsT
, typename TupleLocsT
>
38 struct local_tuple
: public TupleArgsT
{
40 local_tuple(TupleArgsT
const& args
, TupleLocsT
const& locs_
)
41 : TupleArgsT(args
), locs(locs_
) {}
43 mutable TupleLocsT locs
;
46 ///////////////////////////////////////////////////////////////////////////////
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
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.
60 // General case: If TupleT is not really a local_tuple, we just return nil_t.
63 // Parent index is 0: We get the Nth local variable.
64 // Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT>
66 ///////////////////////////////////////////////////////////////////////////////
67 template <int N
, int Parent
, typename TupleT
>
68 struct local_var_result
{
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
> {};
78 //////////////////////////////////
79 template <int N
, typename TupleArgsT
, typename TupleLocsT
>
80 struct local_var_result
<N
, 0, local_tuple
<TupleArgsT
, TupleLocsT
> > {
82 typedef typename tuple_element
<N
, TupleLocsT
>::type
& type
;
84 static type
get(local_tuple
<TupleArgsT
, TupleLocsT
> const& tuple
)
85 { return tuple
.locs
[tuple_index
<N
>()]; }
88 ///////////////////////////////////////////////////////////////////////////////
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
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
104 // Provided are some predefined local_var actors for 0..N local
105 // variable access: lvar1..locN.
107 ///////////////////////////////////////////////////////////////////////////////
108 template <int N
, int Parent
= 0>
111 typedef local_var
<N
, Parent
> self_t
;
113 template <typename TupleT
>
116 typedef typename local_var_result
<N
, Parent
, TupleT
>::type type
;
119 template <typename TupleT
>
120 typename actor_result
<self_t
, TupleT
>::type
121 eval(TupleT
const& tuple
) const
123 return local_var_result
<N
, Parent
, TupleT
>::get(tuple
);
126 template <int PIndex
>
127 actor
<local_var
<N
, Parent
+PIndex
> >
130 return local_var
<N
, Parent
+PIndex
>();
134 //////////////////////////////////
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>();
152 ///////////////////////////////////////////////////////////////////////////////
153 template <int N
, int Parent
, typename TupleT
>
154 struct local_func_result
{
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
> {};
164 //////////////////////////////////
165 template <int N
, typename TupleArgsT
, typename TupleLocsT
>
166 struct local_func_result
<N
, 0, local_tuple
<TupleArgsT
, TupleLocsT
> > {
168 typedef typename actor_result
<
169 typename tuple_element
<N
, TupleLocsT
>::type
,
170 local_tuple
<TupleArgsT
, TupleLocsT
>
173 template <typename ArgsT
>
174 static type
eval(local_tuple
<ArgsT
, TupleLocsT
> const& tuple
)
175 { return tuple
.locs
[tuple_index
<N
>()].eval(tuple
); }
193 struct local_function_actor
;
195 //////////////////////////////////
196 template <int N
, int Parent
>
197 struct local_function_base
{
199 template <typename TupleT
>
202 typedef typename local_func_result
<N
, Parent
, TupleT
>::type type
;
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
> {
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
216 typedef local_tuple
<TupleArgsT
, TupleLocsT
> local_tuple_t
;
217 typedef tuple
<> tuple_t
;
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
);
227 //////////////////////////////////
228 template <int N
, int Parent
,
230 struct local_function_actor
<N
, Parent
, A0
, nil_t
, nil_t
, nil_t
, nil_t
>
231 : public local_function_base
<N
, Parent
> {
233 local_function_actor(
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
242 typedef local_tuple
<TupleArgsT
, TupleLocsT
> local_tuple_t
;
243 typename actor_result
<A0
, local_tuple_t
>::type r0
= a0
.eval(args
);
246 typename actor_result
<A0
, local_tuple_t
>::type
248 tuple_t
local_args(r0
);
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
);
269 struct make_local_function_actor
{
271 typedef local_function_actor
<
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
280 typedef actor
<composite_type
> type
;
286 template <int N
, int Parent
= 0>
287 struct local_function
{
289 actor
<local_function_actor
<N
, Parent
> >
292 return local_function_actor
<N
, Parent
>();
295 template <typename T0
>
296 typename
impl::make_local_function_actor
<N
, Parent
, T0
>::type
297 operator()(T0
const& _0
) const
299 return impl::make_local_function_actor
<N
, Parent
, T0
>::composite_type(_0
);
302 template <int PIndex
>
303 local_function
<N
, Parent
+PIndex
>
306 return local_function
<N
, Parent
+PIndex
>();
310 //////////////////////////////////
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>();
324 ///////////////////////////////////////////////////////////////////////////////
328 // This class encapsulates an actor and some local variable
329 // initializers packed in a tuple.
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.
340 ///////////////////////////////////////////////////////////////////////////////
341 template <typename ActorT
, typename LocsT
>
342 struct context_composite
{
344 typedef context_composite
<ActorT
, LocsT
> self_t
;
346 template <typename TupleT
>
347 struct result
{ typedef typename tuple_element
<0, LocsT
>::type type
; };
349 context_composite(ActorT
const& actor_
, LocsT
const& locals_
)
350 : actor(actor_
), locals(locals_
) {}
352 template <typename TupleT
>
353 typename tuple_element
<0, LocsT
>::type
354 eval(TupleT
const& args
) const
356 local_tuple
<TupleT
, LocsT
> local_context(args
, locals
);
357 actor
.eval(local_context
);
358 return local_context
.locs
[tuple_index
<0>()];
365 ///////////////////////////////////////////////////////////////////////////////
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].
375 ///////////////////////////////////////////////////////////////////////////////
376 template <typename LocsT
>
379 context_gen(LocsT
const& locals_
)
382 template <typename ActorT
>
383 actor
<context_composite
<typename as_actor
<ActorT
>::type
, LocsT
> >
384 operator[](ActorT
const& actor
)
386 return context_composite
<typename as_actor
<ActorT
>::type
, LocsT
>
387 (as_actor
<ActorT
>::convert(actor
), locals
);
393 ///////////////////////////////////////////////////////////////////////////////
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).
399 ///////////////////////////////////////////////////////////////////////////////
400 template <typename T0
>
401 inline context_gen
<tuple
<T0
> >
404 typedef tuple
<T0
> tuple_t
;
405 return context_gen
<tuple_t
>(tuple_t(T0()));
408 //////////////////////////////////
409 template <typename T0
, typename T1
>
410 inline context_gen
<tuple
<T0
, T1
> >
415 typedef tuple
<T0
, T1
> tuple_t
;
416 return context_gen
<tuple_t
>(tuple_t(T0(), _1
));
419 //////////////////////////////////
420 template <typename T0
, typename T1
, typename T2
>
421 inline context_gen
<tuple
<T0
, T1
, T2
> >
427 typedef tuple
<T0
, T1
, T2
> tuple_t
;
428 return context_gen
<tuple_t
>(tuple_t(T0(), _1
, _2
));
431 //////////////////////////////////
432 template <typename T0
, typename T1
, typename T2
, typename T3
>
433 inline context_gen
<tuple
<T0
, T1
, T2
, T3
> >
440 typedef tuple
<T0
, T1
, T2
, T3
> tuple_t
;
441 return context_gen
<tuple_t
>(tuple_t(T0(), _1
, _2
, _3
));
444 //////////////////////////////////
445 template <typename T0
, typename T1
, typename T2
, typename T3
, typename T4
>
446 inline context_gen
<tuple
<T0
, T1
, T2
, T3
, T4
> >
454 typedef tuple
<T0
, T1
, T2
, T3
, T4
> tuple_t
;
455 return context_gen
<tuple_t
>(tuple_t(T0(), _1
, _2
, _3
, _4
));
469 ///////////////////////////////////////////////////////////////////////////////
472 //////////////////////////////////
474 using namespace phoenix
;
475 using namespace phoenix::locals
;
477 //////////////////////////////////
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
494 lfun2(val(5000) * 2),
495 lfun2(lvar1
+ lfun3()),
497 cout
<< lvar1
<< '\n',
498 cout
<< lfun3() << '\n',
499 cout
<< val("bye bye\n")
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 :-{
516 lfun2(val(9999) * 2),
517 cout
<< val("bye bye\n")