diff options
Diffstat (limited to 'boost/phoenix/statement/try_catch.hpp')
-rw-r--r-- | boost/phoenix/statement/try_catch.hpp | 182 |
1 files changed, 169 insertions, 13 deletions
diff --git a/boost/phoenix/statement/try_catch.hpp b/boost/phoenix/statement/try_catch.hpp index a7ea8bf4b3..eb75e2aa63 100644 --- a/boost/phoenix/statement/try_catch.hpp +++ b/boost/phoenix/statement/try_catch.hpp @@ -15,7 +15,10 @@ #include <boost/phoenix/core/expression.hpp> #include <boost/phoenix/core/meta_grammar.hpp> #include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/scope/local_variable.hpp> +#include <boost/phoenix/scope/scoped_environment.hpp> #include <boost/proto/functional/fusion/pop_front.hpp> +#include <boost/core/enable_if.hpp> #ifdef _MSC_VER #pragma warning(push) @@ -52,8 +55,13 @@ namespace boost { namespace phoenix // bring in the expression definitions #include <boost/phoenix/statement/detail/try_catch_expression.hpp> - template <typename A0, typename A1> + template <typename A0, typename A1, typename A2 = void> struct catch_ + : proto::nary_expr<tag::catch_, A0, A1, A2> + {}; + + template <typename A0, typename A1> + struct catch_<A0, A1, void> : proto::binary_expr<tag::catch_, A0, A1> {}; @@ -65,11 +73,26 @@ namespace boost { namespace phoenix namespace rule { - struct catch_ - : expression::catch_< + typedef + expression::catch_< proto::terminal<catch_exception<proto::_> > + , local_variable , meta_grammar > + captured_catch; + + typedef + expression::catch_< + proto::terminal<catch_exception<proto::_> > + , meta_grammar + > + non_captured_catch; + + struct catch_ + : proto::or_< + captured_catch + , non_captured_catch + > {}; struct catch_all @@ -110,6 +133,48 @@ namespace boost { namespace phoenix void operator()(Try const &, Context const &) const {} + template <typename Catch, typename Exception, typename Context> + typename enable_if<proto::matches<Catch, rule::non_captured_catch> >::type + eval_catch_body(Catch const &c, Exception & /*unused*/, Context const &ctx) const + { + phoenix::eval(proto::child_c<1>(c), ctx); + } + + template <typename Catch, typename Exception, typename Context> + typename enable_if<proto::matches<Catch, rule::captured_catch> >::type + eval_catch_body(Catch const &c, Exception &e, Context const &ctx) const + { + typedef + typename proto::detail::uncvref< + typename proto::result_of::value< + typename proto::result_of::child_c<Catch, 1>::type + >::type + >::type + capture_type; + typedef + typename proto::detail::uncvref< + typename result_of::env<Context>::type + >::type + env_type; + typedef vector1<Exception &> local_type; + typedef detail::map_local_index_to_tuple<capture_type> map_type; + + typedef + phoenix::scoped_environment< + env_type + , env_type + , local_type + , map_type + > + scoped_env_tpe; + + local_type local = {e}; + + scoped_env_tpe env(phoenix::env(ctx), phoenix::env(ctx), local); + + phoenix::eval(proto::child_c<2>(c), phoenix::context(env, phoenix::actions(ctx))); + } + // bring in the operator overloads #include <boost/phoenix/statement/detail/try_catch_eval.hpp> }; @@ -135,12 +200,31 @@ namespace boost { namespace phoenix > , proto::when< phoenix::rule::catch_ - , proto::call< - evaluator( - proto::_child_c<1> - , proto::_data - , proto::make<proto::empty_env()> - ) + , proto::or_< + proto::when< + phoenix::rule::captured_catch + , proto::call< + evaluator( + proto::_child_c<2> + , proto::call< + phoenix::functional::context( + proto::make<mpl::true_()> + , proto::make<detail::scope_is_nullary_actions()> + ) + > + , proto::make<proto::empty_env()> + ) + > + > + , proto::otherwise< + proto::call< + evaluator( + proto::_child_c<1> + , proto::_data + , proto::make<proto::empty_env()> + ) + > + > > > , proto::when< @@ -181,13 +265,48 @@ namespace boost { namespace phoenix template < typename TryCatch , typename Exception + , typename Capture , typename Expr , long Arity = proto::arity_of<TryCatch>::value > struct catch_push_back; + template <typename TryCatch, typename Exception, typename Capture, typename Expr> + struct catch_push_back<TryCatch, Exception, Capture, Expr, 1> + { + typedef + typename proto::result_of::make_expr< + phoenix::tag::catch_ + , proto::basic_default_domain + , catch_exception<Exception> + , Capture + , Expr + >::type + catch_expr; + + typedef + phoenix::expression::try_catch< + TryCatch + , catch_expr + > + gen_type; + typedef typename gen_type::type type; + + static type make(TryCatch const & try_catch, Capture const & capture, Expr const & catch_) + { + return + gen_type::make( + try_catch + , proto::make_expr< + phoenix::tag::catch_ + , proto::basic_default_domain + >(catch_exception<Exception>(), capture, catch_) + ); + } + }; + template <typename TryCatch, typename Exception, typename Expr> - struct catch_push_back<TryCatch, Exception, Expr, 1> + struct catch_push_back<TryCatch, Exception, void, Expr, 1> { typedef typename proto::result_of::make_expr< @@ -271,9 +390,39 @@ namespace boost { namespace phoenix > {}; - template <typename TryCatch, typename Exception> + template <typename TryCatch, typename Exception, typename Capture = void> struct catch_gen { + catch_gen(TryCatch const& try_catch_, Capture const& capture) + : try_catch(try_catch_) + , capture(capture) {} + + template <typename Expr> + typename boost::disable_if< + proto::matches< + typename proto::result_of::child_c< + TryCatch + , proto::arity_of<TryCatch>::value - 1 + >::type + , rule::catch_all + > + , typename detail::catch_push_back<TryCatch, Exception, Capture, Expr>::type + >::type + operator[](Expr const& expr) const + { + return + detail::catch_push_back<TryCatch, Exception, Capture, Expr>::make( + try_catch, capture, expr + ); + } + + TryCatch const & try_catch; + Capture const & capture; + }; + + template <typename TryCatch, typename Exception> + struct catch_gen<TryCatch, Exception, void> + { catch_gen(TryCatch const& try_catch_) : try_catch(try_catch_) {} template <typename Expr> @@ -285,12 +434,12 @@ namespace boost { namespace phoenix >::type , rule::catch_all > - , typename detail::catch_push_back<TryCatch, Exception, Expr>::type + , typename detail::catch_push_back<TryCatch, Exception, void, Expr>::type >::type operator[](Expr const& expr) const { return - detail::catch_push_back<TryCatch, Exception, Expr>::make( + detail::catch_push_back<TryCatch, Exception, void, Expr>::make( try_catch, expr ); } @@ -349,6 +498,13 @@ namespace boost { namespace phoenix return catch_gen<that_type, Exception>(*this); } + template <typename Exception, typename Capture> + catch_gen<that_type, Exception, Capture> const + catch_(Capture const &expr) const + { + return catch_gen<that_type, Exception, Capture>(*this, expr); + } + catch_all_gen<that_type> const catch_all; }; |