]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/classic/phoenix/example/fundamental/sample10.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / spirit / classic / phoenix / example / fundamental / sample10.cpp
CommitLineData
7c673cae
FG
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#include <boost/spirit/include/phoenix1_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
20effc67 483#if !defined(__BORLANDC__) || defined(__clang__)
7c673cae
FG
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}