Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / phoenix / core / environment.hpp
1 /*==============================================================================
2     Copyright (c) 2005-2010 Joel de Guzman
3     Copyright (c) 2010-2011 Thomas Heller
4
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #ifndef BOOST_PHOENIX_CORE_ENVIRONMENT_HPP
9 #define BOOST_PHOENIX_CORE_ENVIRONMENT_HPP
10
11 #include <boost/phoenix/core/limits.hpp>
12 #include <boost/fusion/sequence/intrinsic/at.hpp>
13 #include <boost/fusion/support/is_sequence.hpp>
14 #include <boost/phoenix/support/vector.hpp>
15 #include <boost/proto/transform/impl.hpp>
16 #include <boost/utility/enable_if.hpp>
17 #include <boost/utility/result_of.hpp>
18
19 #include <typeinfo>
20
21 namespace boost { namespace phoenix 
22 {
23     struct unused {};
24
25     namespace result_of
26     {
27         template <typename Env, typename Actions>
28         struct context
29         {
30             typedef vector2<Env, Actions> type;
31         };
32         
33         template <typename Env, typename Actions>
34         struct make_context
35             : context<Env, Actions>
36         {};
37
38         template <typename Context>
39         struct env
40         {
41             typedef
42                 typename fusion::result_of::at_c<
43                     typename boost::remove_reference<Context>::type
44                   , 0
45                 >::type
46                 type;
47         };
48         
49         template <typename Context>
50         struct actions
51         {
52             typedef
53                 typename fusion::result_of::at_c<
54                     typename boost::remove_reference<Context>::type
55                   , 1
56                 >::type
57                 type;
58         };
59     }
60
61     namespace functional
62     {
63         struct context
64         {
65             BOOST_PROTO_CALLABLE()
66
67             template <typename Sig>
68             struct result;
69
70             template <typename This, typename Env, typename Actions>
71             struct result<This(Env, Actions)>
72                 : result<This(Env const &, Actions const &)>
73             {};
74
75             template <typename This, typename Env, typename Actions>
76             struct result<This(Env &, Actions)>
77                 : result<This(Env &, Actions const &)>
78             {};
79
80             template <typename This, typename Env, typename Actions>
81             struct result<This(Env, Actions &)>
82                 : result<This(Env const &, Actions &)>
83             {};
84
85             template <typename This, typename Env, typename Actions>
86             struct result<This(Env &, Actions &)>
87                 : result_of::context<Env &, Actions &>
88             {};
89
90             template <typename Env, typename Actions>
91             typename result_of::context<Env &, Actions &>::type
92             operator()(Env & env, Actions & actions) const
93             {
94                 vector2<Env &, Actions &> e = {env, actions};
95                 return e;
96             }
97
98             template <typename Env, typename Actions>
99             typename result_of::context<Env const &, Actions &>::type
100             operator()(Env const & env, Actions & actions) const
101             {
102                 vector2<Env const &, Actions &> e = {env, actions};
103                 return e;
104             }
105
106             template <typename Env, typename Actions>
107             typename result_of::context<Env &, Actions const &>::type
108             operator()(Env & env, Actions const & actions) const
109             {
110                 vector2<Env &, Actions const &> e = {env, actions};
111                 return e;
112             }
113
114             template <typename Env, typename Actions>
115             typename result_of::context<Env const &, Actions const &>::type
116             operator()(Env const & env, Actions const & actions) const
117             {
118                 vector2<Env const&, Actions const &> e = {env, actions};
119                 return e;
120             }
121         };
122
123         struct make_context
124             : context
125         {};
126
127         struct env
128         {
129             BOOST_PROTO_CALLABLE()
130
131             template <typename Sig>
132             struct result;
133
134             template <typename This, typename Context>
135             struct result<This(Context)>
136                 : result<This(Context const &)>
137             {};
138
139             template <typename This, typename Context>
140             struct result<This(Context &)>
141                 : result_of::env<Context>
142             {};
143
144             template <typename Context>
145             typename result_of::env<Context const>::type
146             operator()(Context const & ctx) const
147             {
148                 return fusion::at_c<0>(ctx);
149             }
150
151             template <typename Context>
152             typename result_of::env<Context>::type
153             operator()(Context & ctx) const
154             {
155                 return fusion::at_c<0>(ctx);
156             }
157         };
158         
159         struct actions
160         {
161             BOOST_PROTO_CALLABLE()
162
163             template <typename Sig>
164             struct result;
165
166             template <typename This, typename Context>
167             struct result<This(Context)>
168                 : result<This(Context const &)>
169             {};
170
171             template <typename This, typename Context>
172             struct result<This(Context &)>
173                 : result_of::actions<Context>
174             {};
175
176             template <typename Context>
177             typename result_of::actions<Context const>::type
178             operator()(Context const & ctx) const
179             {
180                 return fusion::at_c<1>(ctx);
181             }
182
183             template <typename Context>
184             typename result_of::actions<Context>::type
185             operator()(Context & ctx) const
186             {
187                 return fusion::at_c<1>(ctx);
188             }
189         };
190
191     }
192
193     struct _context
194         : proto::transform<_context>
195     {
196         template <typename Expr, typename State, typename Data>
197         struct impl
198             : proto::transform_impl<Expr, State, Data>
199         {
200             typedef vector2<State, Data> result_type;
201
202             result_type operator()(
203                 typename impl::expr_param
204               , typename impl::state_param s
205               , typename impl::data_param d
206             ) const
207             {
208                 vector2<State, Data> e = {s, d};
209                 return e;
210             }
211         };
212     };
213
214     template <typename Env, typename Actions>
215     inline
216     typename result_of::context<Env const &, Actions const&>::type const
217     context(Env const& env, Actions const& actions)
218     {
219         vector2<Env const&, Actions const &> e = {env, actions};
220         return e;
221     }
222
223     template <typename Env, typename Actions>
224     inline
225     typename result_of::context<Env const &, Actions const&>::type const
226     make_context(Env const& env, Actions const& actions)
227     {
228         return context(env, actions);
229     }
230
231     template <typename Env, typename Actions>
232     inline
233     typename result_of::context<Env &, Actions const&>::type const
234     context(Env & env, Actions const& actions)
235     {
236         vector2<Env &, Actions const &> e = {env, actions};
237         return e;
238     }
239     
240     template <typename Env, typename Actions>
241     inline
242     typename result_of::context<Env &, Actions const&>::type const
243     make_context(Env & env, Actions const& actions)
244     {
245         return context(env, actions);
246     }
247
248     template <typename Env, typename Actions>
249     inline
250     typename result_of::context<Env const &, Actions &>::type const
251     context(Env const& env, Actions & actions)
252     {
253         vector2<Env const&, Actions &> e = {env, actions};
254         return e;
255     }
256     
257     template <typename Env, typename Actions>
258     inline
259     typename result_of::context<Env const &, Actions &>::type const
260     make_context(Env const& env, Actions & actions)
261     {
262         return context(env, actions);
263     }
264     
265     template <typename Env, typename Actions>
266     inline
267     typename result_of::context<Env &, Actions &>::type const
268     context(Env & env, Actions & actions)
269     {
270         vector2<Env &, Actions &> e = {env, actions};
271         return e;
272     }
273     
274     template <typename Env, typename Actions>
275     inline
276     typename result_of::context<Env &, Actions &>::type const
277     make_context(Env & env, Actions & actions)
278     {
279         return context(env, actions);
280     }
281
282     struct _env
283         : proto::transform<_env>
284     {
285         template <typename Expr, typename State, typename Data>
286         struct impl
287             : proto::transform_impl<Expr, State, Data>
288         {
289             typedef State result_type;
290
291             result_type operator()(
292                 typename impl::expr_param
293               , typename impl::state_param s
294               , typename impl::data_param
295             ) const
296             {
297                 return s;
298             }
299         };
300     };
301
302     template <typename Expr, typename State>
303     struct _env::impl<Expr, State, proto::empty_env>
304         : proto::transform_impl<Expr, State, proto::empty_env>
305     {
306             typedef
307                 typename fusion::result_of::at_c<
308                     typename boost::remove_reference<State>::type
309                   , 0
310                 >::type
311                 result_type;
312
313             result_type operator()(
314                 typename impl::expr_param
315               , typename impl::state_param s
316               , typename impl::data_param
317             ) const
318             {
319                 return fusion::at_c<0>(s);
320             }
321     };
322
323     template <typename Expr, typename State>
324     struct _env::impl<Expr, State, unused>
325         : _env::impl<Expr, State, proto::empty_env>
326     {};
327
328     template <typename Context>
329     inline
330     typename fusion::result_of::at_c<Context, 0>::type
331     env(Context & ctx)
332     {
333         return fusion::at_c<0>(ctx);
334     }
335
336     template <typename Context>
337     inline
338     typename fusion::result_of::at_c<Context const, 0>::type
339     env(Context const & ctx)
340     {
341         return fusion::at_c<0>(ctx);
342     }
343
344     struct _actions
345         : proto::transform<_actions>
346     {
347         template <typename Expr, typename State, typename Data>
348         struct impl
349             : proto::transform_impl<Expr, State, Data>
350         {
351             typedef Data result_type;
352
353             result_type operator()(
354                 typename impl::expr_param
355               , typename impl::state_param
356               , typename impl::data_param d
357             ) const
358             {
359                 return d;
360             }
361         };
362     };
363
364     template <typename Expr, typename State>
365     struct _actions::impl<Expr, State, proto::empty_env>
366         : proto::transform_impl<Expr, State, proto::empty_env>
367     {
368             typedef
369                 typename fusion::result_of::at_c<
370                     typename boost::remove_reference<State>::type
371                   , 1
372                 >::type
373                 result_type;
374
375             result_type operator()(
376                 typename impl::expr_param
377               , typename impl::state_param s
378               , typename impl::data_param
379             ) const
380             {
381                 return fusion::at_c<1>(s);
382             }
383     };
384
385     template <typename Expr, typename State>
386     struct _actions::impl<Expr, State, unused>
387         : _actions::impl<Expr, State, proto::empty_env>
388     {};
389
390     template <typename Context>
391     inline
392     typename fusion::result_of::at_c<Context, 1>::type
393     actions(Context & ctx)
394     {
395         return fusion::at_c<1>(ctx);
396     }
397
398     template <typename Context>
399     inline
400     typename fusion::result_of::at_c<Context const, 1>::type
401     actions(Context const & ctx)
402     {
403         return fusion::at_c<1>(ctx);
404     }
405
406     namespace result_of
407     {
408         template <
409             BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
410                 BOOST_PHOENIX_LIMIT
411               , typename A
412               , mpl::void_
413             )
414           , typename Dummy = void
415         >
416         struct make_env;
417         
418     #define M0(Z, N, D)                                                         \
419         template <BOOST_PHOENIX_typename_A(N)>                                  \
420         struct make_env<BOOST_PHOENIX_A(N)>                                     \
421         {                                                                       \
422             typedef BOOST_PP_CAT(vector, N)<BOOST_PHOENIX_A(N)> type;           \
423         };                                                                      \
424     /**/
425         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
426     #undef M0
427     }
428
429     inline
430     result_of::make_env<>::type
431     make_env()
432     {
433         return result_of::make_env<>::type();
434     }
435 #define M0(Z, N, D)                                                             \
436     template <BOOST_PHOENIX_typename_A(N)>                                      \
437     inline                                                                      \
438     typename result_of::make_env<BOOST_PHOENIX_A_ref(N)>::type                  \
439     make_env(BOOST_PHOENIX_A_ref_a(N))                                          \
440     {                                                                           \
441         typename result_of::make_env<BOOST_PHOENIX_A_ref(N)>::type              \
442             env =                                                               \
443             {                                                                   \
444                 BOOST_PHOENIX_a(N)                                              \
445             };                                                                  \
446         return env;                                                             \
447     }                                                                           \
448     template <BOOST_PHOENIX_typename_A(N)>                                      \
449     inline                                                                      \
450     typename result_of::make_env<BOOST_PHOENIX_A_const_ref(N)>::type            \
451     make_env(BOOST_PHOENIX_A_const_ref_a(N))                                    \
452     {                                                                           \
453         typename result_of::make_env<BOOST_PHOENIX_A_const_ref(N)>::type        \
454             env =                                                               \
455             {                                                                   \
456                 BOOST_PHOENIX_a(N)                                              \
457             };                                                                  \
458         return env;                                                             \
459     }                                                                           \
460     /**/
461         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
462     #undef M0
463
464     template <typename T, typename Enable = void>
465     struct is_environment : fusion::traits::is_sequence<T> {};
466 }}
467
468 #endif
469