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 | |
---|
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 | typedef TupleArgsT parent_t; |
---|
41 | |
---|
42 | local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) |
---|
43 | : TupleArgsT(args), locs(locs_) {} |
---|
44 | |
---|
45 | TupleArgsT& parent() { return *this; } |
---|
46 | TupleArgsT const& parent() const { return *this; } |
---|
47 | |
---|
48 | mutable TupleLocsT locs; |
---|
49 | }; |
---|
50 | |
---|
51 | /////////////////////////////////////////////////////////////////////////////// |
---|
52 | // |
---|
53 | // local_var_result |
---|
54 | // |
---|
55 | // This is a return type computer. Given a constant integer N, a |
---|
56 | // parent index and a tuple, get the Nth local variable type. The |
---|
57 | // parent index is an integer specifying which parent scope to |
---|
58 | // access; 0==current scope, 1==parent scope, 2==parent's parent |
---|
59 | // scope. |
---|
60 | // |
---|
61 | // This is a metaprogram with partial specializations. There is a |
---|
62 | // general case, a special case for local_tuples and a terminating |
---|
63 | // special case for local_tuples. |
---|
64 | // |
---|
65 | // General case: If TupleT is not really a local_tuple, we just return nil_t. |
---|
66 | // |
---|
67 | // local_tuples case: |
---|
68 | // Parent index is 0: We get the Nth local variable. |
---|
69 | // Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT> |
---|
70 | // |
---|
71 | /////////////////////////////////////////////////////////////////////////////// |
---|
72 | template <int N, int Parent, typename TupleT> |
---|
73 | struct local_var_result { |
---|
74 | |
---|
75 | typedef nil_t type; |
---|
76 | }; |
---|
77 | |
---|
78 | ////////////////////////////////// |
---|
79 | template <int N, int Parent, typename TupleArgsT, typename TupleLocsT> |
---|
80 | struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> > |
---|
81 | : public local_var_result<N, Parent-1, TupleArgsT> {}; |
---|
82 | |
---|
83 | ////////////////////////////////// |
---|
84 | template <int N, typename TupleArgsT, typename TupleLocsT> |
---|
85 | struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { |
---|
86 | |
---|
87 | typedef typename tuple_element< |
---|
88 | N, TupleLocsT |
---|
89 | >::type& type; |
---|
90 | |
---|
91 | static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple) |
---|
92 | { return tuple.locs[tuple_index<N>()]; } |
---|
93 | }; |
---|
94 | |
---|
95 | /////////////////////////////////////////////////////////////////////////////// |
---|
96 | // |
---|
97 | // local_var |
---|
98 | // |
---|
99 | // This class looks so curiously like the argument class. local_var |
---|
100 | // provides access to the Nth local variable packed in the tuple |
---|
101 | // duo local_tuple above. Parent specifies the Nth parent scope. |
---|
102 | // 0==current scope, 1==parent scope, 2==parent's parent scope. The |
---|
103 | // member function parent<N>() may be called to provide access to |
---|
104 | // outer scopes. |
---|
105 | // |
---|
106 | // Note that the member function eval expects a local_tuple |
---|
107 | // argument. Otherwise there will be acompile-time error. local_var |
---|
108 | // primitives only work within the context of a context_composite |
---|
109 | // (see below). |
---|
110 | // |
---|
111 | // Provided are some predefined local_var actors for 0..N local |
---|
112 | // variable access: loc1..locN. |
---|
113 | // |
---|
114 | /////////////////////////////////////////////////////////////////////////////// |
---|
115 | template <int N, int Parent = 0> |
---|
116 | struct local_var { |
---|
117 | |
---|
118 | template <typename TupleT> |
---|
119 | struct result { |
---|
120 | |
---|
121 | typedef typename local_var_result<N, Parent, TupleT>::type type; |
---|
122 | }; |
---|
123 | |
---|
124 | template <typename TupleT> |
---|
125 | typename local_var_result<N, Parent, TupleT>::type |
---|
126 | eval(TupleT const& tuple) const |
---|
127 | { |
---|
128 | return local_var_result<N, Parent, TupleT>::get(tuple); |
---|
129 | } |
---|
130 | |
---|
131 | template <int PIndex> |
---|
132 | actor<local_var<N, Parent+PIndex> > |
---|
133 | parent() const |
---|
134 | { |
---|
135 | return local_var<N, Parent+PIndex>(); |
---|
136 | } |
---|
137 | }; |
---|
138 | |
---|
139 | ////////////////////////////////// |
---|
140 | namespace locals { |
---|
141 | |
---|
142 | actor<local_var<0> > const result = local_var<0>(); |
---|
143 | actor<local_var<1> > const loc1 = local_var<1>(); |
---|
144 | actor<local_var<2> > const loc2 = local_var<2>(); |
---|
145 | actor<local_var<3> > const loc3 = local_var<3>(); |
---|
146 | actor<local_var<4> > const loc4 = local_var<4>(); |
---|
147 | } |
---|
148 | |
---|
149 | /////////////////////////////////////////////////////////////////////////////// |
---|
150 | // |
---|
151 | // context_composite |
---|
152 | // |
---|
153 | // This class encapsulates an actor and some local variable |
---|
154 | // initializers packed in a tuple. |
---|
155 | // |
---|
156 | // context_composite is just like a proxy and delegates the actual |
---|
157 | // evaluation to the actor. The actor does the actual work. In the |
---|
158 | // eval member function, before invoking the embedded actor's eval |
---|
159 | // member function, we first stuff an instance of our locals and |
---|
160 | // bundle both 'args' and 'locals' in a local_tuple. This |
---|
161 | // local_tuple instance is created in the stack initializing it |
---|
162 | // with our locals member. We then pass this local_tuple instance |
---|
163 | // as an argument to the actor's eval member function. |
---|
164 | // |
---|
165 | /////////////////////////////////////////////////////////////////////////////// |
---|
166 | template <typename ActorT, typename LocsT> |
---|
167 | struct context_composite { |
---|
168 | |
---|
169 | typedef context_composite<ActorT, LocsT> self_t; |
---|
170 | |
---|
171 | template <typename TupleT> |
---|
172 | struct result { typedef typename tuple_element<0, LocsT>::type type; }; |
---|
173 | |
---|
174 | context_composite(ActorT const& actor_, LocsT const& locals_) |
---|
175 | : actor(actor_), locals(locals_) {} |
---|
176 | |
---|
177 | template <typename TupleT> |
---|
178 | typename tuple_element<0, LocsT>::type |
---|
179 | eval(TupleT const& args) const |
---|
180 | { |
---|
181 | local_tuple<TupleT, LocsT> local_context(args, locals); |
---|
182 | actor.eval(local_context); |
---|
183 | return local_context.locs[tuple_index<0>()]; |
---|
184 | } |
---|
185 | |
---|
186 | ActorT actor; |
---|
187 | LocsT locals; |
---|
188 | }; |
---|
189 | |
---|
190 | /////////////////////////////////////////////////////////////////////////////// |
---|
191 | // |
---|
192 | // context_gen |
---|
193 | // |
---|
194 | // At construction time, this class is given some local var- |
---|
195 | // initializers packed in a tuple. We just store this for later. |
---|
196 | // The operator[] of this class creates the actual context_composite |
---|
197 | // given an actor. This is responsible for the construct |
---|
198 | // context<types>[actor]. |
---|
199 | // |
---|
200 | /////////////////////////////////////////////////////////////////////////////// |
---|
201 | template <typename LocsT> |
---|
202 | struct context_gen { |
---|
203 | |
---|
204 | context_gen(LocsT const& locals_) |
---|
205 | : locals(locals_) {} |
---|
206 | |
---|
207 | template <typename ActorT> |
---|
208 | actor<context_composite<typename as_actor<ActorT>::type, LocsT> > |
---|
209 | operator[](ActorT const& actor) |
---|
210 | { |
---|
211 | return context_composite<typename as_actor<ActorT>::type, LocsT> |
---|
212 | (as_actor<ActorT>::convert(actor), locals); |
---|
213 | } |
---|
214 | |
---|
215 | LocsT locals; |
---|
216 | }; |
---|
217 | |
---|
218 | /////////////////////////////////////////////////////////////////////////////// |
---|
219 | // |
---|
220 | // Front end generator functions. These generators are overloaded for |
---|
221 | // 1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen |
---|
222 | // objects (see above). |
---|
223 | // |
---|
224 | /////////////////////////////////////////////////////////////////////////////// |
---|
225 | template <typename T0> |
---|
226 | inline context_gen<tuple<T0> > |
---|
227 | context() |
---|
228 | { |
---|
229 | typedef tuple<T0> tuple_t; |
---|
230 | return context_gen<tuple_t>(tuple_t(T0())); |
---|
231 | } |
---|
232 | |
---|
233 | ////////////////////////////////// |
---|
234 | template <typename T0, typename T1> |
---|
235 | inline context_gen<tuple<T0, T1> > |
---|
236 | context( |
---|
237 | T1 const& _1 = T1() |
---|
238 | ) |
---|
239 | { |
---|
240 | typedef tuple<T0, T1> tuple_t; |
---|
241 | return context_gen<tuple_t>(tuple_t(T0(), _1)); |
---|
242 | } |
---|
243 | |
---|
244 | ////////////////////////////////// |
---|
245 | template <typename T0, typename T1, typename T2> |
---|
246 | inline context_gen<tuple<T0, T1, T2> > |
---|
247 | context( |
---|
248 | T1 const& _1 = T1(), |
---|
249 | T2 const& _2 = T2() |
---|
250 | ) |
---|
251 | { |
---|
252 | typedef tuple<T0, T1, T2> tuple_t; |
---|
253 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2)); |
---|
254 | } |
---|
255 | |
---|
256 | ////////////////////////////////// |
---|
257 | template <typename T0, typename T1, typename T2, typename T3> |
---|
258 | inline context_gen<tuple<T0, T1, T2, T3> > |
---|
259 | context( |
---|
260 | T1 const& _1 = T1(), |
---|
261 | T2 const& _2 = T2(), |
---|
262 | T3 const& _3 = T3() |
---|
263 | ) |
---|
264 | { |
---|
265 | typedef tuple<T0, T1, T2, T3> tuple_t; |
---|
266 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3)); |
---|
267 | } |
---|
268 | |
---|
269 | ////////////////////////////////// |
---|
270 | template <typename T0, typename T1, typename T2, typename T3, typename T4> |
---|
271 | inline context_gen<tuple<T0, T1, T2, T3, T4> > |
---|
272 | context( |
---|
273 | T1 const& _1 = T1(), |
---|
274 | T2 const& _2 = T2(), |
---|
275 | T3 const& _3 = T3(), |
---|
276 | T4 const& _4 = T4() |
---|
277 | ) |
---|
278 | { |
---|
279 | typedef tuple<T0, T1, T2, T3> tuple_t; |
---|
280 | return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4)); |
---|
281 | } |
---|
282 | |
---|
283 | /////////////////////////////////////////////////////////////////////////////// |
---|
284 | } |
---|
285 | |
---|
286 | ////////////////////////////////// |
---|
287 | using namespace std; |
---|
288 | using namespace phoenix; |
---|
289 | using namespace phoenix::locals; |
---|
290 | |
---|
291 | ////////////////////////////////// |
---|
292 | int |
---|
293 | main() |
---|
294 | { |
---|
295 | context<nil_t>(1) |
---|
296 | [ |
---|
297 | cout << loc1 << '\n', |
---|
298 | context<nil_t>(2) |
---|
299 | [ |
---|
300 | cout << loc1.parent<1>() << ' ' << loc1 << '\n', |
---|
301 | context<nil_t>(3) |
---|
302 | [ |
---|
303 | cout << loc1.parent<2>() << ' ' << loc1.parent<1>() << ' ' << loc1 << '\n' |
---|
304 | ] |
---|
305 | ] |
---|
306 | ] |
---|
307 | |
---|
308 | (); |
---|
309 | |
---|
310 | return 0; |
---|
311 | } |
---|