Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2007 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2004 Daniel Wallin
|
Chris@16
|
4 Copyright (c) 2011 Thomas Heller
|
Chris@16
|
5
|
Chris@16
|
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 ==============================================================================*/
|
Chris@16
|
9 #ifndef PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
|
Chris@16
|
10 #define PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/mpl/int.hpp>
|
Chris@16
|
13 #include <boost/mpl/bool.hpp>
|
Chris@16
|
14 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
15 #include <boost/mpl/identity.hpp>
|
Chris@16
|
16 #include <boost/fusion/include/at.hpp>
|
Chris@16
|
17 #include <boost/fusion/include/value_at.hpp>
|
Chris@16
|
18 #include <boost/preprocessor/enum.hpp>
|
Chris@16
|
19 #include <boost/preprocessor/repeat.hpp>
|
Chris@16
|
20 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
21 #include <boost/type_traits/is_reference.hpp>
|
Chris@16
|
22
|
Chris@16
|
23 #define BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM(z, n, data) \
|
Chris@16
|
24 typename T##n = unused<n>
|
Chris@16
|
25
|
Chris@16
|
26 #define BOOST_PHOENIX_MAP_LOCAL_DISPATCH(z, n, data) \
|
Chris@16
|
27 typedef char(&result##n)[n+2]; \
|
Chris@16
|
28 static result##n get(T##n*);
|
Chris@16
|
29
|
Chris@16
|
30 namespace boost { namespace phoenix
|
Chris@16
|
31 {
|
Chris@16
|
32 template <typename Env, typename OuterEnv, typename Locals, typename Map>
|
Chris@16
|
33 struct scoped_environment;
|
Chris@16
|
34
|
Chris@16
|
35 namespace detail
|
Chris@16
|
36 {
|
Chris@16
|
37 template <typename Key>
|
Chris@16
|
38 struct local
|
Chris@16
|
39 {
|
Chris@16
|
40 typedef Key key_type;
|
Chris@16
|
41 };
|
Chris@16
|
42
|
Chris@16
|
43 namespace result_of
|
Chris@16
|
44 {
|
Chris@16
|
45 template <typename Locals, typename Context>
|
Chris@16
|
46 struct initialize_locals;
|
Chris@16
|
47
|
Chris@16
|
48 template <typename Context>
|
Chris@16
|
49 struct initialize_locals<vector0<>, Context>
|
Chris@16
|
50 {
|
Chris@16
|
51 typedef vector0<> type;
|
Chris@16
|
52 };
|
Chris@16
|
53
|
Chris@16
|
54 #define M1(Z, N, D) \
|
Chris@16
|
55 typename boost::phoenix::result_of::eval< \
|
Chris@16
|
56 BOOST_PP_CAT(A, N) \
|
Chris@16
|
57 , Context \
|
Chris@16
|
58 >::type \
|
Chris@16
|
59 /**/
|
Chris@16
|
60
|
Chris@16
|
61 #define M0(Z, N, D) \
|
Chris@16
|
62 template <BOOST_PHOENIX_typename_A(N), typename Context> \
|
Chris@16
|
63 struct initialize_locals< \
|
Chris@16
|
64 BOOST_PP_CAT(vector, N)< \
|
Chris@16
|
65 BOOST_PHOENIX_A(N) \
|
Chris@16
|
66 > \
|
Chris@16
|
67 , Context \
|
Chris@16
|
68 > \
|
Chris@16
|
69 { \
|
Chris@16
|
70 typedef \
|
Chris@16
|
71 BOOST_PP_CAT(vector, N)< \
|
Chris@16
|
72 BOOST_PP_ENUM(N, M1, _) \
|
Chris@16
|
73 > \
|
Chris@16
|
74 type; \
|
Chris@16
|
75 }; \
|
Chris@16
|
76 /**/
|
Chris@16
|
77 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
|
Chris@16
|
78 #undef M0
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 template <typename Context>
|
Chris@16
|
82 vector0<>
|
Chris@16
|
83 initialize_locals(vector0<> const &, Context const &)
|
Chris@16
|
84 {
|
Chris@16
|
85 vector0<> vars;
|
Chris@16
|
86 return vars;
|
Chris@16
|
87 }
|
Chris@16
|
88 #define M2(Z, N, D) \
|
Chris@16
|
89 eval(locals. BOOST_PP_CAT(a, N), ctx) \
|
Chris@16
|
90 /**/
|
Chris@16
|
91
|
Chris@16
|
92 #define M0(Z, N, D) \
|
Chris@16
|
93 template <BOOST_PHOENIX_typename_A(N), typename Context> \
|
Chris@16
|
94 BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> \
|
Chris@16
|
95 initialize_locals( \
|
Chris@16
|
96 BOOST_PP_CAT(vector, N)<BOOST_PHOENIX_A(N)> const & locals \
|
Chris@16
|
97 , Context const & ctx \
|
Chris@16
|
98 ) \
|
Chris@16
|
99 { \
|
Chris@16
|
100 BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> vars \
|
Chris@16
|
101 = {BOOST_PP_ENUM(N, M2, _)}; \
|
Chris@16
|
102 return vars; \
|
Chris@16
|
103 } \
|
Chris@16
|
104 /**/
|
Chris@16
|
105 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
|
Chris@16
|
106 #undef M0
|
Chris@16
|
107 #undef M1
|
Chris@16
|
108 #undef M2
|
Chris@16
|
109
|
Chris@16
|
110 template <int N>
|
Chris@16
|
111 struct unused;
|
Chris@16
|
112
|
Chris@16
|
113 template <
|
Chris@16
|
114 BOOST_PP_ENUM(
|
Chris@16
|
115 BOOST_PHOENIX_LOCAL_LIMIT
|
Chris@16
|
116 , BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
|
Chris@16
|
117 , _
|
Chris@16
|
118 )
|
Chris@16
|
119 >
|
Chris@16
|
120 struct map_local_index_to_tuple
|
Chris@16
|
121 {
|
Chris@16
|
122 typedef char(¬_found)[1];
|
Chris@16
|
123 static not_found get(...);
|
Chris@16
|
124
|
Chris@16
|
125 BOOST_PP_REPEAT(BOOST_PHOENIX_LOCAL_LIMIT, BOOST_PHOENIX_MAP_LOCAL_DISPATCH, _)
|
Chris@16
|
126 };
|
Chris@16
|
127
|
Chris@16
|
128 template<typename T>
|
Chris@16
|
129 T* generate_pointer();
|
Chris@16
|
130
|
Chris@16
|
131 template <typename Map, typename Tag>
|
Chris@16
|
132 struct get_index
|
Chris@16
|
133 {
|
Chris@16
|
134 BOOST_STATIC_CONSTANT(int,
|
Chris@16
|
135 value = (
|
Chris@16
|
136 static_cast<int>((sizeof(Map::get(generate_pointer<Tag>()))) / sizeof(char)) - 2
|
Chris@16
|
137 ));
|
Chris@16
|
138
|
Chris@16
|
139 // if value == -1, Tag is not found
|
Chris@16
|
140 typedef mpl::int_<value> type;
|
Chris@16
|
141 };
|
Chris@16
|
142
|
Chris@16
|
143
|
Chris@16
|
144 template <typename Local, typename Env>
|
Chris@16
|
145 struct apply_local;
|
Chris@16
|
146
|
Chris@16
|
147 template <typename Local, typename Env>
|
Chris@16
|
148 struct outer_local
|
Chris@16
|
149 {
|
Chris@16
|
150 typedef typename
|
Chris@16
|
151 apply_local<Local, typename Env::outer_env_type>::type
|
Chris@16
|
152 type;
|
Chris@16
|
153 };
|
Chris@16
|
154
|
Chris@16
|
155 template <typename Locals, int Index>
|
Chris@16
|
156 struct get_local_or_void
|
Chris@16
|
157 {
|
Chris@16
|
158 typedef typename
|
Chris@16
|
159 mpl::eval_if_c<
|
Chris@16
|
160 Index < Locals::size_value
|
Chris@16
|
161 , fusion::result_of::at_c<Locals, Index>
|
Chris@16
|
162 , mpl::identity<fusion::void_>
|
Chris@16
|
163 >::type
|
Chris@16
|
164 type;
|
Chris@16
|
165 };
|
Chris@16
|
166
|
Chris@16
|
167 template <typename Local, typename Env, int Index>
|
Chris@16
|
168 struct get_local_from_index
|
Chris@16
|
169 {
|
Chris@16
|
170 typedef typename
|
Chris@16
|
171 mpl::eval_if_c<
|
Chris@16
|
172 Index == -1
|
Chris@16
|
173 , outer_local<Local, Env>
|
Chris@16
|
174 , get_local_or_void<typename Env::locals_type, Index>
|
Chris@16
|
175 >::type
|
Chris@16
|
176 type;
|
Chris@16
|
177 };
|
Chris@16
|
178
|
Chris@16
|
179 template <typename Local, typename Env>
|
Chris@16
|
180 struct get_local
|
Chris@16
|
181 {
|
Chris@16
|
182 static const int index_value = get_index<typename Env::map_type, Local>::value;
|
Chris@16
|
183
|
Chris@16
|
184 typedef typename
|
Chris@16
|
185 get_local_from_index<Local, Env, index_value>::type
|
Chris@16
|
186 type;
|
Chris@16
|
187 };
|
Chris@16
|
188
|
Chris@16
|
189 template <typename Local, typename Env>
|
Chris@16
|
190 struct apply_local
|
Chris@16
|
191 {
|
Chris@16
|
192 // $$$ TODO: static assert that Env is a scoped_environment $$$
|
Chris@16
|
193 typedef typename get_local<Local, Env>::type type;
|
Chris@16
|
194 };
|
Chris@16
|
195
|
Chris@16
|
196 template <typename Key>
|
Chris@16
|
197 struct eval_local
|
Chris@16
|
198 {
|
Chris@16
|
199 template <typename RT, int Index, typename Env>
|
Chris@16
|
200 static RT
|
Chris@16
|
201 get(Env const& env, mpl::false_)
|
Chris@16
|
202 {
|
Chris@16
|
203 return RT(fusion::at_c<Index>(env.locals));
|
Chris@16
|
204 }
|
Chris@16
|
205
|
Chris@16
|
206 template <typename RT, int Index, typename Env>
|
Chris@16
|
207 static RT
|
Chris@16
|
208 get(Env const& env, mpl::true_)
|
Chris@16
|
209 {
|
Chris@16
|
210 static const int index_value = get_index<typename Env::outer_env_type::map_type, detail::local<Key> >::value;
|
Chris@16
|
211
|
Chris@16
|
212 return get<RT, index_value>(
|
Chris@16
|
213 env.outer_env
|
Chris@16
|
214 , mpl::bool_<index_value == -1>());
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 template <typename RT, int Index, typename Env>
|
Chris@16
|
218 static RT
|
Chris@16
|
219 get(Env const& env)
|
Chris@16
|
220 {
|
Chris@16
|
221 return get<RT, Index>(
|
Chris@16
|
222 env
|
Chris@16
|
223 , mpl::bool_<Index == -1>());
|
Chris@16
|
224 }
|
Chris@16
|
225 };
|
Chris@16
|
226 }
|
Chris@16
|
227 }}
|
Chris@16
|
228
|
Chris@16
|
229 #undef BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
|
Chris@16
|
230 #undef BOOST_PHOENIX_MAP_LOCAL_DISPATCH
|
Chris@16
|
231
|
Chris@16
|
232 #endif
|