|
Boost-Commit : |
From: eric_at_[hidden]
Date: 2008-05-26 19:59:51
Author: eric_niebler
Date: 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
New Revision: 45802
URL: http://svn.boost.org/trac/boost/changeset/45802
Log:
more powerful extensible grammar, proper grammar checking for local variables
Text files modified:
branches/proto/v4/boost/phoenix/core/actor.hpp | 157 +++++++++++++++++++++++++++++++--------
branches/proto/v4/boost/phoenix/core/argument.hpp | 14 +-
branches/proto/v4/boost/phoenix/core/value.hpp | 8 +-
branches/proto/v4/boost/phoenix/scope/let.hpp | 137 ++++++++++++++++++++++++++--------
branches/proto/v4/boost/phoenix/scope/local_variable.hpp | 20 ++--
branches/proto/v4/boost/phoenix/statement/do_while.hpp | 15 ++-
branches/proto/v4/boost/phoenix/statement/for.hpp | 25 ++++--
branches/proto/v4/boost/phoenix/statement/if.hpp | 32 ++++---
branches/proto/v4/boost/phoenix/statement/switch.hpp | 70 ++++++++++-------
branches/proto/v4/boost/phoenix/statement/try_catch.hpp | 66 +++++++++++-----
branches/proto/v4/boost/phoenix/statement/while.hpp | 15 ++-
11 files changed, 386 insertions(+), 173 deletions(-)
Modified: branches/proto/v4/boost/phoenix/core/actor.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/core/actor.hpp (original)
+++ branches/proto/v4/boost/phoenix/core/actor.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -10,12 +10,14 @@
#include <iosfwd>
#include <boost/phoenix/core/limits.hpp>
+ #include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/void.hpp>
+ #include <boost/mpl/assert.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/proto/proto.hpp>
#include <boost/type_traits/is_abstract.hpp>
@@ -32,23 +34,24 @@
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar = proto::not_<proto::_>, typename X = proto::callable>
struct evaluator;
}
using detail::evaluator;
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Tag, typename Void = void>
+ template<typename Tag, typename SubGrammar>
struct extension;
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Value, typename Void = void>
+ template<typename Value, typename SubGrammar>
struct terminal_extension
- : proto::_value
+ : proto::otherwise<proto::_value>
{};
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Value, typename Void = void>
+ template<typename Value, typename SubGrammar>
struct is_terminal_nullary
: mpl::true_
{};
@@ -62,43 +65,94 @@
using actorns_::actor;
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
+ struct is_nullary_cases;
+
////////////////////////////////////////////////////////////////////////////////////////
// True when a lambda expression can be applied with no arguments and
// without an active exception object
+ template<typename SubGrammar = proto::not_<proto::_>, typename X = proto::callable>
struct is_nullary
- : proto::switch_<struct is_nullary_cases>
+ : proto::and_<
+ evaluator<SubGrammar> // only valid expressions can be evaluated as "nullary"
+ , proto::or_<
+ SubGrammar
+ , proto::switch_<is_nullary_cases<SubGrammar> >
+ >
+ >
+ {};
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ template<typename Tag, typename SubGrammar>
+ struct is_nullary_extension
+ : proto::otherwise<
+ proto::fold<
+ proto::_
+ , mpl::true_()
+ , mpl::and_<proto::_state, is_nullary<SubGrammar> >()
+ >
+ >
{};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
struct is_nullary_cases
{
- template<typename Tag>
+ private:
+ template<typename T>
+ struct is_terminal_nullary_local
+ : is_terminal_nullary<T, SubGrammar>
+ {};
+
+ public:
+ template<typename Tag, typename X = void>
struct case_
- : proto::otherwise<
- proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, is_nullary>()>
- >
+ : is_nullary_extension<Tag, SubGrammar>
{};
- };
- template<>
- struct is_nullary_cases::case_<proto::tag::terminal>
- : proto::otherwise<is_terminal_nullary<proto::_value>()>
- {};
+ template<typename X>
+ struct case_<proto::tag::terminal, X>
+ : proto::otherwise<is_terminal_nullary_local<proto::_value>()>
+ {};
+ };
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
struct evaluator_cases
{
- template<typename Tag>
+ private:
+ template<typename Value>
+ struct terminal_extension_local
+ : terminal_extension<Value, SubGrammar>
+ {};
+
+ public:
+ template<typename Tag, typename X = void>
struct case_
- : phoenix::extension<Tag>
+ : phoenix::extension<Tag, SubGrammar>
+ {};
+
+ template<typename X>
+ struct case_<proto::tag::terminal, X>
+ : proto::when<
+ proto::if_<
+ proto::matches<proto::_, terminal_extension_local<proto::_value>()>()
+ >
+ , proto::lazy<terminal_extension_local<proto::_value> >
+ >
{};
};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar, typename Callable>
struct evaluator
- : proto::switch_<evaluator_cases>
+ : proto::or_<
+ SubGrammar
+ , proto::switch_<evaluator_cases<SubGrammar> >
+ >
{};
////////////////////////////////////////////////////////////////////////////////////////
@@ -186,8 +240,8 @@
template<typename This>
struct result<This()>
: mpl::if_c<
- result_of<is_nullary(This &)>::type::value
- , result_of<evaluator(This &, initial_state_type, fusion::vector0 &)>
+ result_of<is_nullary<>(This &)>::type::value
+ , result_of<evaluator<>(This &, initial_state_type, fusion::vector0 &)>
, mpl::identity<void>
>::type
{};
@@ -196,7 +250,7 @@
template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
struct result<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \
: result_of< \
- evaluator( \
+ evaluator<>( \
This & \
, initial_state_type \
, BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \
@@ -207,6 +261,16 @@
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(PHOENIX_LIMIT), M0, ~)
#undef M0
}
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ struct INVALID_LAMBDA_EXPRESSION
+ : mpl::false_
+ {};
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ struct VALID_LAMBDA_EXPRESSION
+ : mpl::true_
+ {};
namespace actorns_
{
@@ -226,9 +290,8 @@
typename result<Expr const()>::type
operator()() const
{
- BOOST_MPL_ASSERT((proto::matches<Expr, evaluator>));
fusion::vector0 args;
- return evaluator()(*this, mpl::void_(), args);
+ return this->evaluate(args);
}
#define M0(Z, N, _) ((0))
@@ -242,10 +305,9 @@
typename result<Expr 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((proto::matches<Expr, evaluator>)); \
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 evaluator()(*this, mpl::void_(), args); \
+ return this->evaluate(args); \
} \
/**/
@@ -277,25 +339,54 @@
#undef M4
#undef M5
#undef M6
+
+ private:
+ template<typename Args>
+ typename result_of<evaluator<>(Expr const &, detail::initial_state_type, Args &)>::type
+ evaluate(Args &args) const
+ {
+ typedef typename
+ mpl::if_<
+ proto::matches<Expr, evaluator<> >
+ , VALID_LAMBDA_EXPRESSION
+ , INVALID_LAMBDA_EXPRESSION
+ >::type
+ IS_VALID_LAMBDA_EXPRESSION;
+
+ // If your compile breaks here, your lambda expression doesn't validate against
+ // the Phoenix lambda grammar. Go back and check your expression for well-formedness.
+ BOOST_MPL_ASSERT((IS_VALID_LAMBDA_EXPRESSION));
+
+ return this->evaluate(args, IS_VALID_LAMBDA_EXPRESSION());
+ }
+
+ template<typename Args>
+ typename result_of<evaluator<>(Expr const &, detail::initial_state_type, Args &)>::type
+ evaluate(Args &args, mpl::true_) const
+ {
+ return evaluator<>()(this->proto_base(), mpl::void_(), args);
+ }
+
+ template<typename Args>
+ typename result_of<evaluator<>(Expr const &, detail::initial_state_type, Args &)>::type
+ evaluate(Args &args, mpl::false_) const
+ {
+ BOOST_ASSERT(false);
+ throw "never called";
+ }
};
} // namespace actorns_
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Tag, typename Void>
+ template<typename Tag, typename SubGrammar>
struct extension
: proto::when<
- proto::nary_expr<proto::_, proto::vararg<evaluator> >
- , proto::_default<evaluator>
+ proto::nary_expr<proto::_, proto::vararg<evaluator<SubGrammar> > >
+ , proto::_default<evaluator<SubGrammar> >
>
{};
- ////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<proto::tag::terminal, void>
- : proto::otherwise<proto::lazy<terminal_extension<proto::_value> > >
- {};
-
}}
#endif
Modified: branches/proto/v4/boost/phoenix/core/argument.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/core/argument.hpp (original)
+++ branches/proto/v4/boost/phoenix/core/argument.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -81,21 +81,21 @@
actor<argument<I> > const argument<I,_>::argI = {{{{}}}};
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Int, typename Void>
+ template<typename Value, typename SubGrammar>
struct is_terminal_nullary;
- template<typename Int>
- struct is_terminal_nullary<detail::argument<Int>, void>
+ template<typename Int, typename SubGrammar>
+ struct is_terminal_nullary<detail::argument<Int>, SubGrammar>
: mpl::false_
{};
////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Int, typename Void>
+ template<typename Value, typename SubGrammar>
struct terminal_extension;
- template<typename Int>
- struct terminal_extension<detail::argument<Int>, void>
- : proto::call<detail::at<Int>(proto::_data)>
+ template<typename Int, typename SubGrammar>
+ struct terminal_extension<detail::argument<Int>, SubGrammar>
+ : proto::otherwise<detail::at<Int>(proto::_data)>
{};
////////////////////////////////////////////////////////////////////////////////////////////
Modified: branches/proto/v4/boost/phoenix/core/value.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/core/value.hpp (original)
+++ branches/proto/v4/boost/phoenix/core/value.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -71,11 +71,11 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::byval>
+ template<typename SubGrammar>
+ struct extension<tag::byval, SubGrammar>
: proto::when<
- proto::unary_expr<tag::byval, evaluator>
- , remove_reference<evaluator(proto::_child)>(evaluator(proto::_child))
+ proto::unary_expr<tag::byval, evaluator<SubGrammar> >
+ , remove_reference<evaluator<SubGrammar>(proto::_child)>(evaluator<SubGrammar>(proto::_child))
>
{};
Modified: branches/proto/v4/boost/phoenix/scope/let.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/scope/let.hpp (original)
+++ branches/proto/v4/boost/phoenix/scope/let.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -54,7 +54,7 @@
};
////////////////////////////////////////////////////////////////////////////////////////
- template<typename State, typename Data>
+ template<typename State, typename Data, typename SubGrammar>
struct initialize_locals
{
explicit initialize_locals(State state, Data data)
@@ -76,7 +76,7 @@
typedef
fusion::pair<
First
- , typename boost::result_of<evaluator(Second, State, Data)>::type
+ , typename boost::result_of<evaluator<SubGrammar>(Second, State, Data)>::type
>
type;
};
@@ -84,17 +84,17 @@
template<typename First, typename Second>
fusion::pair<
First
- , typename boost::result_of<evaluator(Second, State, Data)>::type
+ , typename boost::result_of<evaluator<SubGrammar>(Second, State, Data)>::type
> const
operator()(fusion::pair<First, Second> const &p) const
{
typedef
fusion::pair<
First
- , typename boost::result_of<evaluator(Second, State, Data)>::type
+ , typename boost::result_of<evaluator<SubGrammar>(Second, State, Data)>::type
>
pair_type;
- return pair_type(evaluator()(p.second, this->state, this->data));
+ return pair_type(evaluator<SubGrammar>()(p.second, this->state, this->data));
}
private:
@@ -103,7 +103,7 @@
};
////////////////////////////////////////////////////////////////////////////////////////
- template<typename Map, typename State, typename Data>
+ template<typename Map, typename State, typename Data, typename SubGrammar>
struct scope
{
typedef typename remove_reference<State>::type state_type;
@@ -112,7 +112,7 @@
fusion::result_of::as_map<typename
fusion::result_of::transform<
typename remove_reference<Map>::type
- , initialize_locals<State, Data>
+ , initialize_locals<State, Data, SubGrammar>
>::type
>::type
locals_type;
@@ -120,7 +120,7 @@
scope(Map map, State state, Data data)
: state(state)
, data(data)
- , locals(fusion::as_map(fusion::transform(map, initialize_locals<State, Data>(state, data))))
+ , locals(fusion::as_map(fusion::transform(map, initialize_locals<State, Data, SubGrammar>(state, data))))
{}
State state; // outer state
@@ -129,15 +129,16 @@
};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar, typename X = proto::callable>
struct make_scope
- : proto::transform<make_scope>
+ : proto::transform<make_scope<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl
: proto::transform_impl<Expr, State, Data>
{
typedef typename proto::result_of::value<Expr>::type map_type;
- typedef scope<map_type, typename impl::state_param, Data> result_type;
+ typedef scope<map_type, typename impl::state_param, Data, SubGrammar> result_type;
result_type operator()(
typename impl::expr_param expr
@@ -150,17 +151,94 @@
};
};
- ////////////////////////////////////////////////////////////////////////////////////////
- struct is_let_init_nullary
+ template<typename SubGrammar>
+ struct with_grammar
{
- template<typename Sig>
- struct result;
+ ////////////////////////////////////////////////////////////////////////////////////
+ template<typename Map>
+ struct with_locals
+ {
+ // The grammar for valid lambda expressions changes within the body of a let()
+ // expression. In particular, the local variables declared in the let() call
+ // become valid terminals in the let() body.
+ typedef
+ evaluator<
+ proto::or_<
+ // If the current expression is a local variable declared in
+ // a let() call ...
+ proto::when<
+ proto::and_<
+ proto::terminal<detail::local_variable<proto::_> >
+ , proto::if_<
+ fusion::result_of::has_key<
+ Map
+ , detail::local_variable_tag<proto::_value>
+ >()
+ >
+ >
+ // ... evaluate it using the local variable evaluator
+ , proto::lazy<
+ detail::local_variable_evaluator<
+ detail::local_variable_tag<proto::_value>
+ >
+ >
+ >
+ // Otherwise, defer handling of the current expression to the
+ // currently active sub-grammar. This will also handle local
+ // variables declared in outer let() expressions.
+ , SubGrammar
+ >
+ >
+ type;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ struct let_extension
+ : proto::when<
+ proto::and_<
+ proto::binary_expr<tag::let_, proto::terminal<proto::_>, proto::_>
+ , proto::if_<
+ proto::matches<
+ proto::_right
+ , with_locals<proto::_value(proto::_left)>()
+ >()
+ >
+ >
+ , proto::lazy<
+ with_locals<proto::_value(proto::_left)>(
+ proto::_right
+ , detail::make_scope<SubGrammar>(proto::_left)
+ , proto::_data
+ )
+ >
+ >
+ {};
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ struct is_nullary
+ : phoenix::is_nullary<SubGrammar>
+ {};
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ struct is_nullary_fun
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Elem, typename State>
+ struct result<This(Elem &, State &)>
+ : mpl::and_<State, result_of<is_nullary(typename Elem::second_type)> >
+ {};
+ };
- template<typename This, typename Elem, typename State>
- struct result<This(Elem &, State &)>
- : mpl::and_<
- State
- , typename result_of<is_nullary(typename fusion::result_of::second<Elem>::type)>::type
+ ////////////////////////////////////////////////////////////////////////////////////
+ struct is_nullary_extension
+ : proto::otherwise<
+ fusion::result_of::fold<
+ proto::_value(proto::_left)
+ , proto::call<is_nullary(proto::_right)>
+ , proto::make<is_nullary_fun>
+ >()
>
{};
};
@@ -169,26 +247,17 @@
////////////////////////////////////////////////////////////////////////////////////////////
// Evaluate a let() expression by evaluating the body with a state that contains
// a map of the local variables and a reference to the enclosing scope.
- template<>
- struct extension<tag::let_, void>
- : proto::when<
- proto::binary_expr<tag::let_, proto::terminal<proto::_>, evaluator>
- , evaluator(proto::_right, detail::make_scope(proto::_left), proto::_data)
- >
+ template<typename SubGrammar>
+ struct extension<tag::let_, SubGrammar>
+ : detail::with_grammar<SubGrammar>::let_extension
{};
////////////////////////////////////////////////////////////////////////////////////////////
// BUGBUG this isn't quite right. It gets the answer wrong for
// let(_a = 1)[ _a += arg1 ]
- template<>
- struct is_nullary_cases::case_<tag::let_>
- : proto::otherwise<
- fusion::result_of::fold<
- proto::_value(proto::_left)
- , mpl::true_()
- , detail::is_let_init_nullary()
- >()
- >
+ template<typename SubGrammar>
+ struct is_nullary_extension<tag::let_, SubGrammar>
+ : detail::with_grammar<SubGrammar>::is_nullary_extension
{};
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, PHOENIX_LIMIT, <boost/phoenix/scope/let.hpp>))
Modified: branches/proto/v4/boost/phoenix/scope/local_variable.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/scope/local_variable.hpp (original)
+++ branches/proto/v4/boost/phoenix/scope/local_variable.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -23,6 +23,13 @@
{
typedef Tag tag_type;
};
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ template<typename Local>
+ struct local_variable_tag
+ {
+ typedef typename Local::tag_type type;
+ };
////////////////////////////////////////////////////////////////////////////////////////////
// Find a variable in the immediately enclosing scope
@@ -98,15 +105,10 @@
};
////////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Tag>
- struct terminal_extension<detail::local_variable<Tag> >
- : detail::local_variable_evaluator<Tag>
- {};
-
- ////////////////////////////////////////////////////////////////////////////////////////////////
- template<typename Tag>
- struct is_terminal_nullary<detail::local_variable<Tag> >
- : mpl::false_
+ // Bare local variables (outside of a let() or lambda()) are not valid lambda expressions.
+ template<typename Tag, typename SubGrammar>
+ struct terminal_extension<detail::local_variable<Tag>, SubGrammar>
+ : proto::not_<proto::_>
{};
////////////////////////////////////////////////////////////////////////////////////////////////
Modified: branches/proto/v4/boost/phoenix/statement/do_while.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/do_while.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/do_while.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -75,7 +75,8 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates do_[ body ].while_( condition )
- struct do_while_evaluator : proto::transform<do_while_evaluator>
+ template<typename SubGrammar, typename X = proto::callable>
+ struct do_while_evaluator : proto::transform<do_while_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
@@ -90,9 +91,9 @@
{
do
{
- evaluator()(proto::child_c<0>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<0>(expr), state, data);
}
- while(evaluator()(proto::child_c<1>(expr), state, data));
+ while(evaluator<SubGrammar>()(proto::child_c<1>(expr), state, data));
}
};
};
@@ -102,11 +103,11 @@
detail::do_generator const do_ = {};
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::do_while_, void>
+ template<typename SubGrammar>
+ struct extension<tag::do_while_, SubGrammar>
: proto::when<
- proto::nary_expr<tag::do_while_, evaluator, evaluator>
- , detail::do_while_evaluator
+ proto::nary_expr<tag::do_while_, evaluator<SubGrammar>, evaluator<SubGrammar> >
+ , detail::do_while_evaluator<SubGrammar>
>
{};
Modified: branches/proto/v4/boost/phoenix/statement/for.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/for.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/for.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -54,7 +54,8 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates for_(x,y,z)[expr]
- struct for_evaluator : proto::transform<for_evaluator>
+ template<typename SubGrammar, typename X = proto::callable>
+ struct for_evaluator : proto::transform<for_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
@@ -67,11 +68,11 @@
, typename impl::data_param data
) const
{
- for(evaluator()(proto::child_c<0>(expr), state, data)
- ; evaluator()(proto::child_c<1>(expr), state, data)
- ; evaluator()(proto::child_c<2>(expr), state, data))
+ for(evaluator<SubGrammar>()(proto::child_c<0>(expr), state, data)
+ ; evaluator<SubGrammar>()(proto::child_c<1>(expr), state, data)
+ ; evaluator<SubGrammar>()(proto::child_c<2>(expr), state, data))
{
- evaluator()(proto::child_c<3>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<3>(expr), state, data);
}
}
};
@@ -87,11 +88,17 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::for_, void>
+ template<typename SubGrammar>
+ struct extension<tag::for_, SubGrammar>
: proto::when<
- proto::nary_expr<tag::for_, evaluator, evaluator, evaluator, evaluator>
- , detail::for_evaluator
+ proto::nary_expr<
+ tag::for_
+ , evaluator<SubGrammar>
+ , evaluator<SubGrammar>
+ , evaluator<SubGrammar>
+ , evaluator<SubGrammar>
+ >
+ , detail::for_evaluator<SubGrammar>
>
{};
Modified: branches/proto/v4/boost/phoenix/statement/if.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/if.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/if.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -109,7 +109,8 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates if_(condition)[ expression ]
- struct if_evaluator : proto::transform<if_evaluator>
+ template<typename SubGrammar, typename X = proto::callable>
+ struct if_evaluator : proto::transform<if_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
@@ -122,9 +123,9 @@
, typename impl::data_param data
) const
{
- if(evaluator()(proto::left(expr), state, data))
+ if(evaluator<SubGrammar>()(proto::left(expr), state, data))
{
- evaluator()(proto::right(expr), state, data);
+ evaluator<SubGrammar>()(proto::right(expr), state, data);
}
}
};
@@ -132,7 +133,8 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates if_(condition)[ expression ].else_[ expression ]
- struct if_else_evaluator : proto::transform<if_else_evaluator>
+ template<typename SubGrammar, typename X = proto::callable>
+ struct if_else_evaluator : proto::transform<if_else_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
@@ -145,13 +147,13 @@
, typename impl::data_param data
) const
{
- if(evaluator()(proto::child_c<0>(expr), state, data))
+ if(evaluator<SubGrammar>()(proto::child_c<0>(expr), state, data))
{
- evaluator()(proto::child_c<1>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<1>(expr), state, data);
}
else
{
- evaluator()(proto::child_c<2>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<2>(expr), state, data);
}
}
};
@@ -167,20 +169,20 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::if_, void>
+ template<typename SubGrammar>
+ struct extension<tag::if_, SubGrammar>
: proto::when<
- proto::binary_expr<tag::if_, evaluator, evaluator>
- , detail::if_evaluator
+ proto::binary_expr<tag::if_, evaluator<SubGrammar>, evaluator<SubGrammar> >
+ , detail::if_evaluator<SubGrammar>
>
{};
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::else_, void>
+ template<typename SubGrammar>
+ struct extension<tag::else_, SubGrammar>
: proto::when<
- proto::nary_expr<tag::else_, evaluator, evaluator, evaluator>
- , detail::if_else_evaluator
+ proto::nary_expr<tag::else_, evaluator<SubGrammar>, evaluator<SubGrammar>, evaluator<SubGrammar> >
+ , detail::if_else_evaluator<SubGrammar>
>
{};
Modified: branches/proto/v4/boost/phoenix/statement/switch.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/switch.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/switch.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -56,10 +56,15 @@
};
// Define the grammar for valid switch statements
+ template<typename SubGrammar>
+ struct CaseCases;
+
+ template<typename SubGrammar>
struct Case
- : proto::switch_<struct CaseCases>
+ : proto::switch_<CaseCases<SubGrammar> >
{};
+ template<typename SubGrammar>
struct CaseCases
{
template<typename Tag>
@@ -69,33 +74,37 @@
template<int Label>
struct case_<tag::case_<Label> >
- : proto::unary_expr<proto::_, evaluator>
+ : proto::unary_expr<proto::_, evaluator<SubGrammar> >
{};
};
+ template<typename SubGrammar>
struct Default
- : proto::unary_expr<tag::default_, evaluator>
+ : proto::unary_expr<tag::default_, evaluator<SubGrammar> >
{};
+ template<typename SubGrammar>
struct CasesNoDefault
: proto::or_<
- Case
- , proto::comma<CasesNoDefault, Case>
+ Case<SubGrammar>
+ , proto::comma<CasesNoDefault<SubGrammar>, Case<SubGrammar> >
>
{};
+ template<typename SubGrammar>
struct CasesWithDefault
: proto::or_<
- Default
- , proto::comma<CasesNoDefault, Default>
+ Default<SubGrammar>
+ , proto::comma<CasesNoDefault<SubGrammar>, Default<SubGrammar> >
>
{};
+ template<typename SubGrammar>
struct Switch
: proto::binary_expr<
tag::switch_
- , evaluator
- , proto::or_<CasesNoDefault, CasesWithDefault>
+ , evaluator<SubGrammar>
+ , proto::or_<CasesNoDefault<SubGrammar>, CasesWithDefault<SubGrammar> >
>
{};
@@ -104,8 +113,9 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates switch(condition)[ case_<0>(expr), case_<1>(expr), ... ]
+ template<typename SubGrammar, typename X = proto::callable>
struct switch_evaluator
- : proto::transform<switch_evaluator>
+ : proto::transform<switch_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl
@@ -119,14 +129,13 @@
, typename impl::data_param data
) const
{
- detail::do_switch(
+ detail::do_switch<SubGrammar>(
expr.proto_base().child0, state, data
, expr.proto_base().child1.proto_base()
);
}
};
};
-
}
////////////////////////////////////////////////////////////////////////////////////////////
@@ -161,23 +170,25 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::switch_, void>
+ template<typename SubGrammar>
+ struct extension<tag::switch_, SubGrammar>
: proto::when<
- detail::Switch
- , detail::switch_evaluator
+ detail::Switch<SubGrammar>
+ , detail::switch_evaluator<SubGrammar>
>
{};
////////////////////////////////////////////////////////////////////////////////////////////
- template<int Label>
- struct is_nullary_cases::case_<tag::case_<Label> >
+ // Don't try to evaluate the return type of case_<1>(expr)()
+ template<int Label, typename SubGrammar>
+ struct is_nullary_extension<tag::case_<Label>, SubGrammar>
: proto::otherwise<mpl::false_()>
{};
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct is_nullary_cases::case_<tag::default_>
+ // Don't try to evaluate the return type of default(expr)()
+ template<typename SubGrammar>
+ struct is_nullary_extension<tag::default_, SubGrammar>
: proto::otherwise<mpl::false_()>
{};
@@ -199,13 +210,14 @@
#define M1(Z, N, DATA) \
case BOOST_PP_CAT(L, N): \
- evaluator()(BOOST_PP_CAT(a, N).child0, state, data); \
+ evaluator<SubGrammar>()(BOOST_PP_CAT(a, N).child0, state, data); \
break; \
/**/
////////////////////////////////////////////////////////////////////////////////////////////
template<
- typename Expr, typename State, typename Data
+ typename SubGrammar
+ , typename Expr, typename State, typename Data
, typename Args
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
>
@@ -216,7 +228,7 @@
)
{
// Fan out the arguments
- detail::do_switch(
+ detail::do_switch<SubGrammar>(
expr, state, data
, cases.child0.proto_base()
, cases.child1.proto_base()
@@ -226,7 +238,8 @@
////////////////////////////////////////////////////////////////////////////////////////////
template<
- typename Expr, typename State, typename Data
+ typename SubGrammar
+ , typename Expr, typename State, typename Data
BOOST_PP_ENUM_TRAILING_PARAMS(N, int L)
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, int BOOST_PP_CAT(L, N), typename BOOST_PP_CAT(A, N)
@@ -237,7 +250,7 @@
, proto::expr<tag::case_<BOOST_PP_CAT(L, N)>, BOOST_PP_CAT(A, N), 1> const &BOOST_PP_CAT(a, N)
)
{
- switch(evaluator()(expr, state, data))
+ switch(evaluator<SubGrammar>()(expr, state, data))
{
BOOST_PP_REPEAT(BOOST_PP_INC(N), M1, ~)
default:;
@@ -246,7 +259,8 @@
////////////////////////////////////////////////////////////////////////////////////////////
template<
- typename Expr, typename State, typename Data
+ typename SubGrammar
+ , typename Expr, typename State, typename Data
BOOST_PP_ENUM_TRAILING_PARAMS(N, int L)
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, typename BOOST_PP_CAT(A, N)
@@ -257,11 +271,11 @@
, proto::expr<tag::default_, BOOST_PP_CAT(A, N), 1> const &BOOST_PP_CAT(a, N)
)
{
- switch(evaluator()(expr, state, data))
+ switch(evaluator<SubGrammar>()(expr, state, data))
{
BOOST_PP_REPEAT(N, M1, ~)
default:
- evaluator()(BOOST_PP_CAT(a, N).child0, state, data);
+ evaluator<SubGrammar>()(BOOST_PP_CAT(a, N).child0, state, data);
break;
}
}
Modified: branches/proto/v4/boost/phoenix/statement/try_catch.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/try_catch.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/try_catch.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -35,15 +35,22 @@
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
struct Try
- : proto::unary_expr<tag::try_, evaluator>
+ : proto::unary_expr<tag::try_, evaluator<SubGrammar> >
{};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
+ struct CatchCases;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
struct Catch
- : proto::switch_<struct CatchCases>
+ : proto::switch_<CatchCases<SubGrammar> >
{};
+ template<typename SubGrammar>
struct CatchCases
{
template<typename Tag>
@@ -53,13 +60,22 @@
template<typename E>
struct case_<tag::catch_<E> >
- : proto::binary_expr<tag::catch_<E>, proto::or_<Try, Catch>, evaluator>
+ : proto::binary_expr<
+ tag::catch_<E>
+ , proto::or_<Try<SubGrammar>, Catch<SubGrammar> >
+ , evaluator<SubGrammar>
+ >
{};
};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar>
struct CatchAll
- : proto::binary_expr<tag::catch_all, proto::or_<Try, Catch>, evaluator>
+ : proto::binary_expr<
+ tag::catch_all
+ , proto::or_<Try<SubGrammar>, Catch<SubGrammar> >
+ , evaluator<SubGrammar>
+ >
{};
////////////////////////////////////////////////////////////////////////////////////////
@@ -154,8 +170,9 @@
};
////////////////////////////////////////////////////////////////////////////////////////
+ template<typename SubGrammar, typename X = proto::callable>
struct catch_all_evaluator
- : proto::transform<catch_all_evaluator>
+ : proto::transform<catch_all_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl
@@ -171,20 +188,20 @@
{
try
{
- evaluator()(proto::child_c<0>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<0>(expr), state, data);
}
catch(...)
{
- evaluator()(proto::child_c<1>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<1>(expr), state, data);
}
}
};
};
////////////////////////////////////////////////////////////////////////////////////////
- template<typename E>
+ template<typename E, typename SubGrammar, typename X = proto::callable>
struct catch_evaluator
- : proto::transform<catch_evaluator<E> >
+ : proto::transform<catch_evaluator<E, SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl
@@ -200,11 +217,11 @@
{
try
{
- evaluator()(proto::child_c<0>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<0>(expr), state, data);
}
catch(E const &)
{
- evaluator()(proto::child_c<1>(expr), state, data);
+ evaluator<SubGrammar>()(proto::child_c<1>(expr), state, data);
}
}
};
@@ -215,21 +232,30 @@
detail::try_generator const try_ = {};
////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::try_>
- : proto::when<proto::not_<proto::_>, evaluator(proto::_child)>
+ template<typename SubGrammar>
+ struct extension<tag::try_, SubGrammar>
+ : proto::when<
+ proto::not_<proto::_> // try without a catch is not valid ...
+ , evaluator<SubGrammar>(proto::_child) // ... but here is how to evaluate a
+ > // try that is part of a catch.
{};
////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::catch_all>
- : proto::when<detail::CatchAll, detail::catch_all_evaluator>
+ template<typename SubGrammar>
+ struct extension<tag::catch_all, SubGrammar>
+ : proto::when<
+ detail::CatchAll<SubGrammar>
+ , detail::catch_all_evaluator<SubGrammar>
+ >
{};
////////////////////////////////////////////////////////////////////////////////////////
- template<typename E>
- struct extension<tag::catch_<E> >
- : proto::when<detail::Catch, detail::catch_evaluator<E> >
+ template<typename E, typename SubGrammar>
+ struct extension<tag::catch_<E>, SubGrammar>
+ : proto::when<
+ detail::Catch<SubGrammar>
+ , detail::catch_evaluator<E, SubGrammar>
+ >
{};
}}
Modified: branches/proto/v4/boost/phoenix/statement/while.hpp
==============================================================================
--- branches/proto/v4/boost/phoenix/statement/while.hpp (original)
+++ branches/proto/v4/boost/phoenix/statement/while.hpp 2008-05-26 19:59:49 EDT (Mon, 26 May 2008)
@@ -48,7 +48,8 @@
////////////////////////////////////////////////////////////////////////////////////////
// Proto transform that evaluates if_(condition)[ expression ]
- struct while_evaluator : proto::transform<while_evaluator>
+ template<typename SubGrammar, typename X = proto::callable>
+ struct while_evaluator : proto::transform<while_evaluator<SubGrammar> >
{
template<typename Expr, typename State, typename Data>
struct impl : proto::transform_impl<Expr, State, Data>
@@ -61,9 +62,9 @@
, typename impl::data_param data
) const
{
- while(evaluator()(proto::left(expr), state, data))
+ while(evaluator<SubGrammar>()(proto::left(expr), state, data))
{
- evaluator()(proto::right(expr), state, data);
+ evaluator<SubGrammar>()(proto::right(expr), state, data);
}
}
};
@@ -79,11 +80,11 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
- template<>
- struct extension<tag::while_, void>
+ template<typename SubGrammar>
+ struct extension<tag::while_, SubGrammar>
: proto::when<
- proto::binary_expr<tag::while_, evaluator, evaluator>
- , detail::while_evaluator
+ proto::binary_expr<tag::while_, evaluator<SubGrammar>, evaluator<SubGrammar> >
+ , detail::while_evaluator<SubGrammar>
>
{};
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk