try_catch.hpp 16 KB

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