Boost logo

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