• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 namespace phoenix {
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 //
24 //  local_tuple
25 //
26 //      This *is a* tuple like the one we see in TupleT in any actor
27 //      base class' eval member function. local_tuple should look and
28 //      feel the same as a tupled-args, that's why it is derived from
29 //      TupleArgsT. It has an added member, locs which is another tuple
30 //      where the local variables will be stored. locs is mutable to
31 //      allow read-write access to our locals regardless of
32 //      local_tuple's constness (The eval member function accepts it as
33 //      a const argument).
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 template <typename TupleArgsT, typename TupleLocsT>
37 struct local_tuple : public TupleArgsT {
38 
39     typedef TupleLocsT local_vars_t;
40 
local_tuplephoenix::local_tuple41     local_tuple(TupleArgsT const& args, TupleLocsT const& locs_)
42     :   TupleArgsT(args), locs(locs_) {}
43 
44     mutable TupleLocsT locs;
45 };
46 
47 ///////////////////////////////////////////////////////////////////////////////
48 //
49 //  local_var_result
50 //
51 //      This is a return type computer. Given a constant integer N and a
52 //      tuple, get the Nth local variable type. If TupleT is not really
53 //      a local_tuple, we just return nil_t. Otherwise we get the Nth
54 //      local variable type.
55 //
56 ///////////////////////////////////////////////////////////////////////////////
57 template <int N, typename TupleT>
58 struct local_var_result {
59 
60     typedef nil_t type;
61 };
62 
63 //////////////////////////////////
64 template <int N, typename TupleArgsT, typename TupleLocsT>
65 struct local_var_result<N, local_tuple<TupleArgsT, TupleLocsT> > {
66 
67     typedef typename tuple_element<N, TupleLocsT>::type& type;
68 };
69 
70 ///////////////////////////////////////////////////////////////////////////////
71 //
72 //  local_var
73 //
74 //      This class looks so curiously like the argument class. local_var
75 //      provides access to the Nth local variable packed in the tuple
76 //      duo local_tuple above. Note that the member function eval
77 //      expects a local_tuple argument. Otherwise the expression
78 //      'tuple.locs' will fail (compile-time error). local_var
79 //      primitives only work within the context of a locals_composite
80 //      (see below).
81 //
82 //      Provided are some predefined local_var actors for 0..N local
83 //      variable access: loc1..locN.
84 //
85 ///////////////////////////////////////////////////////////////////////////////
86 template <int N>
87 struct local_var {
88 
89     template <typename TupleT>
90     struct result {
91 
92         typedef typename local_var_result<N, TupleT>::type type;
93     };
94 
95     template <typename TupleT>
96     typename local_var_result<N, TupleT>::type
evalphoenix::local_var97     eval(TupleT const& tuple) const
98     {
99         return tuple.locs[tuple_index<N>()];
100     }
101 };
102 
103 //////////////////////////////////
104 actor<local_var<0> > const loc1 = local_var<0>();
105 actor<local_var<1> > const loc2 = local_var<1>();
106 actor<local_var<2> > const loc3 = local_var<2>();
107 actor<local_var<3> > const loc4 = local_var<3>();
108 actor<local_var<4> > const loc5 = local_var<4>();
109 
110 ///////////////////////////////////////////////////////////////////////////////
111 //
112 //  locals_composite
113 //
114 //      This class encapsulates an actor and some local variable
115 //      initializers packed in a tuple.
116 //
117 //      locals_composite is just like a proxy and delegates the actual
118 //      evaluation to the actor. The actor does the actual work. In the
119 //      eval member function, before invoking the embedded actor's eval
120 //      member function, we first stuff an instance of our locals and
121 //      bundle both 'args' and 'locals' in a local_tuple. This
122 //      local_tuple instance is created in the stack initializing it
123 //      with our locals member. We then pass this local_tuple instance
124 //      as an argument to the actor's eval member function.
125 //
126 ///////////////////////////////////////////////////////////////////////////////
127 template <typename ActorT, typename LocsT>
128 struct locals_composite {
129 
130     typedef locals_composite<ActorT, LocsT> self_t;
131 
132     template <typename TupleT>
133     struct result { typedef typename actor_result<ActorT, TupleT>::type type; };
134 
locals_compositephoenix::locals_composite135     locals_composite(ActorT const& actor_, LocsT const& locals_)
136     :   actor(actor_), locals(locals_) {}
137 
138     template <typename TupleT>
139     typename actor_result<ActorT, TupleT>::type
evalphoenix::locals_composite140     eval(TupleT const& args) const
141     {
142         actor.eval(local_tuple<TupleT, LocsT>(args, locals));
143     }
144 
145     ActorT actor;
146     LocsT locals;
147 };
148 
149 ///////////////////////////////////////////////////////////////////////////////
150 //
151 //  locals_gen
152 //
153 //      At construction time, this class is given some local var-
154 //      initializers packed in a tuple. We just store this for later.
155 //      The operator[] of this class creates the actual locals_composite
156 //      given an actor. This is responsible for the construct
157 //      locals<types>[actor].
158 //
159 ///////////////////////////////////////////////////////////////////////////////
160 template <typename LocsT>
161 struct locals_gen {
162 
locals_genphoenix::locals_gen163     locals_gen(LocsT const& locals_)
164     :   locals(locals_) {}
165 
166     template <typename ActorT>
167     actor<locals_composite<typename as_actor<ActorT>::type, LocsT> >
operator []phoenix::locals_gen168     operator[](ActorT const& actor)
169     {
170         return locals_composite<typename as_actor<ActorT>::type, LocsT>
171             (as_actor<ActorT>::convert(actor), locals);
172     }
173 
174     LocsT locals;
175 };
176 
177 ///////////////////////////////////////////////////////////////////////////////
178 //
179 //    Front end generator functions. These generators are overloaded for
180 //    1..N local variables. locals<T0,... TN>(i0,...iN) generate locals_gen
181 //    objects (see above).
182 //
183 ///////////////////////////////////////////////////////////////////////////////
184 template <typename T0>
185 inline locals_gen<tuple<T0> >
locals(T0 const & _0=T0 ())186 locals(
187     T0 const& _0 = T0()
188 )
189 {
190     typedef tuple<T0> tuple_t;
191     return locals_gen<tuple_t>(tuple_t(_0));
192 }
193 
194 //////////////////////////////////
195 template <typename T0, typename T1>
196 inline locals_gen<tuple<T0, T1> >
locals(T0 const & _0=T0 (),T1 const & _1=T1 ())197 locals(
198     T0 const& _0 = T0(),
199     T1 const& _1 = T1()
200 )
201 {
202     typedef tuple<T0, T1> tuple_t;
203     return locals_gen<tuple_t>(tuple_t(_0, _1));
204 }
205 
206 //////////////////////////////////
207 template <typename T0, typename T1, typename T2>
208 inline locals_gen<tuple<T0, T1, T2> >
locals(T0 const & _0=T0 (),T1 const & _1=T1 (),T2 const & _2=T2 ())209 locals(
210     T0 const& _0 = T0(),
211     T1 const& _1 = T1(),
212     T2 const& _2 = T2()
213 )
214 {
215     typedef tuple<T0, T1, T2> tuple_t;
216     return locals_gen<tuple_t>(tuple_t(_0, _1, _2));
217 }
218 
219 //////////////////////////////////
220 template <typename T0, typename T1, typename T2, typename T3>
221 inline locals_gen<tuple<T0, T1, T2, T3> >
locals(T0 const & _0=T0 (),T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=T3 ())222 locals(
223     T0 const& _0 = T0(),
224     T1 const& _1 = T1(),
225     T2 const& _2 = T2(),
226     T3 const& _3 = T3()
227 )
228 {
229     typedef tuple<T0, T1, T2, T3> tuple_t;
230     return locals_gen<tuple_t>(tuple_t(_0, _1, _2, _3));
231 }
232 
233 //////////////////////////////////
234 template <typename T0, typename T1, typename T2, typename T3, typename T4>
235 inline locals_gen<tuple<T0, T1, T2, T3, T4> >
locals(T0 const & _0=T0 (),T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=T3 (),T4 const & _4=T4 ())236 locals(
237     T0 const& _0 = T0(),
238     T1 const& _1 = T1(),
239     T2 const& _2 = T2(),
240     T3 const& _3 = T3(),
241     T4 const& _4 = T4()
242 )
243 {
244     typedef tuple<T0, T1, T2, T3> tuple_t;
245     return locals_gen<tuple_t>(tuple_t(_0, _1, _2, _3, _4));
246 }
247 
248 ///////////////////////////////////////////////////////////////////////////////
249 }
250 
251 //////////////////////////////////
252 using namespace std;
253 using namespace phoenix;
254 
255 //////////////////////////////////
256 int
main()257 main()
258 {
259     int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
260     vector<int> c(init, init + 10);
261     typedef vector<int>::iterator iterator;
262 
263     for_each(c.begin(), c.end(),
264         locals<int, char const*>(0, "...That's all\n")
265         [
266             for_(loc1 = 0, loc1 < arg1, ++loc1)
267             [
268                 cout << loc1 << ", "
269             ],
270             cout << loc2
271         ]
272     );
273 
274     return 0;
275 }
276