• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
operator ()boost::phoenix::try_catch_eval134         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
eval_catch_bodyboost::phoenix::try_catch_eval139         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
eval_catch_bodyboost::phoenix::try_catch_eval147         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 
makeboost::phoenix::detail::catch_push_back297             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 
makeboost::phoenix::detail::catch_push_back330             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 
makeboost::phoenix::detail::catch_all_push_back369             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     {
catch_genboost::phoenix::catch_gen398         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
operator []boost::phoenix::catch_gen413         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 try_catch;
422         Capture capture;
423     };
424 
425     template <typename TryCatch, typename Exception>
426     struct catch_gen<TryCatch, Exception, void>
427     {
catch_genboost::phoenix::catch_gen428         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
operator []boost::phoenix::catch_gen441         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 try_catch;
450     };
451 
452     template <typename TryCatch>
453     struct catch_all_gen
454     {
catch_all_genboost::phoenix::catch_all_gen455         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
operator []boost::phoenix::catch_all_gen468         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 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 actor<Expr> base_type;
488 
try_catch_actorboost::phoenix::try_catch_actor489         try_catch_actor(base_type const& expr)
490             : base_type(expr)
491             , catch_all(*this)
492         {
493         }
494 
495         template <typename Exception>
496         catch_gen<base_type, Exception> const
catch_boost::phoenix::try_catch_actor497         catch_() const
498         {
499             return catch_gen<base_type, Exception>(*this);
500         }
501 
502         template <typename Exception, typename Capture>
503         catch_gen<base_type, Exception, Capture> const
catch_boost::phoenix::try_catch_actor504         catch_(Capture const &expr) const
505         {
506             return catch_gen<base_type, Exception, Capture>(*this, expr);
507         }
508 
509         catch_all_gen<base_type> const catch_all;
510     };
511 
512     template <typename Expr>
513     struct is_actor<try_catch_actor<Expr> >
514         : mpl::true_
515     {};
516 
517     struct try_gen
518     {
519         template <typename Try>
520         typename expression::try_catch<Try>::type const
operator []boost::phoenix::try_gen521         operator[](Try const & try_) const
522         {
523             return expression::try_catch<Try>::make(try_);
524         }
525     };
526 
527 #ifndef BOOST_PHOENIX_NO_PREDEFINED_TERMINALS
528     try_gen const try_ = {};
529 #endif
530 }}
531 
532 #ifdef _MSC_VER
533 #pragma warning(pop)
534 #endif
535 
536 #endif
537