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