Imported Upstream version 1.51.0
[platform/upstream/boost.git] / boost / spirit / home / phoenix / scope / let.hpp
1 /*=============================================================================
2     Copyright (c) 2001-2007 Joel de Guzman
3     Copyright (c) 2004 Daniel Wallin
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 PHOENIX_SCOPE_LET_HPP
9 #define PHOENIX_SCOPE_LET_HPP
10
11 #include <boost/spirit/home/phoenix/core/limits.hpp>
12 #include <boost/spirit/home/phoenix/core/composite.hpp>
13 #include <boost/spirit/home/phoenix/scope/scoped_environment.hpp>
14 #include <boost/spirit/home/phoenix/scope/detail/local_variable.hpp>
15 #include <boost/spirit/home/phoenix/detail/local_reference.hpp>
16 #include <boost/spirit/home/phoenix/core/actor.hpp>
17 #include <boost/fusion/include/transform.hpp>
18 #include <boost/fusion/include/as_vector.hpp>
19 #include <boost/mpl/eval_if.hpp>
20 #include <boost/mpl/bool.hpp>
21
22 namespace boost { namespace phoenix
23 {
24     template <typename Base, typename Vars, typename Map>
25     struct let_actor : Base
26     {
27         typedef typename
28             mpl::fold<
29                 Vars
30               , mpl::false_
31               , detail::compute_no_nullary
32             >::type
33         no_nullary;
34         
35         template <typename Env>
36         struct result
37         {
38             typedef typename 
39                 fusion::result_of::as_vector<
40                     typename fusion::result_of::transform<
41                         Vars
42                       , detail::initialize_local<Env>
43                     >::type
44                 >::type 
45             locals_type;
46
47             typedef typename Base::template
48                 result<scoped_environment<Env, Env, locals_type, Map> >::type
49             result_type;
50             
51             typedef typename 
52                 detail::unwrap_local_reference<result_type>::type 
53             type;
54         };
55
56         let_actor(Base const& base, Vars const& vars)
57             : Base(base), vars(vars) {}
58
59         template <typename Env>
60         typename result<Env>::type
61         eval(Env const& env) const
62         {
63             typedef typename 
64                 fusion::result_of::as_vector<
65                     typename fusion::result_of::transform<
66                         Vars
67                       , detail::initialize_local<Env>
68                     >::type
69                 >::type 
70             locals_type;
71
72             locals_type locals = 
73                 fusion::as_vector(
74                     fusion::transform(
75                         vars
76                       , detail::initialize_local<Env>(env)));
77             
78             typedef typename result<Env>::type RT;
79             return RT(Base::eval(
80                 scoped_environment<Env, Env, locals_type, Map>(
81                     env
82                   , env
83                   , locals)));
84         }
85
86         Vars vars;
87     };
88     
89     template <typename Vars, typename Map>
90     struct let_actor_gen
91     {
92         template <typename Base>
93         actor<let_actor<Base, Vars, Map> > const
94         operator[](actor<Base> const& base) const
95         {
96             return let_actor<Base, Vars, Map>(base, vars);
97         }
98
99         let_actor_gen(Vars const& vars)
100             : vars(vars) {}
101
102         Vars vars;
103     };
104
105     template <typename Key>
106     struct local_variable; // forward
107     struct assign_eval; // forward
108
109     struct let_gen
110     {
111         template <typename K0, typename V0>
112         let_actor_gen<
113             fusion::vector<V0>
114           , detail::map_local_index_to_tuple<K0>
115         >
116         operator()(
117             actor<composite<assign_eval, fusion::vector<local_variable<K0>, V0> > > const& a0
118         ) const
119         {
120             return fusion::vector<V0>(fusion::at_c<1>(a0));
121         }
122     
123         template <typename K0, typename K1, typename V0, typename V1>
124         let_actor_gen<
125             fusion::vector<V0, V1>
126           , detail::map_local_index_to_tuple<K0, K1>
127         >
128         operator()(
129             actor<composite<assign_eval, fusion::vector<local_variable<K0>, V0> > > const& a0
130           , actor<composite<assign_eval, fusion::vector<local_variable<K1>, V1> > > const& a1
131         ) const
132         {
133             return fusion::vector<V0, V1>(fusion::at_c<1>(a0), fusion::at_c<1>(a1));
134         }
135         
136         // Bring in the rest...
137         #define PHOENIX_LOCAL_GEN_NAME let_actor_gen
138         #include <boost/spirit/home/phoenix/scope/detail/local_gen.hpp>
139         #undef PHOENIX_LOCAL_GEN_NAME
140     };
141
142     let_gen const let = let_gen();
143 }}
144
145 #endif