diff options
Diffstat (limited to 'src/boost/libs/proto/example/lambda.hpp')
-rw-r--r-- | src/boost/libs/proto/example/lambda.hpp | 1730 |
1 files changed, 1730 insertions, 0 deletions
diff --git a/src/boost/libs/proto/example/lambda.hpp b/src/boost/libs/proto/example/lambda.hpp new file mode 100644 index 00000000..a08d9bf6 --- /dev/null +++ b/src/boost/libs/proto/example/lambda.hpp @@ -0,0 +1,1730 @@ +#ifndef BOOST_PP_IS_ITERATING + /////////////////////////////////////////////////////////////////////////////// + // Copyright 2008 Eric Niebler. Distributed under the Boost + // Software License, Version 1.0. (See accompanying file + // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // + // This example contains a full-featured reimplementation of the old, + // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It + // is necessarily complex to accomodate all the quirks and inconsistencies + // of that old library, but it is a good example of how to build a + // complete and full-featured EDLS using Proto. + #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008 + #define BOOST_LAMBDA_HPP_EAN_04_19_2008 + + #include <iosfwd> + #include <typeinfo> + #include <algorithm> + #include <boost/ref.hpp> + #include <boost/assert.hpp> + #include <boost/mpl/or.hpp> + #include <boost/mpl/int.hpp> + #include <boost/mpl/void.hpp> + #include <boost/mpl/identity.hpp> + #include <boost/mpl/next_prior.hpp> + #include <boost/mpl/min_max.hpp> + #include <boost/mpl/assert.hpp> + #include <boost/preprocessor.hpp> + #include <boost/utility/enable_if.hpp> + #include <boost/utility/result_of.hpp> + #include <boost/fusion/include/vector.hpp> + #include <boost/type_traits/add_reference.hpp> + #include <boost/type_traits/remove_reference.hpp> + #include <boost/type_traits/remove_const.hpp> + #include <boost/type_traits/is_same.hpp> + #include <boost/proto/proto.hpp> + + #ifndef BOOST_LAMBDA_MAX_ARITY + # define BOOST_LAMBDA_MAX_ARITY 3 + #endif + + #ifdef _MSC_VER + # pragma warning(push) + # pragma warning(disable: 4355) // 'this' : used in base member initializer list + # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels + #endif + + namespace boost { namespace lambda + { + namespace tag + { + struct if_ {}; + struct if_else_ {}; + struct for_ {}; + struct while_ {}; + struct do_while_ {}; + struct protect {}; + struct try_ {}; + struct throw_ {}; + struct rethrow_ {}; + struct switch_ {}; + struct default_ {}; + template<int I> struct case_ { static const int value = I; }; + template<typename E> struct catch_ { typedef E exception_type; }; + struct catch_all_ { typedef catch_all_ exception_type; }; + }; + + template<typename Int> + struct placeholder + { + typedef typename Int::tag tag; + typedef typename Int::value_type value_type; + typedef placeholder<Int> type; + typedef placeholder<typename Int::next> next; + typedef placeholder<typename Int::prior> prior; + static const value_type value = Int::value; + + friend std::ostream &operator<<(std::ostream &sout, placeholder) + { + return sout << "boost::lambda::_" << (Int::value+1); + } + }; + + struct exception_placeholder + {}; + + struct no_exception_type {}; + no_exception_type const no_exception = {}; + + // Calculate the arity of a lambda expression + struct Arity + : proto::or_< + proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()> + , proto::when<proto::terminal<proto::_>, mpl::int_<0>()> + , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> > + > + {}; + + // True when a lambda expression can be applied with no arguments and + // without an active exception object + struct IsNullary + : proto::or_< + proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()> + , proto::when<proto::terminal<exception_placeholder>, mpl::false_()> + , proto::when<proto::terminal<proto::_>, mpl::true_()> + , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> > + > + {}; + + struct Eval; + + template<typename Expr, typename State, typename Data> + typename boost::result_of<Eval(Expr&, State&, Data&)>::type + eval_lambda(Expr& e, State& s, Data& d); + + struct EvalWhile : proto::transform<EvalWhile> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef mpl::void_ result_type; + + result_type operator()( + typename impl::expr_param expr + , typename impl::state_param state + , typename impl::data_param data + ) const + { + while(eval_lambda(proto::left(expr), state, data)) + { + eval_lambda(proto::right(expr), state, data); + } + return result_type(); + } + }; + }; + + struct EvalDoWhile : proto::transform<EvalDoWhile> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef mpl::void_ result_type; + + result_type operator()( + typename impl::expr_param expr + , typename impl::state_param state + , typename impl::data_param data + ) const + { + do + { + eval_lambda(proto::child_c<0>(expr), state, data); + } + while(eval_lambda(proto::child_c<1>(expr), state, data)); + + return result_type(); + } + }; + }; + + struct EvalFor : proto::transform<EvalFor> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef mpl::void_ result_type; + + result_type operator()( + typename impl::expr_param expr + , typename impl::state_param state + , typename impl::data_param data + ) const + { + for(eval_lambda(proto::child_c<0>(expr), state, data) + ; eval_lambda(proto::child_c<1>(expr), state, data) + ; eval_lambda(proto::child_c<2>(expr), state, data)) + { + eval_lambda(proto::child_c<3>(expr), state, data); + } + return result_type(); + } + }; + }; + + struct EvalIf : proto::transform<EvalIf> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef mpl::void_ result_type; + + result_type operator()( + typename impl::expr_param expr + , typename impl::state_param state + , typename impl::data_param data + ) const + { + if(eval_lambda(proto::left(expr), state, data)) + { + eval_lambda(proto::right(expr), state, data); + } + return result_type(); + } + }; + }; + + struct EvalIfElse : proto::transform<EvalIfElse> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef mpl::void_ result_type; + + result_type operator()( + typename impl::expr_param expr + , typename impl::state_param state + , typename impl::data_param data + ) const + { + if(eval_lambda(proto::child_c<0>(expr), state, data)) + { + eval_lambda(proto::child_c<1>(expr), state, data); + } + else + { + eval_lambda(proto::child_c<2>(expr), state, data); + } + return result_type(); + } + }; + }; + + struct EvalException : proto::transform<EvalException> + { + template<typename Expr, typename State, typename Data> + struct impl : proto::transform_impl<Expr, State, Data> + { + typedef typename remove_const<typename impl::state>::type result_type; + BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>)); + BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>)); + + typename impl::state_param operator()( + typename impl::expr_param + , typename impl::state_param state + , typename impl::data_param + ) const + { + return state; + } + }; + }; + + struct EvalSwitch : proto::transform<EvalSwitch> + { + template<typename Expr, typename State, typename Data, long Arity, typename BackTag> + struct impl2; + + #define M0(Z, N, DATA) \ + case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \ + eval_lambda(proto::child_c<N>(expr), state, data); \ + break; \ + /**/ + + #define M1(Z, N, DATA) \ + template<typename Expr, typename State, typename Data, typename BackTag> \ + struct impl2<Expr, State, Data, N, BackTag> \ + : proto::transform_impl<Expr, State, Data> \ + { \ + typedef void result_type; \ + \ + void operator()( \ + typename impl2::expr_param expr \ + , typename impl2::state_param state \ + , typename impl2::data_param data \ + ) const \ + { \ + switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ + { \ + BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \ + default: \ + break; \ + } \ + } \ + }; \ + \ + template<typename Expr, typename State, typename Data> \ + struct impl2<Expr, State, Data, N, tag::default_> \ + : proto::transform_impl<Expr, State, Data> \ + { \ + typedef void result_type; \ + \ + void operator()( \ + typename impl2::expr_param expr \ + , typename impl2::state_param state \ + , typename impl2::data_param data \ + ) const \ + { \ + switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ + { \ + BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \ + default:; \ + eval_lambda(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \ + break; \ + } \ + } \ + }; \ + /**/ + BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~) + #undef M0 + #undef M1 + + template<typename Expr, typename State, typename Data> + struct impl + : impl2< + Expr + , State + , Data + , proto::arity_of<Expr>::value + , typename proto::tag_of< + typename proto::result_of::child_c< + Expr + , proto::arity_of<Expr>::value-1 + >::type + >::type + > + {}; + }; + + struct throw_fun + { + BOOST_PROTO_CALLABLE() + typedef void result_type; + template<typename Expr> + void operator()(Expr const &e) const + { + throw e; + } + }; + + struct unwrap_ref : proto::callable + { + template<typename Sig> + struct result; + + template<typename This, typename T> + struct result<This(reference_wrapper<T>)> + { + typedef T &type; + }; + + template<typename This, typename T> + struct result<This(T &)> + : result<This(T)> + {}; + + template<typename T> + T &operator()(reference_wrapper<T> const &ref) const + { + return ref; + } + }; + + struct anytype + { + template<typename T> + anytype(T &) { BOOST_ASSERT(false); } + template<typename T> + operator T &() const { BOOST_ASSERT(false); throw; } + private: + anytype(); + }; + + struct rethrow_fun + { + BOOST_PROTO_CALLABLE() + typedef anytype result_type; + template<typename State> + anytype operator()(State const &) const + { + BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>)); + throw; + } + }; + + struct Cases + { + template<typename Tag> + struct case_ + : proto::otherwise<proto::_default<Eval> > + {}; + + template<typename E> + struct case_<tag::catch_<E> > + : proto::otherwise<Eval(proto::_child)> + {}; + + template<int I> + struct case_<tag::case_<I> > + : proto::otherwise<Eval(proto::_child)> + {}; + }; + + template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {}; + template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {}; + template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {}; + template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {}; + template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {}; + template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {}; + template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {}; + template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {}; + template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {}; + + template<> + struct Cases::case_<proto::tag::terminal> + : proto::or_< + proto::when< + proto::terminal<placeholder<proto::_> > + , proto::functional::at(proto::_data, proto::_value) + > + , proto::when< + proto::terminal<exception_placeholder> + , EvalException + > + , proto::when< + proto::terminal<reference_wrapper<proto::_> > + , unwrap_ref(proto::_value) + > + , proto::otherwise<proto::_default<Eval> > + > + {}; + + template<> + struct Cases::case_<proto::tag::function> + : proto::or_< + proto::when< + proto::function<proto::terminal<rethrow_fun> > + , rethrow_fun(proto::_state) + > + , proto::otherwise<proto::_default<Eval> > + > + {}; + + struct Eval + : proto::switch_<Cases> + {}; + + template<typename Expr, typename State, typename Data> + typename boost::result_of<Eval(Expr&, State&, Data&)>::type + eval_lambda(Expr& e, State& s, Data& d) + { + return Eval()(e, s, d); + } + + // Use a grammar to disable Proto's assignment operator overloads. + // We'll define our own because we want (x+=_1) to store x by + // reference. (In all other cases, variables are stored by value + // within lambda expressions.) + struct Grammar + : proto::switch_<struct AssignOps> + {}; + + struct AssignOps + { + template<typename Tag> struct case_ : proto::_ {}; + }; + + template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {}; + template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {}; + + template<typename Expr> + struct llexpr; + + // Wrap expressions in lambda::llexpr<>. + struct Generator + : proto::pod_generator<llexpr> + {}; + + // The domain for the lambda library. + struct lldomain + : proto::domain<Generator, Grammar, proto::default_domain> + { + // Make all terminals and children held by value instead of by reference. + // Proto::domain<>::as_expr<> holds everything it can by value; the only + // exceptions are function types, abstract types, and iostreams. + template<typename T> + struct as_child + : proto_base_domain::as_expr<T> + {}; + + // The exception is arrays, which should still be held by reference + template<typename T, std::size_t N> + struct as_child<T[N]> + : proto_base_domain::as_child<T[N]> + {}; + }; + + template<typename Sig> + struct llresult; + + template<typename This> + struct llresult<This()> + : mpl::if_c< + result_of<IsNullary(This &)>::type::value + , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)> + , mpl::identity<void> + >::type + {}; + + #define M0(Z, N, DATA) \ + template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \ + struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \ + : result_of< \ + Eval( \ + This & \ + , no_exception_type const & \ + , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \ + ) \ + > \ + {}; \ + /**/ + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~) + #undef M0 + + template<typename Expr> + struct llexpr + { + BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain) + BOOST_PROTO_EXTENDS_ASSIGN() + BOOST_PROTO_EXTENDS_SUBSCRIPT() + + template<typename Sig> + struct result + : llresult<Sig> + {}; + + typename result<llexpr const()>::type + operator()() const + { + fusion::vector0<> args; + return eval_lambda(*this, no_exception, args); + } + + #define M1(Z, N, _) ((0)(1)) + + #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT) + + #define M3(R, SIZE, PRODUCT) \ + template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \ + typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \ + operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \ + { \ + BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \ + BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \ + (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \ + return eval_lambda(*this, no_exception, args); \ + } \ + /**/ + + #define M4(R, _, I, ELEM) \ + BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \ + /**/ + + #define M5(R, _, I, ELEM) \ + BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \ + /**/ + + #define M6(R, _, I, ELEM) \ + BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \ + /**/ + + #define C0 + + #define C1 const + + #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "lambda.hpp")) + #include BOOST_PP_ITERATE() + + #undef C0 + #undef C1 + #undef M1 + #undef M2 + #undef M3 + #undef M4 + #undef M5 + #undef M6 + }; + + typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type; + typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type; + typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type; + + placeholder1_type const _1 = {{{}}}; + placeholder2_type const _2 = {{{}}}; + placeholder3_type const _3 = {{{}}}; + + placeholder1_type const free1 = {{{}}}; + placeholder2_type const free2 = {{{}}}; + placeholder3_type const free3 = {{{}}}; + + typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type; + placeholderE_type const _e = {{{}}}; + + struct byref + { + template<typename Sig> + struct result; + + template<typename This, typename T> + struct result<This(T &)> + { + typedef llexpr<typename proto::terminal<T &>::type> type; + }; + + template<typename This, typename T> + struct result<This(llexpr<T> &)> + { + typedef boost::reference_wrapper<llexpr<T> > type; + }; + + template<typename This, typename T> + struct result<This(llexpr<T> const &)> + { + typedef boost::reference_wrapper<llexpr<T> const> type; + }; + + template<typename T> + typename result<byref(T &)>::type operator()(T &t) const + { + typename result<byref(T &)>::type that = {{t}}; + return that; + } + + template<typename T> + typename result<byref(T const &)>::type operator()(T const &t) const + { + typename result<byref(T const &)>::type that = {{t}}; + return that; + } + + template<typename T> + boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const + { + return boost::ref(t); + } + + template<typename T> + boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const + { + return boost::ref(t); + } + }; + + namespace exprns_ + { + // Ugh, the assign operators (and only the assign operators) store + // their left terminals by reference. That requires this special handling. + #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \ + template<typename T, typename U> \ + typename proto::result_of::make_expr< \ + TAG \ + , lldomain \ + , typename boost::result_of<byref(T &)>::type \ + , U & \ + >::type const \ + operator OP(T &t, U &u) \ + { \ + return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \ + } \ + template<typename T, typename U> \ + typename proto::result_of::make_expr< \ + TAG \ + , lldomain \ + , typename boost::result_of<byref(T &)>::type \ + , U const & \ + >::type const \ + operator OP(T &t, U const &u) \ + { \ + return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \ + } \ + /**/ + + BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign) + BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign) + } + + template<typename T> + struct var_type + { + typedef llexpr<typename proto::terminal<T &>::type> type; + }; + + template<typename T> + llexpr<typename proto::terminal<T &>::type> const + var(T &t) + { + llexpr<typename proto::terminal<T &>::type> that = {{t}}; + return that; + } + + template<typename T> + struct constant_type + : proto::result_of::make_expr< + proto::tag::terminal + , lldomain + , T const & + > + {}; + + template<typename T> + typename constant_type<T>::type const + constant(T const &t) + { + typename constant_type<T>::type that = {{t}}; + return that; + } + + template<typename T> + struct constant_ref_type + { + typedef llexpr<typename proto::terminal<T const &>::type> type; + }; + + template<typename T> + llexpr<typename proto::terminal<T const &>::type> const + constant_ref(T const &t) + { + llexpr<typename proto::terminal<T const &>::type> that = {{t}}; + return that; + } + + template<typename Cond> + struct while_generator + { + explicit while_generator(Cond const &c) + : cond(c) + {} + + template<typename Body> + typename proto::result_of::make_expr< + tag::while_ + , lldomain + , Cond const & + , Body const & + >::type const + operator[](Body const &body) const + { + return proto::make_expr<tag::while_, lldomain>( + boost::ref(this->cond) + , boost::ref(body) + ); + } + + private: + Cond const &cond; + }; + + template<typename Expr> + while_generator<Expr> while_(Expr const &expr) + { + return while_generator<Expr>(expr); + } + + template<typename Expr> + struct else_generator + { + typedef typename proto::result_of::left<Expr const &>::type condition_type; + typedef typename proto::result_of::right<Expr const &>::type body1_type; + + explicit else_generator(Expr const &expr) + : if_(expr) + {} + + template<typename Body2> + typename proto::result_of::make_expr< + tag::if_else_ + , lldomain + , condition_type + , body1_type + , Body2 const & + >::type const + operator[](Body2 const &body2) const + { + return proto::make_expr<tag::if_else_, lldomain>( + boost::ref(proto::left(this->if_)) + , boost::ref(proto::right(this->if_)) + , boost::ref(body2) + ); + } + + private: + Expr const &if_; + }; + + template<typename Expr> + struct with_else : Expr + { + template<typename T> + with_else(T const &expr) + : Expr(expr) + , else_(*this) + {} + + else_generator<Expr> else_; + }; + + template<typename Cond> + struct if_generator + { + explicit if_generator(Cond const &c) + : cond(c) + {} + + template<typename Body> + with_else< + typename proto::result_of::make_expr< + tag::if_ + , lldomain + , Cond const & + , Body const & + >::type + > const + operator[](Body const &body) const + { + return proto::make_expr<tag::if_, lldomain>( + boost::ref(this->cond) + , boost::ref(body) + ); + } + + private: + Cond const &cond; + }; + + template<typename Expr> + if_generator<Expr> if_(Expr const &expr) + { + return if_generator<Expr>(expr); + } + + template<typename Init, typename Cond, typename Oper> + struct for_generator + { + explicit for_generator(Init const &i, Cond const &c, Oper const &o) + : init(i) + , cond(c) + , oper(o) + {} + + template<typename Body> + typename proto::result_of::make_expr< + tag::for_ + , lldomain + , Init const & + , Cond const & + , Oper const & + , Body const & + >::type const + operator[](Body const &body) const + { + return proto::make_expr<tag::for_, lldomain>( + boost::ref(this->init) + , boost::ref(this->cond) + , boost::ref(this->oper) + , boost::ref(body) + ); + } + + private: + Init const &init; + Cond const &cond; + Oper const &oper; + }; + + template<typename Init, typename Cond, typename Oper> + for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o) + { + return for_generator<Init, Cond, Oper>(i, c, o); + } + + template<typename Body> + struct do_while_generator + { + explicit do_while_generator(Body const &b) + : body(b) + {} + + template<typename Cond> + typename proto::result_of::make_expr< + tag::do_while_ + , lldomain + , Body const & + , Cond const & + >::type const + operator()(Cond const &cond) const + { + return proto::make_expr<tag::do_while_, lldomain>( + boost::ref(this->body) + , boost::ref(cond) + ); + } + + private: + Body const &body; + }; + + template<typename Body> + struct do_body + { + explicit do_body(Body const &body) + : while_(body) + {} + + do_while_generator<Body> while_; + }; + + struct do_generator + { + template<typename Body> + do_body<Body> operator[](Body const &body) const + { + return do_body<Body>(body); + } + }; + + do_generator const do_ = {}; + + struct noop_fun + { + typedef void result_type; + void operator()() const {} + }; + + typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type; + noop_type const noop = {{{{{}}}}}; + + template<typename Init, typename Cond, typename Oper> + typename proto::result_of::make_expr< + tag::for_ + , lldomain + , Init const & + , Cond const & + , Oper const & + , noop_type const & + >::type const + for_loop(Init const &init, Cond const &cond, Oper const &oper) + { + return proto::make_expr<tag::for_, lldomain>( + boost::ref(init) + , boost::ref(cond) + , boost::ref(oper) + , boost::ref(noop) + ); + } + + template<typename Init, typename Cond, typename Oper, typename Body> + typename proto::result_of::make_expr< + tag::for_ + , lldomain + , Init const & + , Cond const & + , Oper const & + , Body const & + >::type const + for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body) + { + return proto::make_expr<tag::for_>( + boost::ref(init) + , boost::ref(cond) + , boost::ref(oper) + , boost::ref(body) + ); + } + + template<typename Cond, typename Body> + typename proto::result_of::make_expr< + tag::while_ + , lldomain + , Cond const & + , Body const & + >::type const + while_loop(Cond const &cond, Body const &body) + { + return proto::make_expr<tag::while_, lldomain>( + boost::ref(cond) + , boost::ref(body) + ); + } + + template<typename Cond> + typename proto::result_of::make_expr< + tag::while_ + , lldomain + , Cond const & + , noop_type const & + >::type const + while_loop(Cond const &cond) + { + return proto::make_expr<tag::while_, lldomain>( + boost::ref(cond) + , boost::ref(noop) + ); + } + + template<typename Cond, typename Body> + typename proto::result_of::make_expr< + tag::do_while_ + , lldomain + , Body const & + , Cond const & + >::type const + do_while_loop(Cond const &cond, Body const &body) + { + return proto::make_expr<tag::do_while_, lldomain>( + boost::ref(body) + , boost::ref(cond) + ); + } + + template<typename Cond> + typename proto::result_of::make_expr< + tag::do_while_ + , lldomain + , noop_type const & + , Cond const & + >::type const + do_while_loop(Cond const &cond) + { + return proto::make_expr<tag::do_while_, lldomain>( + boost::ref(noop) + , boost::ref(cond) + ); + } + + template<typename Cond, typename Body1> + typename proto::result_of::make_expr< + tag::if_ + , lldomain + , Cond const & + , Body1 const & + >::type const + if_then(Cond const &cond, Body1 const &body1) + { + return proto::make_expr<tag::if_, lldomain>( + boost::ref(cond) + , boost::ref(body1) + ); + } + + template<typename Cond, typename Body1, typename Body2> + typename proto::result_of::make_expr< + tag::if_else_ + , lldomain + , Cond const & + , Body1 const & + , Body2 const & + >::type const + if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2) + { + return proto::make_expr<tag::if_else_, lldomain>( + boost::ref(cond) + , boost::ref(body1) + , boost::ref(body2) + ); + } + + template<typename Cond, typename Body1, typename Body2> + typename proto::result_of::make_expr< + proto::tag::if_else_ + , lldomain + , Cond const & + , Body1 const & + , Body2 const & + >::type const + if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2) + { + return proto::make_expr<proto::tag::if_else_, lldomain>( + boost::ref(cond) + , boost::ref(body1) + , boost::ref(body2) + ); + } + + template<typename T> + T const &make_const(T const &t) + { + return t; + } + + #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ + template<typename_A(N)> \ + typename proto::result_of::make_expr< \ + proto::tag::function \ + , lldomain \ + , A_const_ref(N) \ + >::type const \ + bind(A_const_ref_a(N)) \ + { \ + return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \ + } \ + \ + template<typename Ret, typename_A(N)> \ + typename proto::result_of::make_expr< \ + proto::tag::function \ + , lldomain \ + , A_const_ref(N) \ + >::type const \ + bind(A_const_ref_a(N)) \ + { \ + return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \ + } \ + /**/ + BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) + #undef M1 + + template<typename Ret, typename Expr> + Expr const &ret(Expr const &expr) + { + return expr; + } + + template<typename Expr> + Expr const &const_parameters(Expr const &expr) + { + return expr; + } + + template<typename Expr> + Expr const &break_const(Expr const &expr) + { + return expr; + } + + template<typename Lambda> + proto::unexpr<Lambda> const + unlambda(Lambda const &lambda) + { + return proto::unexpr<Lambda>(lambda); + } + + template<typename Lambda> + typename proto::result_of::make_expr< + tag::protect + , lldomain + , Lambda const & + >::type const + protect(Lambda const &lambda) + { + return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda)); + } + + template<typename T> + T const std_functor(T const &t) + { + return t; + } + + template<typename T> + struct ll_static_cast_fun + { + typedef T result_type; + + template<typename U> + T operator()(U &u) const + { + return static_cast<T>(u); + } + + template<typename U> + T operator()(U const &u) const + { + return static_cast<T>(u); + } + }; + + template<typename T, typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_static_cast_fun<T> + , U const & + >::type + ll_static_cast(U const &u) + { + ll_static_cast_fun<T> fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + template<typename T> + struct ll_const_cast_fun + { + typedef T result_type; + + template<typename U> + T operator()(U &u) const + { + return const_cast<T>(u); + } + + template<typename U> + T operator()(U const &u) const + { + return const_cast<T>(u); + } + }; + + template<typename T, typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_const_cast_fun<T> + , U const & + >::type + ll_const_cast(U const &u) + { + ll_const_cast_fun<T> fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + template<typename T> + struct ll_dynamic_cast_fun + { + typedef T result_type; + + template<typename U> + T operator()(U &u) const + { + return dynamic_cast<T>(u); + } + + template<typename U> + T operator()(U const &u) const + { + return dynamic_cast<T>(u); + } + }; + + template<typename T, typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_dynamic_cast_fun<T> + , U const & + >::type + ll_dynamic_cast(U const &u) + { + ll_dynamic_cast_fun<T> fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + template<typename T> + struct ll_reinterpret_cast_fun + { + typedef T result_type; + + template<typename U> + T operator()(U &u) const + { + return reinterpret_cast<T>(u); + } + + template<typename U> + T operator()(U const &u) const + { + return reinterpret_cast<T>(u); + } + }; + + template<typename T, typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_reinterpret_cast_fun<T> + , U const & + >::type + ll_reinterpret_cast(U const &u) + { + ll_reinterpret_cast_fun<T> fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + struct ll_sizeof_fun + { + typedef std::size_t result_type; + + template<typename U> + std::size_t operator()(U const &) const + { + return sizeof(U); + } + }; + + template<typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_sizeof_fun + , U const & + >::type + ll_sizeof(U const &u) + { + ll_sizeof_fun fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + struct ll_typeid_fun + { + typedef std::type_info const &result_type; + + template<typename U> + std::type_info const &operator()(U const &) const + { + return typeid(U); + } + }; + + template<typename U> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , ll_typeid_fun + , U const & + >::type + ll_typeid(U const &u) + { + ll_typeid_fun fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); + } + + template<typename T> + struct constructor + { + typedef T result_type; + + T operator()() const + { + return T(); + } + + #define M0(Z, N, DATA) \ + template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ + T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ + { \ + return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ + } \ + /**/ + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) + #undef M0 + }; + + template<typename T> + struct new_ptr + { + typedef T *result_type; + + T *operator()() const + { + return new T(); + } + + #define M0(Z, N, DATA) \ + template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ + T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ + { \ + return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ + } \ + /**/ + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) + #undef M0 + }; + + struct destructor + { + typedef void result_type; + + template<typename T> + void operator()(T const &t) const + { + t.~T(); + } + + template<typename T> + void operator()(T *const &t) const + { + (*t).~T(); + } + }; + + struct delete_ptr + { + typedef void result_type; + template<typename T> + void operator()(T *t) const + { + delete t; + } + }; + + template<typename T> + struct new_array + { + typedef T *result_type; + T *operator()(std::size_t n) const + { + return new T[n]; + } + }; + + struct delete_array + { + typedef void result_type; + template<typename T> + void operator()(T *t) const + { + delete[] t; + } + }; + + template<typename T> + struct type2type {}; + + struct try_catch_nil {}; + + template<typename Head, typename Tail> + struct try_catch_cons : Tail + { + typedef typename Head::proto_tag::exception_type exception_type; + + try_catch_cons(Head const &head, Tail const &tail) + : Tail(tail) + , head(head) + {} + + template<typename State, typename Data> + typename result_of<Tail const(State const &, Data &)>::type + operator()(State const &state, Data &data) const + { + return this->invoke(state, data, type2type<exception_type>()); + } + + private: + // catch(Exception const &) + template<typename State, typename Data, typename Exception> + typename result_of<Tail const(State const &, Data &)>::type + invoke(State const &state, Data &data, type2type<Exception>) const + { + typedef typename result_of<Tail const(State const &, Data &)>::type result_type; + try + { + return static_cast<result_type>(this->Tail::operator()(state, data)); + } + catch(Exception const &e) + { + return static_cast<result_type>(eval_lambda(this->head, e, data)); + } + } + + // catch(...) + template<typename State, typename Data> + typename result_of<Tail const(State const &, Data &)>::type + invoke(State const &state, Data &data, type2type<tag::catch_all_>) const + { + typedef typename result_of<Tail const(State const &, Data &)>::type result_type; + try + { + return static_cast<result_type>(this->Tail::operator()(state, data)); + } + catch(...) + { + return static_cast<result_type>(eval_lambda(this->head, tag::catch_all_(), data)); + } + } + + Head const &head; + }; + + template<typename Head> + struct try_catch_cons<Head, try_catch_nil> : proto::callable + { + try_catch_cons(Head const &head, try_catch_nil const &) + : head(head) + {} + + template<typename Sig> + struct result; + + template<typename This, typename State, typename Data> + struct result<This(State, Data)> + : result_of<Eval(Head const &, State, Data)> + {}; + + template<typename State, typename Data> + typename result_of<Eval(Head const &, State, Data)>::type + operator()(State const &state, Data &data) const + { + return eval_lambda(this->head, state, data); + } + + private: + Head const &head; + }; + + struct try_catch_fun : proto::callable + { + template<typename Sig> + struct result; + + template<typename This, typename Fun, typename State, typename Data> + struct result<This(Fun, State, Data)> + : result_of<Fun(State, Data)> + {}; + + template<typename Fun, typename State, typename Data> + typename result_of<Fun(State const &, Data &)>::type + operator()(Fun const &fun, State const &state, Data &data) const + { + return fun(state, data); + } + }; + + template<> + struct Cases::case_<tag::try_> + : proto::otherwise< + try_catch_fun( + proto::fold< + proto::_ + , try_catch_nil() + , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state) + > + , proto::_state + , proto::_data + ) + > + {}; + + template<typename E, typename Expr> + typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const + catch_exception(Expr const &expr) + { + return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr)); + } + + template<typename E> + typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const + catch_exception() + { + return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop)); + } + + template<typename Expr> + typename proto::result_of::make_expr< + tag::catch_all_ + , lldomain + , Expr const & + >::type const + catch_all(Expr const &expr) + { + return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr)); + } + + inline + proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const + catch_all() + { + return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop)); + } + + #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ + template<typename_A(N)> \ + typename proto::result_of::make_expr< \ + tag::try_ \ + , lldomain \ + , A_const_ref(N) \ + >::type const \ + try_catch(A_const_ref_a(N)) \ + { \ + return proto::make_expr<tag::try_, lldomain>(ref_a(N)); \ + } \ + /**/ + BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) + #undef M1 + + template<typename Expr> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , throw_fun + , Expr const & + >::type const + throw_exception(Expr const &expr) + { + throw_fun fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr)); + } + + inline + proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const + rethrow() + { + return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun()); + } + + struct make_void_fun + { + typedef void result_type; + template<typename T> + void operator()(T const &) const + {} + }; + + template<typename Expr> + typename proto::result_of::make_expr< + proto::tag::function + , lldomain + , make_void_fun + , Expr const & + >::type const + make_void(Expr const &expr) + { + make_void_fun fun; + return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr)); + } + + #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ + template<typename_A(N)> \ + typename proto::result_of::make_expr< \ + tag::switch_ \ + , lldomain \ + , A_const_ref(N) \ + >::type const \ + switch_statement(A_const_ref_a(N)) \ + { \ + return proto::make_expr<tag::switch_, lldomain>(ref_a(N)); \ + } \ + /**/ + BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) + #undef M1 + + template<int I, typename Expr> + typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const + case_statement(Expr const &expr) + { + return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr)); + } + + template<int I> + typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const + case_statement() + { + return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop)); + } + + template<typename Expr> + typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const + default_statement(Expr const &expr) + { + return proto::make_expr<tag::default_, lldomain>(boost::ref(expr)); + } + + inline + proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const + default_statement() + { + return proto::make_expr<tag::default_, lldomain>(boost::ref(noop)); + } + + namespace ll + { + struct for_each + { + template<typename Sig> + struct result; + + template<typename This, typename Begin, typename End, typename Fun> + struct result<This(Begin, End, Fun)> + : remove_const<typename remove_reference<Fun>::type> + {}; + + template<typename InIter, typename Fun> + Fun operator()(InIter begin, InIter end, Fun fun) const + { + return std::for_each(begin, end, fun); + } + }; + } + + }} + + namespace boost + { + template<typename Expr> + struct result_of<lambda::llexpr<Expr>()> + : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()> + {}; + + template<typename Expr> + struct result_of<lambda::llexpr<Expr> const()> + : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()> + {}; + } + + #ifdef _MSC_VER + # pragma warning(pop) + #endif + + #endif + +#else + + BOOST_PP_SEQ_FOR_EACH_PRODUCT( + M2, + BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~) + ) + +#endif |