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 context_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 namespace locals {
105
106 actor<local_var<0> > const result = local_var<0>();
107 actor<local_var<1> > const loc1 = local_var<1>();
108 actor<local_var<2> > const loc2 = local_var<2>();
109 actor<local_var<3> > const loc3 = local_var<3>();
110 actor<local_var<4> > const loc4 = local_var<4>();
111 }
112
113 ///////////////////////////////////////////////////////////////////////////////
114 //
115 // context_composite
116 //
117 // This class encapsulates an actor and some local variable
118 // initializers packed in a tuple.
119 //
120 // context_composite is just like a proxy and delegates the actual
121 // evaluation to the actor. The actor does the actual work. In the
122 // eval member function, before invoking the embedded actor's eval
123 // member function, we first stuff an instance of our locals and
124 // bundle both 'args' and 'locals' in a local_tuple. This
125 // local_tuple instance is created in the stack initializing it
126 // with our locals member. We then pass this local_tuple instance
127 // as an argument to the actor's eval member function.
128 //
129 ///////////////////////////////////////////////////////////////////////////////
130 template <typename ActorT, typename LocsT>
131 struct context_composite {
132
133 typedef context_composite<ActorT, LocsT> self_t;
134
135 template <typename TupleT>
136 struct result { typedef typename tuple_element<0, LocsT>::type type; };
137
context_compositephoenix::context_composite138 context_composite(ActorT const& actor_, LocsT const& locals_)
139 : actor(actor_), locals(locals_) {}
140
141 template <typename TupleT>
142 typename tuple_element<0, LocsT>::type
evalphoenix::context_composite143 eval(TupleT const& args) const
144 {
145 local_tuple<TupleT, LocsT> local_context(args, locals);
146 actor.eval(local_context);
147 return local_context.locs[tuple_index<0>()];
148 }
149
150 ActorT actor;
151 LocsT locals;
152 };
153
154 ///////////////////////////////////////////////////////////////////////////////
155 //
156 // context_gen
157 //
158 // At construction time, this class is given some local var-
159 // initializers packed in a tuple. We just store this for later.
160 // The operator[] of this class creates the actual context_composite
161 // given an actor. This is responsible for the construct
162 // context<types>[actor].
163 //
164 ///////////////////////////////////////////////////////////////////////////////
165 template <typename LocsT>
166 struct context_gen {
167
context_genphoenix::context_gen168 context_gen(LocsT const& locals_)
169 : locals(locals_) {}
170
171 template <typename ActorT>
172 actor<context_composite<typename as_actor<ActorT>::type, LocsT> >
operator []phoenix::context_gen173 operator[](ActorT const& actor)
174 {
175 return context_composite<typename as_actor<ActorT>::type, LocsT>
176 (as_actor<ActorT>::convert(actor), locals);
177 }
178
179 LocsT locals;
180 };
181
182 ///////////////////////////////////////////////////////////////////////////////
183 //
184 // Front end generator functions. These generators are overloaded for
185 // 1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen
186 // objects (see above).
187 //
188 ///////////////////////////////////////////////////////////////////////////////
189 template <typename T0>
190 inline context_gen<tuple<T0> >
context()191 context()
192 {
193 typedef tuple<T0> tuple_t;
194 return context_gen<tuple_t>(tuple_t(T0()));
195 }
196
197 //////////////////////////////////
198 template <typename T0, typename T1>
199 inline context_gen<tuple<T0, T1> >
context(T1 const & _1=T1 ())200 context(
201 T1 const& _1 = T1()
202 )
203 {
204 typedef tuple<T0, T1> tuple_t;
205 return context_gen<tuple_t>(tuple_t(T0(), _1));
206 }
207
208 //////////////////////////////////
209 template <typename T0, typename T1, typename T2>
210 inline context_gen<tuple<T0, T1, T2> >
context(T1 const & _1=T1 (),T2 const & _2=T2 ())211 context(
212 T1 const& _1 = T1(),
213 T2 const& _2 = T2()
214 )
215 {
216 typedef tuple<T0, T1, T2> tuple_t;
217 return context_gen<tuple_t>(tuple_t(T0(), _1, _2));
218 }
219
220 //////////////////////////////////
221 template <typename T0, typename T1, typename T2, typename T3>
222 inline context_gen<tuple<T0, T1, T2, T3> >
context(T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=T3 ())223 context(
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 context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3));
231 }
232
233 //////////////////////////////////
234 template <typename T0, typename T1, typename T2, typename T3, typename T4>
235 inline context_gen<tuple<T0, T1, T2, T3, T4> >
context(T1 const & _1=T1 (),T2 const & _2=T2 (),T3 const & _3=T3 (),T4 const & _4=T4 ())236 context(
237 T1 const& _1 = T1(),
238 T2 const& _2 = T2(),
239 T3 const& _3 = T3(),
240 T4 const& _4 = T4()
241 )
242 {
243 typedef tuple<T0, T1, T2, T3> tuple_t;
244 return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4));
245 }
246
247 ///////////////////////////////////////////////////////////////////////////////
248 }
249
250 //////////////////////////////////
251 using namespace std;
252 using namespace phoenix;
253 using namespace phoenix::locals;
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 // find the first element > 5, print each element
264 // as we traverse the container c. Print the result
265 // if one is found.
266
267 find_if(c.begin(), c.end(),
268 context<bool>()
269 [
270 cout << arg1,
271 result = arg1 > 5,
272 if_(!result)
273 [
274 cout << val(", ")
275 ]
276 .else_
277 [
278 cout << val(" found result == ") << arg1
279 ]
280 ]
281 );
282
283 return 0;
284 }
285