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