Chris@16
|
1 /*==============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2010 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2010 Thomas Heller
|
Chris@16
|
4
|
Chris@16
|
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 ==============================================================================*/
|
Chris@16
|
8 #ifndef BOOST_PHOENIX_STATEMENT_SWITCH_HPP
|
Chris@16
|
9 #define BOOST_PHOENIX_STATEMENT_SWITCH_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/phoenix/core/limits.hpp>
|
Chris@16
|
12 #include <boost/fusion/iterator/advance.hpp>
|
Chris@16
|
13 #include <boost/phoenix/core/call.hpp>
|
Chris@16
|
14 #include <boost/phoenix/core/expression.hpp>
|
Chris@16
|
15 #include <boost/phoenix/core/meta_grammar.hpp>
|
Chris@16
|
16 #include <boost/phoenix/core/is_nullary.hpp>
|
Chris@16
|
17 #include <boost/phoenix/support/iterate.hpp>
|
Chris@16
|
18 #include <boost/proto/make_expr.hpp>
|
Chris@16
|
19 #include <boost/proto/fusion.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #ifdef _MSC_VER
|
Chris@16
|
22 #pragma warning(push)
|
Chris@16
|
23 #pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
|
Chris@16
|
24 #endif
|
Chris@16
|
25
|
Chris@16
|
26 BOOST_PHOENIX_DEFINE_EXPRESSION(
|
Chris@16
|
27 (boost)(phoenix)(switch_case)
|
Chris@16
|
28 , (proto::terminal<proto::_>)
|
Chris@16
|
29 (meta_grammar)
|
Chris@16
|
30 )
|
Chris@16
|
31
|
Chris@16
|
32 BOOST_PHOENIX_DEFINE_EXPRESSION(
|
Chris@16
|
33 (boost)(phoenix)(switch_default_case)
|
Chris@16
|
34 , (meta_grammar)
|
Chris@16
|
35 )
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost { namespace phoenix
|
Chris@16
|
38 {
|
Chris@16
|
39 namespace detail
|
Chris@16
|
40 {
|
Chris@16
|
41 struct switch_case_grammar;
|
Chris@16
|
42 struct switch_case_with_default_grammar;
|
Chris@16
|
43 struct switch_grammar
|
Chris@16
|
44 : proto::or_<
|
Chris@16
|
45 proto::when<
|
Chris@16
|
46 detail::switch_case_grammar
|
Chris@16
|
47 , mpl::false_()
|
Chris@16
|
48 >
|
Chris@16
|
49 , proto::when<
|
Chris@16
|
50 detail::switch_case_with_default_grammar
|
Chris@16
|
51 , mpl::true_()
|
Chris@16
|
52 >
|
Chris@16
|
53 >
|
Chris@16
|
54 {};
|
Chris@16
|
55 }
|
Chris@16
|
56
|
Chris@16
|
57 namespace detail
|
Chris@16
|
58 {
|
Chris@16
|
59 struct switch_case_is_nullary
|
Chris@16
|
60 : proto::or_<
|
Chris@16
|
61 proto::when<
|
Chris@16
|
62 proto::comma<
|
Chris@16
|
63 switch_case_is_nullary
|
Chris@16
|
64 , proto::or_<phoenix::rule::switch_default_case, phoenix::rule::switch_case>
|
Chris@16
|
65 >
|
Chris@16
|
66 , mpl::and_<
|
Chris@16
|
67 switch_case_is_nullary(
|
Chris@16
|
68 proto::_child_c<0>
|
Chris@16
|
69 , proto::_state
|
Chris@16
|
70 )
|
Chris@16
|
71 , switch_case_is_nullary(
|
Chris@16
|
72 proto::_child_c<1>
|
Chris@16
|
73 , proto::_state
|
Chris@16
|
74 )
|
Chris@16
|
75 >()
|
Chris@16
|
76 >
|
Chris@16
|
77 , proto::when<
|
Chris@16
|
78 proto::or_<phoenix::rule::switch_default_case, phoenix::rule::switch_case>
|
Chris@16
|
79 , evaluator(proto::_child_c<0>, proto::_state)
|
Chris@16
|
80 >
|
Chris@16
|
81 >
|
Chris@16
|
82 {};
|
Chris@16
|
83
|
Chris@16
|
84 struct switch_case_grammar
|
Chris@16
|
85 : proto::or_<
|
Chris@16
|
86 proto::comma<switch_case_grammar, phoenix::rule::switch_case>
|
Chris@16
|
87 , proto::when<phoenix::rule::switch_case, proto::_>
|
Chris@16
|
88 >
|
Chris@16
|
89 {};
|
Chris@16
|
90
|
Chris@16
|
91 struct switch_case_with_default_grammar
|
Chris@16
|
92 : proto::or_<
|
Chris@16
|
93 proto::comma<switch_case_grammar, phoenix::rule::switch_default_case>
|
Chris@16
|
94 , proto::when<phoenix::rule::switch_default_case, proto::_>
|
Chris@16
|
95 >
|
Chris@16
|
96 {};
|
Chris@16
|
97
|
Chris@16
|
98 struct switch_size
|
Chris@16
|
99 : proto::or_<
|
Chris@16
|
100 proto::when<
|
Chris@16
|
101 proto::comma<switch_size, proto::_>
|
Chris@16
|
102 , mpl::next<switch_size(proto::_left)>()
|
Chris@16
|
103 >
|
Chris@16
|
104 , proto::when<proto::_, mpl::int_<1>()>
|
Chris@16
|
105 >
|
Chris@16
|
106 {};
|
Chris@16
|
107 }
|
Chris@16
|
108 }}
|
Chris@16
|
109
|
Chris@16
|
110 BOOST_PHOENIX_DEFINE_EXPRESSION(
|
Chris@16
|
111 (boost)(phoenix)(switch_)
|
Chris@16
|
112 , (meta_grammar) // Cond
|
Chris@16
|
113 (detail::switch_grammar) // Cases
|
Chris@16
|
114 )
|
Chris@16
|
115
|
Chris@16
|
116 namespace boost { namespace phoenix {
|
Chris@16
|
117
|
Chris@16
|
118 template <typename Dummy>
|
Chris@16
|
119 struct is_nullary::when<rule::switch_, Dummy>
|
Chris@16
|
120 : proto::and_<
|
Chris@16
|
121 evaluator(proto::_child_c<0>, _context)
|
Chris@16
|
122 , detail::switch_case_is_nullary(proto::_child_c<1>, _context)
|
Chris@16
|
123 >
|
Chris@16
|
124 {};
|
Chris@16
|
125
|
Chris@16
|
126 struct switch_eval
|
Chris@16
|
127 {
|
Chris@16
|
128 typedef void result_type;
|
Chris@16
|
129
|
Chris@16
|
130 template <typename Context>
|
Chris@16
|
131 result_type
|
Chris@16
|
132 operator()(Context const &) const
|
Chris@16
|
133 {
|
Chris@16
|
134 }
|
Chris@16
|
135
|
Chris@16
|
136 template <typename Cond, typename Cases, typename Context>
|
Chris@16
|
137 result_type
|
Chris@16
|
138 operator()(Cond const & cond, Cases const & cases, Context const & ctx) const
|
Chris@16
|
139 {
|
Chris@16
|
140 this->evaluate(
|
Chris@16
|
141 ctx
|
Chris@16
|
142 , cond
|
Chris@16
|
143 , cases
|
Chris@16
|
144 , typename detail::switch_size::impl<Cases, int, proto::empty_env>::result_type()
|
Chris@16
|
145 , typename detail::switch_grammar::impl<Cases, int, proto::empty_env>::result_type()
|
Chris@16
|
146 );
|
Chris@16
|
147 }
|
Chris@16
|
148
|
Chris@16
|
149 private:
|
Chris@16
|
150 template <typename Context, typename Cond, typename Cases>
|
Chris@16
|
151 result_type
|
Chris@16
|
152 evaluate(
|
Chris@16
|
153 Context const & ctx
|
Chris@16
|
154 , Cond const & cond
|
Chris@16
|
155 , Cases const & cases
|
Chris@16
|
156 , mpl::int_<1>
|
Chris@16
|
157 , mpl::false_
|
Chris@16
|
158 ) const
|
Chris@16
|
159 {
|
Chris@16
|
160 typedef
|
Chris@16
|
161 typename proto::result_of::value<
|
Chris@16
|
162 typename proto::result_of::child_c<
|
Chris@16
|
163 Cases
|
Chris@16
|
164 , 0
|
Chris@16
|
165 >::type
|
Chris@16
|
166 >::type
|
Chris@16
|
167 case_label;
|
Chris@16
|
168
|
Chris@16
|
169 switch(boost::phoenix::eval(cond, ctx))
|
Chris@16
|
170 {
|
Chris@16
|
171 case case_label::value:
|
Chris@16
|
172 boost::phoenix::eval(proto::child_c<1>(cases), ctx);
|
Chris@16
|
173 }
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 template <typename Context, typename Cond, typename Cases>
|
Chris@16
|
177 result_type
|
Chris@16
|
178 evaluate(
|
Chris@16
|
179 Context const & ctx
|
Chris@16
|
180 , Cond const & cond
|
Chris@16
|
181 , Cases const & cases
|
Chris@16
|
182 , mpl::int_<1>
|
Chris@16
|
183 , mpl::true_
|
Chris@16
|
184 ) const
|
Chris@16
|
185 {
|
Chris@16
|
186 switch(boost::phoenix::eval(cond, ctx))
|
Chris@16
|
187 {
|
Chris@16
|
188 default:
|
Chris@16
|
189 boost::phoenix::eval(proto::child_c<0>(cases), ctx);
|
Chris@16
|
190 }
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 // Bring in the evaluation functions
|
Chris@16
|
194 #include <boost/phoenix/statement/detail/switch.hpp>
|
Chris@16
|
195 };
|
Chris@16
|
196
|
Chris@16
|
197 template <typename Dummy>
|
Chris@16
|
198 struct default_actions::when<rule::switch_, Dummy>
|
Chris@16
|
199 : call<switch_eval>
|
Chris@16
|
200 {};
|
Chris@16
|
201
|
Chris@16
|
202 template <int N, typename A>
|
Chris@16
|
203 inline
|
Chris@16
|
204 typename proto::result_of::make_expr<
|
Chris@16
|
205 tag::switch_case
|
Chris@16
|
206 , proto::basic_default_domain
|
Chris@16
|
207 , mpl::int_<N>
|
Chris@16
|
208 , A
|
Chris@16
|
209 >::type const
|
Chris@16
|
210 case_(A const & a)
|
Chris@16
|
211 {
|
Chris@16
|
212 return
|
Chris@16
|
213 proto::make_expr<
|
Chris@16
|
214 tag::switch_case
|
Chris@16
|
215 , proto::basic_default_domain
|
Chris@16
|
216 >(
|
Chris@16
|
217 mpl::int_<N>()
|
Chris@16
|
218 , a
|
Chris@16
|
219 );
|
Chris@16
|
220 }
|
Chris@16
|
221
|
Chris@16
|
222 template <typename A>
|
Chris@16
|
223 inline
|
Chris@16
|
224 typename proto::result_of::make_expr<
|
Chris@16
|
225 tag::switch_default_case
|
Chris@16
|
226 , proto::basic_default_domain
|
Chris@16
|
227 , A
|
Chris@16
|
228 >::type const
|
Chris@16
|
229 default_(A const& a)
|
Chris@16
|
230 {
|
Chris@16
|
231 return
|
Chris@16
|
232 proto::make_expr<
|
Chris@16
|
233 tag::switch_default_case
|
Chris@16
|
234 , proto::basic_default_domain
|
Chris@16
|
235 >(a);
|
Chris@16
|
236 }
|
Chris@16
|
237
|
Chris@16
|
238 template <typename Cond>
|
Chris@16
|
239 struct switch_gen
|
Chris@16
|
240 {
|
Chris@101
|
241 switch_gen(Cond const& cond_) : cond(cond_) {}
|
Chris@16
|
242
|
Chris@16
|
243 template <typename Cases>
|
Chris@16
|
244 typename expression::switch_<
|
Chris@16
|
245 Cond
|
Chris@16
|
246 , Cases
|
Chris@16
|
247 >::type
|
Chris@16
|
248 operator[](Cases const& cases) const
|
Chris@16
|
249 {
|
Chris@16
|
250 return
|
Chris@16
|
251 this->generate(
|
Chris@16
|
252 cases
|
Chris@16
|
253 , proto::matches<Cases, detail::switch_grammar>()
|
Chris@16
|
254 );
|
Chris@16
|
255 }
|
Chris@16
|
256
|
Chris@16
|
257 private:
|
Chris@16
|
258 Cond const& cond;
|
Chris@16
|
259
|
Chris@16
|
260 template <typename Cases>
|
Chris@16
|
261 typename expression::switch_<
|
Chris@16
|
262 Cond
|
Chris@16
|
263 , Cases
|
Chris@16
|
264 >::type
|
Chris@16
|
265 generate(Cases const & cases, mpl::true_) const
|
Chris@16
|
266 {
|
Chris@16
|
267 return expression::switch_<Cond, Cases>::make(cond, cases);
|
Chris@16
|
268 }
|
Chris@16
|
269
|
Chris@16
|
270 template <typename Cases>
|
Chris@16
|
271 typename expression::switch_<
|
Chris@16
|
272 Cond
|
Chris@16
|
273 , Cases
|
Chris@16
|
274 >::type
|
Chris@16
|
275 generate(Cases const &, mpl::false_) const
|
Chris@16
|
276 {
|
Chris@16
|
277 BOOST_MPL_ASSERT_MSG(
|
Chris@16
|
278 false
|
Chris@16
|
279 , INVALID_SWITCH_CASE_STATEMENT
|
Chris@16
|
280 , (Cases)
|
Chris@16
|
281 );
|
Chris@16
|
282 }
|
Chris@16
|
283 };
|
Chris@16
|
284
|
Chris@16
|
285 template <typename Cond>
|
Chris@16
|
286 inline
|
Chris@16
|
287 switch_gen<Cond> const
|
Chris@16
|
288 switch_(Cond const& cond)
|
Chris@16
|
289 {
|
Chris@16
|
290 return switch_gen<Cond>(cond);
|
Chris@16
|
291 }
|
Chris@16
|
292
|
Chris@16
|
293 }}
|
Chris@16
|
294
|
Chris@16
|
295 #ifdef _MSC_VER
|
Chris@16
|
296 #pragma warning(pop)
|
Chris@16
|
297 #endif
|
Chris@16
|
298
|
Chris@16
|
299 #endif
|
Chris@16
|
300
|