Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/spirit/phoenix/example/fundamental/sample10.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 14.8 KB
Line 
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
21namespace 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///////////////////////////////////////////////////////////////////////////////
37template <typename TupleArgsT, typename TupleLocsT>
38struct 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///////////////////////////////////////////////////////////////////////////////
67template <int N, int Parent, typename TupleT>
68struct local_var_result {
69
70    typedef nil_t type;
71};
72
73//////////////////////////////////
74template <int N, int Parent, typename TupleArgsT, typename TupleLocsT>
75struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> >
76:   public local_var_result<N, Parent-1, TupleArgsT> {};
77
78//////////////////////////////////
79template <int N, typename TupleArgsT, typename TupleLocsT>
80struct 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///////////////////////////////////////////////////////////////////////////////
108template <int N, int Parent = 0>
109struct 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//////////////////////////////////
135namespace 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///////////////////////////////////////////////////////////////////////////////
153template <int N, int Parent, typename TupleT>
154struct local_func_result {
155
156    typedef nil_t type;
157};
158
159//////////////////////////////////
160template <int N, int Parent, typename TupleArgsT, typename TupleLocsT>
161struct local_func_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> >
162:   public local_func_result<N, Parent-1, TupleArgsT> {};
163
164//////////////////////////////////
165template <int N, typename TupleArgsT, typename TupleLocsT>
166struct 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
185template <
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>
193struct local_function_actor;
194
195//////////////////////////////////
196template <int N, int Parent>
197struct 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//////////////////////////////////
207template <int N, int Parent>
208struct 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//////////////////////////////////
228template <int N, int Parent,
229    typename A0>
230struct 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
259namespace 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
286template <int N, int Parent = 0>
287struct 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//////////////////////////////////
311namespace 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///////////////////////////////////////////////////////////////////////////////
341template <typename ActorT, typename LocsT>
342struct 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///////////////////////////////////////////////////////////////////////////////
376template <typename LocsT>
377struct 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///////////////////////////////////////////////////////////////////////////////
400template <typename T0>
401inline context_gen<tuple<T0> >
402context()
403{
404    typedef tuple<T0> tuple_t;
405    return context_gen<tuple_t>(tuple_t(T0()));
406}
407
408//////////////////////////////////
409template <typename T0, typename T1>
410inline context_gen<tuple<T0, T1> >
411context(
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//////////////////////////////////
420template <typename T0, typename T1, typename T2>
421inline context_gen<tuple<T0, T1, T2> >
422context(
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//////////////////////////////////
432template <typename T0, typename T1, typename T2, typename T3>
433inline context_gen<tuple<T0, T1, T2, T3> >
434context(
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//////////////////////////////////
445template <typename T0, typename T1, typename T2, typename T3, typename T4>
446inline context_gen<tuple<T0, T1, T2, T3, T4> >
447context(
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//////////////////////////////////
473using namespace std;
474using namespace phoenix;
475using namespace phoenix::locals;
476
477//////////////////////////////////
478int
479main()
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}
Note: See TracBrowser for help on using the repository browser.