]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================== |
2 | Copyright (c) 2005-2007 Dan Marsden | |
3 | Copyright (c) 2005-2010 Joel de Guzman | |
4 | Copyright (c) 2010 Thomas Heller | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ==============================================================================*/ | |
9 | ||
10 | #ifndef BOOST_PHOENIX_STATEMENT_TRY_CATCH_HPP | |
11 | #define BOOST_PHOENIX_STATEMENT_TRY_CATCH_HPP | |
12 | ||
13 | #include <boost/phoenix/config.hpp> | |
14 | #include <boost/phoenix/core/limits.hpp> | |
15 | #include <boost/phoenix/core/call.hpp> | |
16 | #include <boost/phoenix/core/expression.hpp> | |
17 | #include <boost/phoenix/core/meta_grammar.hpp> | |
18 | #include <boost/phoenix/core/is_nullary.hpp> | |
19 | #include <boost/phoenix/scope/local_variable.hpp> | |
20 | #include <boost/phoenix/scope/scoped_environment.hpp> | |
21 | #include <boost/proto/functional/fusion/pop_front.hpp> | |
22 | #include <boost/core/enable_if.hpp> | |
23 | ||
24 | #ifdef _MSC_VER | |
25 | #pragma warning(push) | |
26 | #pragma warning(disable: 4355) // 'this' : used in base member initializer list | |
27 | #endif | |
28 | ||
29 | namespace boost { namespace phoenix | |
30 | { | |
31 | template <typename Expr> | |
32 | struct try_catch_actor; | |
33 | ||
34 | template <typename Exception> | |
35 | struct catch_exception | |
36 | { | |
37 | typedef Exception type; | |
38 | }; | |
39 | ||
40 | namespace tag | |
41 | { | |
42 | struct try_catch {}; | |
43 | struct catch_ {}; | |
44 | struct catch_all {}; | |
45 | } | |
46 | ||
47 | namespace expression | |
48 | { | |
49 | template < | |
50 | typename Try | |
51 | , BOOST_PHOENIX_typename_A_void(BOOST_PHOENIX_CATCH_LIMIT) | |
52 | , typename Dummy = void | |
53 | > | |
54 | struct try_catch; | |
55 | ||
56 | // bring in the expression definitions | |
57 | #include <boost/phoenix/statement/detail/try_catch_expression.hpp> | |
58 | ||
59 | template <typename A0, typename A1, typename A2 = void> | |
60 | struct catch_ | |
61 | : proto::nary_expr<tag::catch_, A0, A1, A2> | |
62 | {}; | |
63 | ||
64 | template <typename A0, typename A1> | |
65 | struct catch_<A0, A1, void> | |
66 | : proto::binary_expr<tag::catch_, A0, A1> | |
67 | {}; | |
68 | ||
69 | template <typename A0> | |
70 | struct catch_all | |
71 | : proto::unary_expr<tag::catch_all, A0> | |
72 | {}; | |
73 | } | |
74 | ||
75 | namespace rule | |
76 | { | |
77 | typedef | |
78 | expression::catch_< | |
79 | proto::terminal<catch_exception<proto::_> > | |
80 | , local_variable | |
81 | , meta_grammar | |
82 | > | |
83 | captured_catch; | |
84 | ||
85 | typedef | |
86 | expression::catch_< | |
87 | proto::terminal<catch_exception<proto::_> > | |
88 | , meta_grammar | |
89 | > | |
90 | non_captured_catch; | |
91 | ||
92 | struct catch_ | |
93 | : proto::or_< | |
94 | captured_catch | |
95 | , non_captured_catch | |
96 | > | |
97 | {}; | |
98 | ||
99 | struct catch_all | |
100 | : expression::catch_all< | |
101 | meta_grammar | |
102 | > | |
103 | {}; | |
104 | ||
105 | struct try_catch | |
106 | : proto::or_< | |
107 | expression::try_catch< | |
108 | meta_grammar | |
109 | , proto::vararg<rule::catch_> | |
110 | > | |
111 | , expression::try_catch< | |
112 | meta_grammar | |
113 | , rule::catch_all | |
114 | > | |
115 | , expression::try_catch< | |
116 | meta_grammar | |
117 | , proto::vararg<rule::catch_> | |
118 | , rule::catch_all | |
119 | > | |
120 | > | |
121 | {}; | |
122 | } | |
123 | ||
124 | template <typename Dummy> | |
125 | struct meta_grammar::case_<tag::try_catch, Dummy> | |
126 | : enable_rule<rule::try_catch, Dummy> | |
127 | {}; | |
128 | ||
129 | struct try_catch_eval | |
130 | { | |
131 | typedef void result_type; | |
132 | ||
133 | template <typename Try, typename Context> | |
134 | void operator()(Try const &, Context const &) const | |
135 | {} | |
136 | ||
137 | template <typename Catch, typename Exception, typename Context> | |
138 | typename enable_if<proto::matches<Catch, rule::non_captured_catch> >::type | |
139 | eval_catch_body(Catch const &c, Exception & /*unused*/, Context const &ctx | |
140 | BOOST_PHOENIX_SFINAE_AND_OVERLOADS) const | |
141 | { | |
142 | phoenix::eval(proto::child_c<1>(c), ctx); | |
143 | } | |
144 | ||
145 | template <typename Catch, typename Exception, typename Context> | |
146 | typename enable_if<proto::matches<Catch, rule::captured_catch> >::type | |
147 | eval_catch_body(Catch const &c, Exception &e, Context const &ctx) const | |
148 | { | |
149 | typedef | |
150 | typename proto::detail::uncvref< | |
151 | typename proto::result_of::value< | |
152 | typename proto::result_of::child_c<Catch, 1>::type | |
153 | >::type | |
154 | >::type | |
155 | capture_type; | |
156 | typedef | |
157 | typename proto::detail::uncvref< | |
158 | typename result_of::env<Context>::type | |
159 | >::type | |
160 | env_type; | |
161 | typedef vector1<Exception &> local_type; | |
162 | typedef detail::map_local_index_to_tuple<capture_type> map_type; | |
163 | ||
164 | typedef | |
165 | phoenix::scoped_environment< | |
166 | env_type | |
167 | , env_type | |
168 | , local_type | |
169 | , map_type | |
170 | > | |
171 | scoped_env_tpe; | |
172 | ||
173 | local_type local = {e}; | |
174 | ||
175 | scoped_env_tpe env(phoenix::env(ctx), phoenix::env(ctx), local); | |
176 | ||
177 | phoenix::eval(proto::child_c<2>(c), phoenix::context(env, phoenix::actions(ctx))); | |
178 | } | |
179 | ||
180 | // bring in the operator overloads | |
181 | #include <boost/phoenix/statement/detail/try_catch_eval.hpp> | |
182 | }; | |
183 | ||
184 | template <typename Dummy> | |
185 | struct default_actions::when<rule::try_catch, Dummy> | |
186 | : call<try_catch_eval, Dummy> | |
187 | {}; | |
188 | ||
189 | namespace detail | |
190 | { | |
191 | struct try_catch_is_nullary | |
192 | : proto::or_< | |
193 | proto::when< | |
194 | phoenix::rule::catch_all | |
195 | , proto::call< | |
196 | evaluator( | |
197 | proto::_child_c<0> | |
198 | , proto::_data | |
199 | , proto::make<proto::empty_env()> | |
200 | ) | |
201 | > | |
202 | > | |
203 | , proto::when< | |
204 | phoenix::rule::catch_ | |
205 | , proto::or_< | |
206 | proto::when< | |
207 | phoenix::rule::captured_catch | |
208 | , proto::call< | |
209 | evaluator( | |
210 | proto::_child_c<2> | |
211 | , proto::call< | |
212 | phoenix::functional::context( | |
213 | proto::make<mpl::true_()> | |
214 | , proto::make<detail::scope_is_nullary_actions()> | |
215 | ) | |
216 | > | |
217 | , proto::make<proto::empty_env()> | |
218 | ) | |
219 | > | |
220 | > | |
221 | , proto::otherwise< | |
222 | proto::call< | |
223 | evaluator( | |
224 | proto::_child_c<1> | |
225 | , proto::_data | |
226 | , proto::make<proto::empty_env()> | |
227 | ) | |
228 | > | |
229 | > | |
230 | > | |
231 | > | |
232 | , proto::when< | |
233 | phoenix::rule::try_catch | |
234 | , proto::make< | |
235 | mpl::and_< | |
236 | proto::call< | |
237 | evaluator( | |
238 | proto::_child_c<0> | |
239 | , proto::_data | |
240 | , proto::make<proto::empty_env()> | |
241 | ) | |
242 | > | |
243 | , proto::fold< | |
244 | proto::call< | |
245 | proto::functional::pop_front(proto::_) | |
246 | > | |
247 | , proto::make<mpl::true_()> | |
248 | , proto::make< | |
249 | mpl::and_< | |
250 | proto::_state | |
251 | , proto::call< | |
252 | try_catch_is_nullary( | |
253 | proto::_ | |
254 | , proto::make<proto::empty_env()> | |
255 | , proto::_data | |
256 | ) | |
257 | > | |
258 | >() | |
259 | > | |
260 | > | |
261 | >() | |
262 | > | |
263 | > | |
264 | > | |
265 | {}; | |
266 | ||
267 | template < | |
268 | typename TryCatch | |
269 | , typename Exception | |
270 | , typename Capture | |
271 | , typename Expr | |
272 | , long Arity = proto::arity_of<TryCatch>::value | |
273 | > | |
274 | struct catch_push_back; | |
275 | ||
276 | template <typename TryCatch, typename Exception, typename Capture, typename Expr> | |
277 | struct catch_push_back<TryCatch, Exception, Capture, Expr, 1> | |
278 | { | |
279 | typedef | |
280 | typename proto::result_of::make_expr< | |
281 | phoenix::tag::catch_ | |
282 | , proto::basic_default_domain | |
283 | , catch_exception<Exception> | |
284 | , Capture | |
285 | , Expr | |
286 | >::type | |
287 | catch_expr; | |
288 | ||
289 | typedef | |
290 | phoenix::expression::try_catch< | |
291 | TryCatch | |
292 | , catch_expr | |
293 | > | |
294 | gen_type; | |
295 | typedef typename gen_type::type type; | |
296 | ||
297 | static type make(TryCatch const & try_catch, Capture const & capture, Expr const & catch_) | |
298 | { | |
299 | return | |
300 | gen_type::make( | |
301 | try_catch | |
302 | , proto::make_expr< | |
303 | phoenix::tag::catch_ | |
304 | , proto::basic_default_domain | |
305 | >(catch_exception<Exception>(), capture, catch_) | |
306 | ); | |
307 | } | |
308 | }; | |
309 | ||
310 | template <typename TryCatch, typename Exception, typename Expr> | |
311 | struct catch_push_back<TryCatch, Exception, void, Expr, 1> | |
312 | { | |
313 | typedef | |
314 | typename proto::result_of::make_expr< | |
315 | phoenix::tag::catch_ | |
316 | , proto::basic_default_domain | |
317 | , catch_exception<Exception> | |
318 | , Expr | |
319 | >::type | |
320 | catch_expr; | |
321 | ||
322 | typedef | |
323 | phoenix::expression::try_catch< | |
324 | TryCatch | |
325 | , catch_expr | |
326 | > | |
327 | gen_type; | |
328 | typedef typename gen_type::type type; | |
329 | ||
330 | static type make(TryCatch const & try_catch, Expr const & catch_) | |
331 | { | |
332 | return | |
333 | gen_type::make( | |
334 | try_catch | |
335 | , proto::make_expr< | |
336 | phoenix::tag::catch_ | |
337 | , proto::basic_default_domain | |
338 | >(catch_exception<Exception>(), catch_) | |
339 | ); | |
340 | } | |
341 | }; | |
342 | ||
343 | template < | |
344 | typename TryCatch | |
345 | , typename Expr | |
346 | , long Arity = proto::arity_of<TryCatch>::value | |
347 | > | |
348 | struct catch_all_push_back; | |
349 | ||
350 | template <typename TryCatch, typename Expr> | |
351 | struct catch_all_push_back<TryCatch, Expr, 1> | |
352 | { | |
353 | typedef | |
354 | typename proto::result_of::make_expr< | |
355 | phoenix::tag::catch_all | |
356 | , proto::basic_default_domain | |
357 | , Expr | |
358 | >::type | |
359 | catch_expr; | |
360 | ||
361 | typedef | |
362 | phoenix::expression::try_catch< | |
363 | TryCatch | |
364 | , catch_expr | |
365 | > | |
366 | gen_type; | |
367 | typedef typename gen_type::type type; | |
368 | ||
369 | static type make(TryCatch const& try_catch, Expr const& catch_) | |
370 | { | |
371 | return | |
372 | gen_type::make( | |
373 | try_catch | |
374 | , proto::make_expr< | |
375 | phoenix::tag::catch_all | |
376 | , proto::basic_default_domain | |
377 | >(catch_) | |
378 | ); | |
379 | } | |
380 | }; | |
381 | #include <boost/phoenix/statement/detail/catch_push_back.hpp> | |
382 | } | |
383 | ||
384 | template <typename Dummy> | |
385 | struct is_nullary::when<rule::try_catch, Dummy> | |
386 | : proto::call< | |
387 | detail::try_catch_is_nullary( | |
388 | proto::_ | |
389 | , proto::make<proto::empty_env()> | |
390 | , _context | |
391 | ) | |
392 | > | |
393 | {}; | |
394 | ||
395 | template <typename TryCatch, typename Exception, typename Capture = void> | |
396 | struct catch_gen | |
397 | { | |
398 | catch_gen(TryCatch const& try_catch_, Capture const& capture) | |
399 | : try_catch(try_catch_) | |
400 | , capture(capture) {} | |
401 | ||
402 | template <typename Expr> | |
403 | typename boost::disable_if< | |
404 | proto::matches< | |
405 | typename proto::result_of::child_c< | |
406 | TryCatch | |
407 | , proto::arity_of<TryCatch>::value - 1 | |
408 | >::type | |
409 | , rule::catch_all | |
410 | > | |
411 | , typename detail::catch_push_back<TryCatch, Exception, Capture, Expr>::type | |
412 | >::type | |
413 | operator[](Expr const& expr) const | |
414 | { | |
415 | return | |
416 | detail::catch_push_back<TryCatch, Exception, Capture, Expr>::make( | |
417 | try_catch, capture, expr | |
418 | ); | |
419 | } | |
420 | ||
421 | TryCatch const & try_catch; | |
422 | Capture const & capture; | |
423 | }; | |
424 | ||
425 | template <typename TryCatch, typename Exception> | |
426 | struct catch_gen<TryCatch, Exception, void> | |
427 | { | |
428 | catch_gen(TryCatch const& try_catch_) : try_catch(try_catch_) {} | |
429 | ||
430 | template <typename Expr> | |
431 | typename boost::disable_if< | |
432 | proto::matches< | |
433 | typename proto::result_of::child_c< | |
434 | TryCatch | |
435 | , proto::arity_of<TryCatch>::value - 1 | |
436 | >::type | |
437 | , rule::catch_all | |
438 | > | |
439 | , typename detail::catch_push_back<TryCatch, Exception, void, Expr>::type | |
440 | >::type | |
441 | operator[](Expr const& expr) const | |
442 | { | |
443 | return | |
444 | detail::catch_push_back<TryCatch, Exception, void, Expr>::make( | |
445 | try_catch, expr | |
446 | ); | |
447 | } | |
448 | ||
449 | TryCatch const & try_catch; | |
450 | }; | |
451 | ||
452 | template <typename TryCatch> | |
453 | struct catch_all_gen | |
454 | { | |
455 | catch_all_gen(TryCatch const& try_catch_) : try_catch(try_catch_) {} | |
456 | ||
457 | template <typename Expr> | |
458 | typename boost::disable_if< | |
459 | proto::matches< | |
460 | typename proto::result_of::child_c< | |
461 | TryCatch | |
462 | , proto::arity_of<TryCatch>::value - 1 | |
463 | >::type | |
464 | , rule::catch_all | |
465 | > | |
466 | , typename detail::catch_all_push_back<TryCatch, Expr>::type | |
467 | >::type | |
468 | operator[](Expr const& expr) const | |
469 | { | |
470 | return detail::catch_all_push_back<TryCatch, Expr>::make( | |
471 | try_catch, expr | |
472 | ); | |
473 | } | |
474 | ||
475 | TryCatch const & try_catch; | |
476 | }; | |
477 | ||
478 | template < | |
479 | typename Expr | |
480 | > | |
481 | struct try_catch_actor; | |
482 | ||
483 | template <typename Expr> | |
484 | struct try_catch_actor | |
485 | : actor<Expr> | |
486 | { | |
487 | typedef try_catch_actor<Expr> that_type; | |
488 | typedef actor<Expr> base_type; | |
489 | ||
490 | try_catch_actor(base_type const& expr) | |
491 | : base_type(expr) | |
492 | , catch_all(*this) | |
493 | { | |
494 | } | |
495 | ||
496 | template <typename Exception> | |
497 | catch_gen<that_type, Exception> const | |
498 | catch_() const | |
499 | { | |
500 | return catch_gen<that_type, Exception>(*this); | |
501 | } | |
502 | ||
503 | template <typename Exception, typename Capture> | |
504 | catch_gen<that_type, Exception, Capture> const | |
505 | catch_(Capture const &expr) const | |
506 | { | |
507 | return catch_gen<that_type, Exception, Capture>(*this, expr); | |
508 | } | |
509 | ||
510 | catch_all_gen<that_type> const catch_all; | |
511 | }; | |
512 | ||
513 | struct try_gen | |
514 | { | |
515 | template <typename Try> | |
516 | typename expression::try_catch<Try>::type const | |
517 | operator[](Try const & try_) const | |
518 | { | |
519 | return expression::try_catch<Try>::make(try_); | |
520 | } | |
521 | }; | |
522 | ||
523 | #ifndef BOOST_PHOENIX_NO_PREDEFINED_TERMINALS | |
524 | try_gen const try_ = {}; | |
525 | #endif | |
526 | }} | |
527 | ||
528 | #ifdef _MSC_VER | |
529 | #pragma warning(pop) | |
530 | #endif | |
531 | ||
532 | #endif |