$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r62616 - in trunk: boost/proto boost/proto/detail boost/proto/transform libs/proto/doc libs/proto/doc/reference libs/proto/doc/reference/concepts libs/proto/doc/reference/transform libs/proto/test
From: eric_at_[hidden]
Date: 2010-06-08 20:14:43
Author: eric_niebler
Date: 2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
New Revision: 62616
URL: http://svn.boost.org/trac/boost/changeset/62616
Log:
use basic_expr instead of expr when possible for better compile times
Text files modified: 
   trunk/boost/proto/deep_copy.hpp                           |    29 ++++--                                  
   trunk/boost/proto/detail/expr0.hpp                        |   125 +++++++++++++++++++++++++++++           
   trunk/boost/proto/domain.hpp                              |    49 +++++++++++                             
   trunk/boost/proto/expr.hpp                                |    18 ++--                                    
   trunk/boost/proto/extends.hpp                             |    80 ++++++++++--------                      
   trunk/boost/proto/fusion.hpp                              |     6 +                                       
   trunk/boost/proto/generate.hpp                            |   112 +++++++++++++++++---------              
   trunk/boost/proto/literal.hpp                             |     2                                         
   trunk/boost/proto/make_expr.hpp                           |   108 ++++++++++--------------                
   trunk/boost/proto/matches.hpp                             |    26 +++---                                  
   trunk/boost/proto/proto_fwd.hpp                           |    12 ++                                      
   trunk/boost/proto/traits.hpp                              |    96 ++++++++++++---------                   
   trunk/boost/proto/transform/arg.hpp                       |     4                                         
   trunk/boost/proto/transform/call.hpp                      |    12 +-                                      
   trunk/boost/proto/transform/make.hpp                      |    60 ++++++++++++-                           
   trunk/boost/proto/transform/pass_through.hpp              |    18 ++-                                     
   trunk/boost/proto/transform/when.hpp                      |    10 +-                                      
   trunk/libs/proto/doc/glossary.qbk                         |     6                                         
   trunk/libs/proto/doc/proto.qbk                            |     2                                         
   trunk/libs/proto/doc/reference.xml                        |    20 ++++                                    
   trunk/libs/proto/doc/reference/args.xml                   |    23 +++--                                   
   trunk/libs/proto/doc/reference/concepts/Expr.xml          |     6                                         
   trunk/libs/proto/doc/reference/domain.xml                 |    63 ++++++++++++++                          
   trunk/libs/proto/doc/reference/expr.xml                   |   122 ++++++++++++++++++++++++++++            
   trunk/libs/proto/doc/reference/make_expr.xml              |    16 +-                                      
   trunk/libs/proto/doc/reference/matches.xml                |    16 +-                                      
   trunk/libs/proto/doc/reference/traits.xml                 |    12 +-                                      
   trunk/libs/proto/doc/reference/transform/pass_through.xml |     2                                         
   trunk/libs/proto/test/make_expr.cpp                       |   169 ++++++++++++++++++++++++++++++++------- 
   trunk/libs/proto/test/proto_fusion_s.cpp                  |    18 ++++                                    
   30 files changed, 927 insertions(+), 315 deletions(-)
Modified: trunk/boost/proto/deep_copy.hpp
==============================================================================
--- trunk/boost/proto/deep_copy.hpp	(original)
+++ trunk/boost/proto/deep_copy.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -40,14 +40,21 @@
                     >::type
                 actual_terminal_type;
 
-                typedef typename terminal<actual_terminal_type>::type expr_type;
+                typedef
+                    typename base_expr<
+                        typename Expr::proto_domain
+                      , tag::terminal
+                      , term<actual_terminal_type>
+                    >::type
+                expr_;
+
                 typedef typename Expr::proto_generator proto_generator;
-                typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;
+                typedef typename proto_generator::template result<proto_generator(expr_)>::type result_type;
 
                 template<typename Expr2, typename S, typename D>
                 result_type operator()(Expr2 const &e, S const &, D const &) const
                 {
-                    return proto_generator()(expr_type::make(e.proto_base().child0));
+                    return proto_generator()(expr_::make(e.proto_base().child0));
                 }
             };
         }
@@ -161,7 +168,7 @@
         #define BOOST_PROTO_DEFINE_DEEP_COPY_TYPE(Z, N, DATA)                                       \
             typename deep_copy_impl<                                                                \
                 typename remove_reference<                                                          \
-                  typename Expr::BOOST_PP_CAT(proto_child, N)                                       \
+                    typename Expr::BOOST_PP_CAT(proto_child, N)                                     \
                 >::type::proto_derived_expr                                                         \
             >::result_type                                                                          \
             /**/
@@ -189,22 +196,22 @@
             struct deep_copy_impl<Expr, N>
             {
                 typedef
-                    proto::expr<
-                        typename Expr::proto_tag
+                    typename base_expr<
+                        typename Expr::proto_domain
+                      , typename Expr::proto_tag
                       , BOOST_PP_CAT(list, N)<
                             BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_TYPE, ~)
                         >
-                      , N
-                    >
-                expr_type;
+                    >::type
+                expr_;
 
                 typedef typename Expr::proto_generator proto_generator;
-                typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;
+                typedef typename proto_generator::template result<proto_generator(expr_)>::type result_type;
 
                 template<typename Expr2, typename S, typename D>
                 result_type operator()(Expr2 const &e, S const &, D const &) const
                 {
-                    expr_type const that = {
+                    expr_ const that = {
                         BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_FUN, ~)
                     };
 
Modified: trunk/boost/proto/detail/expr0.hpp
==============================================================================
--- trunk/boost/proto/detail/expr0.hpp	(original)
+++ trunk/boost/proto/detail/expr0.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -12,6 +12,127 @@
 
 #define ARG_COUNT BOOST_PP_MAX(1, BOOST_PP_ITERATION())
 
+    /// \brief Simplified representation of a node in an expression tree.
+    ///
+    /// \c proto::basic_expr\<\> is a node in an expression template tree. It
+    /// is a container for its child sub-trees. It also serves as
+    /// the terminal nodes of the tree.
+    ///
+    /// \c Tag is type that represents the operation encoded by
+    ///             this expression. It is typically one of the structs
+    ///             in the \c boost::proto::tag namespace, but it doesn't
+    ///             have to be.
+    ///
+    /// \c Args is a type list representing the type of the children
+    ///             of this expression. It is an instantiation of one
+    ///             of \c proto::list1\<\>, \c proto::list2\<\>, etc. The
+    ///             child types must all themselves be either \c expr\<\>
+    ///             or <tt>proto::expr\<\>&</tt>. If \c Args is an
+    ///             instantiation of \c proto::term\<\> then this
+    ///             \c expr\<\> type represents a terminal expression;
+    ///             the parameter to the \c proto::term\<\> template
+    ///             represents the terminal's value type.
+    ///
+    /// \c Arity is an integral constant representing the number of child
+    ///             nodes this node contains. If \c Arity is 0, then this
+    ///             node is a terminal.
+    ///
+    /// \c proto::basic_expr\<\> is a valid Fusion random-access sequence, where
+    /// the elements of the sequence are the child expressions.
+    #ifdef BOOST_PROTO_DEFINE_TERMINAL
+    template<typename Tag, typename Arg0>
+    struct basic_expr<Tag, term<Arg0>, 0>
+    #else
+    template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(ARG_COUNT, typename Arg)>
+    struct basic_expr<Tag, BOOST_PP_CAT(list, BOOST_PP_ITERATION())<BOOST_PP_ENUM_PARAMS(ARG_COUNT, Arg)>, BOOST_PP_ITERATION() >
+    #endif
+    {
+        typedef Tag proto_tag;
+        BOOST_STATIC_CONSTANT(long, proto_arity_c = BOOST_PP_ITERATION());
+        typedef mpl::long_<BOOST_PP_ITERATION() > proto_arity;
+        typedef basic_expr proto_base_expr;
+        #ifdef BOOST_PROTO_DEFINE_TERMINAL
+        typedef term<Arg0> proto_args;
+        #else
+        typedef BOOST_PP_CAT(list, BOOST_PP_ITERATION())<BOOST_PP_ENUM_PARAMS(ARG_COUNT, Arg)> proto_args;
+        #endif
+        typedef basic_expr proto_grammar;
+        typedef default_domain proto_domain;
+        typedef default_generator proto_generator;
+        typedef proto::tag::proto_expr fusion_tag;
+        typedef basic_expr proto_derived_expr;
+        typedef void proto_is_expr_; /**< INTERNAL ONLY */
+
+        BOOST_PP_REPEAT(ARG_COUNT, BOOST_PROTO_CHILD, ~)
+        BOOST_PP_REPEAT_FROM_TO(ARG_COUNT, BOOST_PROTO_MAX_ARITY, BOOST_PROTO_VOID, ~)
+
+        /// \return *this
+        ///
+        basic_expr const &proto_base() const
+        {
+            return *this;
+        }
+
+        /// \overload
+        ///
+        basic_expr &proto_base()
+        {
+            return *this;
+        }
+
+    #ifdef BOOST_PROTO_DEFINE_TERMINAL
+        /// \return A new \c expr\<\> object initialized with the specified
+        /// arguments.
+        ///
+        template<typename A0>
+        static basic_expr const make(A0 &a0)
+        {
+            return detail::make_terminal(a0, static_cast<basic_expr *>(0), static_cast<proto_args *>(0));
+        }
+
+        /// \overload
+        ///
+        template<typename A0>
+        static basic_expr const make(A0 const &a0)
+        {
+            return detail::make_terminal(a0, static_cast<basic_expr *>(0), static_cast<proto_args *>(0));
+        }
+    #else
+        /// \return A new \c expr\<\> object initialized with the specified
+        /// arguments.
+        ///
+        template<BOOST_PP_ENUM_PARAMS(ARG_COUNT, typename A)>
+        static basic_expr const make(BOOST_PP_ENUM_BINARY_PARAMS(ARG_COUNT, A, const &a))
+        {
+            basic_expr that = {BOOST_PP_ENUM_PARAMS(ARG_COUNT, a)};
+            return that;
+        }
+    #endif
+
+    #if 1 == BOOST_PP_ITERATION()
+        /// If \c Tag is \c boost::proto::tag::address_of and \c proto_child0 is
+        /// <tt>T&</tt>, then \c address_of_hack_type_ is <tt>T*</tt>.
+        /// Otherwise, it is some undefined type.
+        typedef typename detail::address_of_hack<Tag, proto_child0>::type address_of_hack_type_;
+
+        /// \return The address of <tt>this->child0</tt> if \c Tag is
+        /// \c boost::proto::tag::address_of. Otherwise, this function will
+        /// fail to compile.
+        ///
+        /// \attention Proto overloads <tt>operator&</tt>, which means that
+        /// proto-ified objects cannot have their addresses taken, unless we use
+        /// the following hack to make \c &x implicitly convertible to \c X*.
+        operator address_of_hack_type_() const
+        {
+            return boost::addressof(this->child0);
+        }
+    #else
+        /// INTERNAL ONLY
+        ///
+        typedef detail::not_a_valid_type address_of_hack_type_;
+    #endif
+    };
+
     /// \brief Representation of a node in an expression tree.
     ///
     /// \c proto::expr\<\> is a node in an expression template tree. It
@@ -87,7 +208,7 @@
         template<typename A0>
         static expr const make(A0 &a0)
         {
-            return detail::make_terminal(a0, static_cast<expr *>(0));
+            return detail::make_terminal(a0, static_cast<expr *>(0), static_cast<proto_args *>(0));
         }
 
         /// \overload
@@ -95,7 +216,7 @@
         template<typename A0>
         static expr const make(A0 const &a0)
         {
-            return detail::make_terminal(a0, static_cast<expr *>(0));
+            return detail::make_terminal(a0, static_cast<expr *>(0), static_cast<proto_args *>(0));
         }
     #else
         /// \return A new \c expr\<\> object initialized with the specified
Modified: trunk/boost/proto/domain.hpp
==============================================================================
--- trunk/boost/proto/domain.hpp	(original)
+++ trunk/boost/proto/domain.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -11,9 +11,8 @@
 #ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
 #define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
 
-#include <boost/config.hpp>
 #include <boost/ref.hpp>
-#include <boost/proto/generate.hpp>
+#include <boost/proto/proto_fwd.hpp>
 #include <boost/proto/detail/deduce_domain.hpp>
 
 namespace boost { namespace proto
@@ -173,6 +172,52 @@
     {
         typedef typename domain_of<T>::type type;
     };
+
+    /// \brief Tests a domain to see whether its generator would prefer
+    /// to be passed instances of \c proto::basic_expr\<\> rather than
+    /// \c proto::expr\<\>.
+    ///
+    template<typename Domain, typename Void>
+    struct wants_basic_expr
+      : mpl::false_
+    {};
+
+    template<typename Domain>
+    struct wants_basic_expr<Domain, typename Domain::proto_use_basic_expr_>
+      : mpl::true_
+    {};
+
+    /// \brief Given a domain, a tag type and an argument list,
+    /// compute the type of the expression to generate. This is
+    /// either an instance of \c proto::expr\<\> or
+    /// \c proto::basic_expr\<\>.
+    ///
+    template<typename Domain, typename Tag, typename Args, typename Void>
+    struct base_expr
+    {
+        typedef proto::expr<Tag, Args, Args::arity> type;
+    };
+
+    /// INTERNAL ONLY
+    ///
+    template<typename Domain, typename Tag, typename Args>
+    struct base_expr<Domain, Tag, Args, typename Domain::proto_use_basic_expr_>
+    {
+        typedef proto::basic_expr<Tag, Args, Args::arity> type;
+    };
+
+    /// \brief Annotate a domain to indicate that its generator would
+    /// prefer to be passed instances of \c proto::basic_expr\<\> rather
+    /// than \c proto::expr\<\>. <tt>use_basic_expr\<Domain\></tt> is
+    /// itself a domain.
+    ///
+    template<typename Domain>
+    struct use_basic_expr
+      : Domain
+    {
+        BOOST_PROTO_USE_BASIC_EXPR()
+    };
+
 }}
 
 #endif
Modified: trunk/boost/proto/expr.hpp
==============================================================================
--- trunk/boost/proto/expr.hpp	(original)
+++ trunk/boost/proto/expr.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -69,17 +69,17 @@
             typedef Expr *type;
         };
 
-        template<typename T, typename Tag, typename Arg0>
-        proto::expr<Tag, proto::term<Arg0>, 0> make_terminal(T &t, proto::expr<Tag, proto::term<Arg0>, 0> *)
+        template<typename T, typename Expr, typename Arg0>
+        Expr make_terminal(T &t, Expr *, proto::term<Arg0> *)
         {
-            proto::expr<Tag, proto::term<Arg0>, 0> that = {t};
+            Expr that = {t};
             return that;
         }
 
-        template<typename T, typename Tag, typename Arg0, std::size_t N>
-        proto::expr<Tag, proto::term<Arg0[N]>, 0> make_terminal(T (&t)[N], proto::expr<Tag, proto::term<Arg0[N]>, 0> *)
+        template<typename T, typename Expr, typename Arg0, std::size_t N>
+        Expr make_terminal(T (&t)[N], Expr *, proto::term<Arg0[N]> *)
         {
-            expr<Tag, proto::term<Arg0[N]>, 0> that;
+            Expr that;
             for(std::size_t i = 0; i < N; ++i)
             {
                 that.child0[i] = t[i];
@@ -87,10 +87,10 @@
             return that;
         }
 
-        template<typename T, typename Tag, typename Arg0, std::size_t N>
-        proto::expr<Tag, proto::term<Arg0[N]>, 0> make_terminal(T const(&t)[N], proto::expr<Tag, proto::term<Arg0[N]>, 0> *)
+        template<typename T, typename Expr, typename Arg0, std::size_t N>
+        Expr make_terminal(T const(&t)[N], Expr *, proto::term<Arg0[N]> *)
         {
-            expr<Tag, proto::term<Arg0[N]>, 0> that;
+            Expr that;
             for(std::size_t i = 0; i < N; ++i)
             {
                 that.child0[i] = t[i];
Modified: trunk/boost/proto/extends.hpp
==============================================================================
--- trunk/boost/proto/extends.hpp	(original)
+++ trunk/boost/proto/extends.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -204,31 +204,33 @@
         BOOST_PROTO_DISABLE_MSVC_C4522                                                              \
         Typename() boost::tr1_result_of<                                                            \
             Typename() This::proto_generator(                                                       \
-                boost::proto::expr<                                                                 \
-                    boost::proto::tag::assign                                                       \
+                Typename() boost::proto::base_expr<                                         \
+                    Typename() This::proto_domain                                                   \
+                  , boost::proto::tag::assign                                                       \
                   , boost::proto::list2<                                                            \
                         This &                                                                      \
                       , This Const() &                                                              \
                     >                                                                               \
-                  , 2                                                                               \
-                >                                                                                   \
+                >::type                                                                             \
             )                                                                                       \
         >::type const                                                                               \
         operator =(This Const() &a)                                                                 \
         {                                                                                           \
-            typedef boost::proto::expr<                                                             \
-                boost::proto::tag::assign                                                           \
-              , boost::proto::list2<                                                                \
-                    This &                                                                          \
-                  , This Const() &                                                                  \
-                >                                                                                   \
-              , 2                                                                                   \
-            > that_type;                                                                            \
+            typedef                                                                                 \
+                Typename() boost::proto::base_expr<                                         \
+                    Typename() This::proto_domain                                                   \
+                  , boost::proto::tag::assign                                                       \
+                  , boost::proto::list2<                                                            \
+                        This &                                                                      \
+                      , This Const() &                                                              \
+                    >                                                                               \
+                >::type                                                                             \
+            that_type;                                                                              \
             that_type const that = {                                                                \
                 *this                                                                               \
               , a                                                                                   \
             };                                                                                      \
-            return Typename() This::proto_generator()(that);                                           \
+            return Typename() This::proto_generator()(that);                                        \
         }                                                                                           \
         /**/
 
@@ -251,26 +253,28 @@
         template<typename A>                                                                        \
         typename boost::tr1_result_of<                                                              \
             proto_generator(                                                                        \
-                boost::proto::expr<                                                                 \
-                    boost::proto::tag::assign                                                       \
+                typename boost::proto::base_expr<                                           \
+                    proto_domain                                                                    \
+                  , boost::proto::tag::assign                                                       \
                   , boost::proto::list2<                                                            \
                         proto_derived_expr ThisConst() &                                            \
                       , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
                     >                                                                               \
-                  , 2                                                                               \
-                >                                                                                   \
+                >::type                                                                             \
             )                                                                                       \
         >::type const                                                                               \
         operator =(A ThatConst() &a) ThisConst()                                                    \
         {                                                                                           \
-            typedef boost::proto::expr<                                                             \
-                boost::proto::tag::assign                                                           \
-              , boost::proto::list2<                                                                \
-                    proto_derived_expr ThisConst() &                                                \
-                  , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type   \
-                >                                                                                   \
-              , 2                                                                                   \
-            > that_type;                                                                            \
+            typedef                                                                                 \
+                typename boost::proto::base_expr<                                           \
+                    proto_domain                                                                    \
+                  , boost::proto::tag::assign                                                       \
+                  , boost::proto::list2<                                                            \
+                        proto_derived_expr ThisConst() &                                            \
+                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
+                    >                                                                               \
+                >::type                                                                             \
+            that_type;                                                                            \
             that_type const that = {                                                                \
                 *static_cast<proto_derived_expr ThisConst() *>(this)                                \
               , boost::proto::as_child<proto_domain>(a)                                             \
@@ -315,26 +319,28 @@
         template<typename A>                                                                        \
         typename boost::tr1_result_of<                                                              \
             proto_generator(                                                                        \
-                boost::proto::expr<                                                                 \
-                    boost::proto::tag::subscript                                                    \
+                typename boost::proto::base_expr<                                           \
+                    proto_domain                                                                    \
+                  , boost::proto::tag::subscript                                                    \
                   , boost::proto::list2<                                                            \
                         proto_derived_expr ThisConst() &                                            \
                       , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
                     >                                                                               \
-                  , 2                                                                               \
-                >                                                                                   \
+                >::type                                                                             \
             )                                                                                       \
         >::type const                                                                               \
         operator [](A ThatConst() &a) ThisConst()                                                   \
         {                                                                                           \
-            typedef boost::proto::expr<                                                             \
-                boost::proto::tag::subscript                                                        \
-              , boost::proto::list2<                                                                \
-                    proto_derived_expr ThisConst() &                                                \
-                  , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type   \
-                >                                                                                   \
-              , 2                                                                                   \
-            > that_type;                                                                            \
+            typedef                                                                                 \
+                typename boost::proto::base_expr<                                           \
+                    proto_domain                                                                    \
+                  , boost::proto::tag::subscript                                                    \
+                  , boost::proto::list2<                                                            \
+                        proto_derived_expr ThisConst() &                                            \
+                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
+                    >                                                                               \
+                >::type                                                                             \
+            that_type;                                                                              \
             that_type const that = {                                                                \
                 *static_cast<proto_derived_expr ThisConst() *>(this)                                \
               , boost::proto::as_child<proto_domain>(a)                                             \
Modified: trunk/boost/proto/fusion.hpp
==============================================================================
--- trunk/boost/proto/fusion.hpp	(original)
+++ trunk/boost/proto/fusion.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -728,6 +728,12 @@
     {
         typedef fusion::fusion_sequence_tag type;
     };
+
+    template<typename Tag, typename Args, long Arity>
+    struct sequence_tag< proto::basic_expr<Tag, Args, Arity> >
+    {
+        typedef fusion::fusion_sequence_tag type;
+    };
 }} 
 
 #if BOOST_MSVC
Modified: trunk/boost/proto/generate.hpp
==============================================================================
--- trunk/boost/proto/generate.hpp	(original)
+++ trunk/boost/proto/generate.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -12,11 +12,14 @@
     #define BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007
 
     #include <boost/config.hpp>
-    #include <boost/utility/result_of.hpp>
     #include <boost/preprocessor/cat.hpp>
     #include <boost/preprocessor/iteration/iterate.hpp>
-    #include <boost/preprocessor/repetition/enum.hpp>
+    #include <boost/preprocessor/facilities/intercept.hpp>
+    #include <boost/preprocessor/repetition/enum_params.hpp>
+    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
+    #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
     #include <boost/utility/enable_if.hpp>
+    #include <boost/utility/result_of.hpp>
     #include <boost/proto/proto_fwd.hpp>
     #include <boost/proto/args.hpp>
 
@@ -26,39 +29,38 @@
         namespace detail
         {
             template<typename Expr>
-            struct expr_params;
+            struct by_value_generator_;
 
-            template<typename Tag, typename Args, long N>
-            struct expr_params<proto::expr<Tag, Args, N> >
+            template<typename Tag, typename Arg>
+            struct by_value_generator_<proto::expr<Tag, term<Arg>, 0> >
             {
-                typedef Tag tag;
-                typedef Args args;
-                BOOST_STATIC_CONSTANT(long, arity = N);
-            };
-
-            template<typename Expr, long Arity = expr_params<Expr>::arity>
-            struct by_value_generator_;
+                typedef
+                    proto::expr<
+                        Tag
+                      , term<typename detail::term_traits<Arg>::value_type>
+                      , 0
+                    >
+                type;
 
-        #define BOOST_PROTO_DEFINE_BY_VALUE_TYPE(Z, N, Expr)                                        \
-            typename uncvref<typename expr_params<Expr>::args::BOOST_PP_CAT(child, N)>::type        \
-            /**/
-
-        #define BOOST_PROTO_DEFINE_BY_VALUE(Z, N, expr)                                             \
-            expr.BOOST_PP_CAT(child, N)                                                             \
-            /**/
+                static type const call(proto::expr<Tag, term<Arg>, 0> const &e)
+                {
+                    type that = {e.child0};
+                    return that;
+                }
+            };
 
-            template<typename Expr>
-            struct by_value_generator_<Expr, 0>
+            template<typename Tag, typename Arg>
+            struct by_value_generator_<proto::basic_expr<Tag, term<Arg>, 0> >
             {
                 typedef
-                    proto::expr<
-                        typename expr_params<Expr>::tag
-                      , term<typename detail::term_traits<typename expr_params<Expr>::args::child0>::value_type>
+                    proto::basic_expr<
+                        Tag
+                      , term<typename detail::term_traits<Arg>::value_type>
                       , 0
                     >
                 type;
 
-                static type const make(Expr const &e)
+                static type const call(proto::basic_expr<Tag, term<Arg>, 0> const &e)
                 {
                     type that = {e.child0};
                     return that;
@@ -120,6 +122,7 @@
         struct generator
         {
             BOOST_PROTO_CALLABLE()
+            BOOST_PROTO_USE_BASIC_EXPR()
 
             template<typename Sig>
             struct result;
@@ -165,6 +168,7 @@
         struct pod_generator
         {
             BOOST_PROTO_CALLABLE()
+            BOOST_PROTO_USE_BASIC_EXPR()
 
             template<typename Sig>
             struct result;
@@ -245,7 +249,7 @@
             template<typename Expr>
             typename result<by_value_generator(Expr)>::type operator ()(Expr const &e) const
             {
-                return detail::by_value_generator_<Expr>::make(e);
+                return detail::by_value_generator_<Expr>::call(e);
             }
         };
 
@@ -360,25 +364,55 @@
 
     #define N BOOST_PP_ITERATION()
 
-            template<typename Expr>
-            struct by_value_generator_<Expr, N>
+            template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, typename Arg) >
+            struct by_value_generator_<
+                proto::expr<Tag, BOOST_PP_CAT(list, N)<BOOST_PP_ENUM_PARAMS(N, Arg)>, N>
+            >
             {
                 typedef
-                    proto::expr<
-                        typename expr_params<Expr>::tag
-                      , BOOST_PP_CAT(list, N)<
-                            // typename uncvref<typename expr_params<Expr>::args::child0>::type, ...
-                            BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_BY_VALUE_TYPE, Expr)
-                        >
-                      , N
+                    BOOST_PP_CAT(list, N)<BOOST_PP_ENUM_PARAMS(N, Arg)>
+                src_args;
+
+                typedef
+                    BOOST_PP_CAT(list, N)<
+                        BOOST_PP_ENUM_BINARY_PARAMS(N, typename uncvref<Arg, >::type BOOST_PP_INTERCEPT)
                     >
-                type;
+                dst_args;
+
+                typedef proto::expr<Tag, src_args, N> src_type;
+                typedef proto::expr<Tag, dst_args, N> type;
+
+                static type const call(src_type const &e)
+                {
+                    type that = {
+                        BOOST_PP_ENUM_PARAMS(N, e.child)
+                    };
+                    return that;
+                }
+            };
+
+            template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, typename Arg) >
+            struct by_value_generator_<
+                proto::basic_expr<Tag, BOOST_PP_CAT(list, N)<BOOST_PP_ENUM_PARAMS(N, Arg)>, N>
+            >
+            {
+                typedef
+                    BOOST_PP_CAT(list, N)<BOOST_PP_ENUM_PARAMS(N, Arg)>
+                src_args;
+
+                typedef
+                    BOOST_PP_CAT(list, N)<
+                        BOOST_PP_ENUM_BINARY_PARAMS(N, typename uncvref<Arg, >::type BOOST_PP_INTERCEPT)
+                    >
+                dst_args;
+
+                typedef proto::basic_expr<Tag, src_args, N> src_type;
+                typedef proto::basic_expr<Tag, dst_args, N> type;
 
-                static type const make(Expr const &e)
+                static type const call(src_type const &e)
                 {
                     type that = {
-                        // expr.child0, ...
-                        BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_BY_VALUE, e)
+                        BOOST_PP_ENUM_PARAMS(N, e.child)
                     };
                     return that;
                 }
Modified: trunk/boost/proto/literal.hpp
==============================================================================
--- trunk/boost/proto/literal.hpp	(original)
+++ trunk/boost/proto/literal.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -25,7 +25,7 @@
         ///
         /// A simple wrapper for a terminal, provided for
         /// ease of use. In all cases, <tt>literal\<X\> l(x);</tt>
-        /// is equivalent to <tt>terminal\<X\>::::type l = {x};</tt>.
+        /// is equivalent to <tt>terminal\<X\>::type l = {x};</tt>.
         ///
         /// The \c Domain template parameter defaults to
         /// \c proto::default_domain.
Modified: trunk/boost/proto/make_expr.hpp
==============================================================================
--- trunk/boost/proto/make_expr.hpp	(original)
+++ trunk/boost/proto/make_expr.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -155,41 +155,23 @@
         {
             template<typename T, typename Domain>
             struct protoify_
-            {
-                typedef
-                    typename boost::unwrap_reference<T>::type
-                unref_type;
-
-                typedef
-                    typename mpl::eval_if_c<
-                        boost::is_reference_wrapper<T>::value
-                      , proto::result_of::as_child<unref_type, Domain>
-                      , proto::result_of::as_expr<unref_type, Domain>
-                    >::type
-                type;
-
-                static type call(T &t)
-                {
-                    return typename mpl::if_c<
-                        is_reference_wrapper<T>::value
-                      , functional::as_child<Domain>
-                      , functional::as_expr<Domain>
-                    >::type()(static_cast<unref_type &>(t));
-                }
-            };
+              : result_of::as_expr<T, Domain>
+            {};
 
             template<typename T, typename Domain>
             struct protoify_<T &, Domain>
-            {
-                typedef
-                    typename proto::result_of::as_child<T, Domain>::type
-                type;
+              : result_of::as_child<T, Domain>
+            {};
 
-                static type call(T &t)
-                {
-                    return functional::as_child<Domain>()(t);
-                }
-            };
+            template<typename T, typename Domain>
+            struct protoify_<boost::reference_wrapper<T>, Domain>
+              : result_of::as_child<T, Domain>
+            {};
+
+            template<typename T, typename Domain>
+            struct protoify_<boost::reference_wrapper<T> const, Domain>
+              : result_of::as_child<T, Domain>
+            {};
 
             template<typename Tag, typename Domain, typename Sequence, std::size_t Size>
             struct unpack_expr_
@@ -273,7 +255,7 @@
             ///
             /// In this specialization, the domain is deduced from the
             /// domains of the child types. (If
-            /// <tt>is_domain\<A0\>::::value</tt> is \c true, then another
+            /// <tt>is_domain\<A0\>::value</tt> is \c true, then another
             /// specialization is selected.)
             template<
                 typename Tag
@@ -283,12 +265,12 @@
             >
             struct make_expr
             {
-                /// Same as <tt>result_of::make_expr\<Tag, D, A0, ... AN\>::::type</tt>
+                /// Same as <tt>result_of::make_expr\<Tag, D, A0, ... AN\>::type</tt>
                 /// where \c D is the deduced domain, which is calculated as follows:
                 ///
                 /// For each \c x in <tt>[0,N)</tt> (proceeding in order beginning with
-                /// <tt>x=0</tt>), if <tt>domain_of\<Ax\>::::type</tt> is not
-                /// \c default_domain, then \c D is <tt>domain_of\<Ax\>::::type</tt>.
+                /// <tt>x=0</tt>), if <tt>domain_of\<Ax\>::type</tt> is not
+                /// \c default_domain, then \c D is <tt>domain_of\<Ax\>::type</tt>.
                 /// Otherwise, \c D is \c default_domain.
                 typedef
                     typename detail::make_expr_<
@@ -318,26 +300,26 @@
             {
                 /// If \c Tag is <tt>tag::terminal</tt>, then \c type is a
                 /// typedef for <tt>boost::result_of\<Domain(expr\<tag::terminal,
-                /// term\<A0\> \>)\>::::type</tt>.
+                /// term\<A0\> \>)\>::type</tt>.
                 ///
                 /// Otherwise, \c type is a typedef for <tt>boost::result_of\<Domain(expr\<Tag,
-                /// listN\< as_child\<A0\>::::type, ... as_child\<AN\>::::type\>)
-                /// \>::::type</tt>, where \c N is the number of non-void template
-                /// arguments, and <tt>as_child\<A\>::::type</tt> is evaluated as
+                /// listN\< as_child\<A0\>::type, ... as_child\<AN\>::type\>)
+                /// \>::type</tt>, where \c N is the number of non-void template
+                /// arguments, and <tt>as_child\<A\>::type</tt> is evaluated as
                 /// follows:
                 ///
-                /// \li If <tt>is_expr\<A\>::::value</tt> is \c true, then the
+                /// \li If <tt>is_expr\<A\>::value</tt> is \c true, then the
                 /// child type is \c A.
                 /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
-                /// and <tt>is_expr\<B\>::::value</tt> is \c true, then the
+                /// and <tt>is_expr\<B\>::value</tt> is \c true, then the
                 /// child type is <tt>B &</tt>.
-                /// \li If <tt>is_expr\<A\>::::value</tt> is \c false, then the
+                /// \li If <tt>is_expr\<A\>::value</tt> is \c false, then the
                 /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<A\> \>
-                /// )\>::::type</tt>.
+                /// )\>::type</tt>.
                 /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
-                /// and <tt>is_expr\<B\>::::value</tt> is \c false, then the
+                /// and <tt>is_expr\<B\>::value</tt> is \c false, then the
                 /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<B &\> \>
-                /// )\>::::type</tt>.
+                /// )\>::type</tt>.
                 typedef
                     typename detail::make_expr_<
                         Tag
@@ -358,7 +340,7 @@
             ///
             /// In this specialization, the domain is deduced from the
             /// domains of the child types. (If
-            /// <tt>is_domain\<Sequence>::::value</tt> is \c true, then another
+            /// <tt>is_domain\<Sequence>::value</tt> is \c true, then another
             /// specialization is selected.)
             template<
                 typename Tag
@@ -371,8 +353,8 @@
                 /// Let \c S be the type of a Fusion Random Access Sequence
                 /// equivalent to \c Sequence. Then \c type is the
                 /// same as <tt>result_of::make_expr\<Tag,
-                /// fusion::result_of::value_at_c\<S, 0\>::::type, ...
-                /// fusion::result_of::value_at_c\<S, N-1\>::::type\>::::type</tt>,
+                /// fusion::result_of::value_at_c\<S, 0\>::type, ...
+                /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
                 /// where \c N is the size of \c S.
                 typedef
                     typename detail::unpack_expr_<
@@ -395,8 +377,8 @@
                 /// Let \c S be the type of a Fusion Random Access Sequence
                 /// equivalent to \c Sequence. Then \c type is the
                 /// same as <tt>result_of::make_expr\<Tag, Domain,
-                /// fusion::result_of::value_at_c\<S, 0\>::::type, ...
-                /// fusion::result_of::value_at_c\<S, N-1\>::::type\>::::type</tt>,
+                /// fusion::result_of::value_at_c\<S, 0\>::type, ...
+                /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
                 /// where \c N is the size of \c S.
                 typedef
                     typename detail::unpack_expr_<
@@ -595,7 +577,7 @@
         /// <tt>as_expr\<Domain\>(x)</tt>.
         ///
         /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
-        /// <tt>expr\<Tag, listN\<C0,...CN\> \>::::make(c0,...cN)</tt>
+        /// <tt>expr\<Tag, listN\<C0,...CN\> \>::make(c0,...cN)</tt>
         /// where \c Bx is the type of \c bx.
         ///
         /// \return <tt>Domain()(make_\<Tag\>(wrap_(a0),...wrap_(aN)))</tt>.
@@ -655,14 +637,14 @@
         /// Let \c s be a Fusion Random Access Sequence equivalent to \c sequence.
         /// Let <tt>wrap_\<N\>(s)</tt>, where \c s has type \c S, be defined
         /// such that:
-        /// \li If <tt>fusion::result_of::value_at_c\<S,N\>::::type</tt> is a reference,
+        /// \li If <tt>fusion::result_of::value_at_c\<S,N\>::type</tt> is a reference,
         /// <tt>wrap_\<N\>(s)</tt> is equivalent to
         /// <tt>as_child\<Domain\>(fusion::at_c\<N\>(s))</tt>.
         /// \li Otherwise, <tt>wrap_\<N\>(s)</tt> is equivalent to
         /// <tt>as_expr\<Domain\>(fusion::at_c\<N\>(s))</tt>.
         ///
         /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
-        /// <tt>expr\<Tag, listN\<B0,...BN\> \>::::make(b0,...bN)</tt>
+        /// <tt>expr\<Tag, listN\<B0,...BN\> \>::make(b0,...bN)</tt>
         /// where \c Bx is the type of \c bx.
         ///
         /// \param sequence a Fusion Forward Sequence.
@@ -744,12 +726,13 @@
         struct make_expr_<Tag, Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
             BOOST_PP_ENUM_TRAILING_PARAMS(M, void BOOST_PP_INTERCEPT), void>
         {
-            typedef proto::expr<
-                Tag
-              , BOOST_PP_CAT(list, N)<BOOST_PP_ENUM(N, BOOST_PROTO_AS_CHILD_TYPE, (A, ~, Domain)) >
-              , N
-            > expr_type;
+            typedef
+                BOOST_PP_CAT(list, N)<
+                    BOOST_PP_ENUM(N, BOOST_PROTO_AS_CHILD_TYPE, (A, ~, Domain))
+                >
+            proto_args;
 
+            typedef typename base_expr<Domain, Tag, proto_args>::type expr_type;
             typedef typename Domain::proto_generator proto_generator;
             typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;
 
@@ -777,14 +760,13 @@
         {
             BOOST_PROTO_FUSION_ITERATORS_TYPE(N)
 
-            typedef proto::expr<
-                Tag
-              , BOOST_PP_CAT(list, N)<
+            typedef
+                BOOST_PP_CAT(list, N)<
                     BOOST_PP_ENUM(N, BOOST_PROTO_FUSION_AS_CHILD_AT_TYPE, ~)
                 >
-              , N
-            > expr_type;
+            proto_args;
 
+            typedef typename base_expr<Domain, Tag, proto_args>::type expr_type;
             typedef typename Domain::proto_generator proto_generator;
             typedef typename proto_generator::template result<proto_generator(expr_type)>::type type;
 
Modified: trunk/boost/proto/matches.hpp
==============================================================================
--- trunk/boost/proto/matches.hpp	(original)
+++ trunk/boost/proto/matches.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -464,9 +464,9 @@
         /// \li An expression \c E matches <tt>and_\<B0,B1,...Bn\></tt> if \c E
         ///     matches all \c Bx for \c x in <tt>[0,n)</tt>.
         /// \li An expression \c E matches <tt>if_\<T,U,V\></tt> if
-        ///     <tt>boost::result_of\<when\<_,T\>(E,int,int)\>::::type::value</tt>
+        ///     <tt>boost::result_of\<when\<_,T\>(E,int,int)\>::type::value</tt>
         ///     is \c true and \c E matches \c U; or, if
-        ///     <tt>boost::result_of\<when\<_,T\>(E,int,int)\>::::type::value</tt>
+        ///     <tt>boost::result_of\<when\<_,T\>(E,int,int)\>::type::value</tt>
         ///     is \c false and \c E matches \c V. (Note: \c U defaults to \c _
         ///     and \c V defaults to \c not_\<_\>.)
         /// \li An expression \c E matches <tt>not_\<T\></tt> if \c E does
@@ -484,7 +484,7 @@
         /// \li \c A is <tt>B const &</tt>
         /// \li \c B is <tt>exact\<A\></tt>
         /// \li \c B is <tt>convertible_to\<X\></tt> and
-        ///     <tt>is_convertible\<A,X\>::::value</tt> is \c true.
+        ///     <tt>is_convertible\<A,X\>::value</tt> is \c true.
         /// \li \c A is <tt>X[M]</tt> or <tt>X(&)[M]</tt> and
         ///     \c B is <tt>X[proto::N]</tt>.
         /// \li \c A is <tt>X(&)[M]</tt> and \c B is <tt>X(&)[proto::N]</tt>.
@@ -522,7 +522,7 @@
         /// and a transform that returns the current expression unchanged.
         ///
         /// The wildcard type, \c _, is a grammar element such that
-        /// <tt>matches\<E,_\>::::value</tt> is \c true for any expression
+        /// <tt>matches\<E,_\>::value</tt> is \c true for any expression
         /// type \c E.
         ///
         /// The wildcard can also be used as a stand-in for a template
@@ -617,7 +617,7 @@
                 typedef Expr result_type;
 
                 /// \param e An expression
-                /// \pre <tt>matches\<Expr,not_\>::::value</tt> is \c true.
+                /// \pre <tt>matches\<Expr,not_\>::value</tt> is \c true.
                 /// \return \c e
                 #ifdef BOOST_PROTO_STRICT_RESULT_OF
                 result_type
@@ -642,15 +642,15 @@
         /// When <tt>if_\<If,Then,Else\></tt> is used as a grammar, \c If
         /// must be a Proto transform and \c Then and \c Else must be grammars.
         /// An expression type \c E matches <tt>if_\<If,Then,Else\></tt> if
-        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::::type::value</tt>
+        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::type::value</tt>
         /// is \c true and \c E matches \c U; or, if
-        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::::type::value</tt>
+        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::type::value</tt>
         /// is \c false and \c E matches \c V.
         ///
         /// The template parameter \c Then defaults to \c _
         /// and \c Else defaults to \c not\<_\>, so an expression type \c E
         /// will match <tt>if_\<If\></tt> if and only if
-        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::::type::value</tt>
+        /// <tt>boost::result_of\<when\<_,If\>(E,int,int)\>::type::value</tt>
         /// is \c true.
         ///
         /// \code
@@ -667,7 +667,7 @@
         /// When <tt>if_\<If,Then,Else\></tt> is used as a transform, \c If,
         /// \c Then and \c Else must be Proto transforms. When applying
         /// the transform to an expression \c E, state \c S and data \c V,
-        /// if <tt>boost::result_of\<when\<_,If\>(E,S,V)\>::::type::value</tt>
+        /// if <tt>boost::result_of\<when\<_,If\>(E,S,V)\>::type::value</tt>
         /// is \c true then the \c Then transform is applied; otherwise
         /// the \c Else transform is applied.
         ///
@@ -737,7 +737,7 @@
         /// When applying <tt>or_\<B0,B1,...Bn\></tt> as a transform with an
         /// expression \c e of type \c E, state \c s and data \c d, it is
         /// equivalent to <tt>Bx()(e, s, d)</tt>, where \c x is the lowest
-        /// number such that <tt>matches\<E,Bx\>::::value</tt> is \c true.
+        /// number such that <tt>matches\<E,Bx\>::value</tt> is \c true.
         template<BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, typename G)>
         struct or_ : transform<or_<BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_LOGICAL_ARITY, G)> >
         {
@@ -746,7 +746,7 @@
             /// \param e An expression
             /// \param s The current state
             /// \param d A data of arbitrary type
-            /// \pre <tt>matches\<Expr,or_\>::::value</tt> is \c true.
+            /// \pre <tt>matches\<Expr,or_\>::value</tt> is \c true.
             /// \return <tt>which()(e, s, d)</tt>, where <tt>which</tt> is the
             /// sub-grammar that matched <tt>Expr</tt>.
 
@@ -808,7 +808,7 @@
             /// \param e An expression
             /// \param s The current state
             /// \param d A data of arbitrary type
-            /// \pre <tt>matches\<Expr,switch_\>::::value</tt> is \c true.
+            /// \pre <tt>matches\<Expr,switch_\>::value</tt> is \c true.
             /// \return <tt>which()(e, s, d)</tt>, where <tt>which</tt> is
             /// <tt>Cases::case_<typename Expr::proto_tag></tt>
 
@@ -827,7 +827,7 @@
         ///
         /// By default, matching terminals ignores references and
         /// cv-qualifiers. For instance, a terminal expression of
-        /// type <tt>terminal\<int const &\>::::type</tt> will match
+        /// type <tt>terminal\<int const &\>::type</tt> will match
         /// the grammar <tt>terminal\<int\></tt>. If that is not
         /// desired, you can force an exact match with
         /// <tt>terminal\<exact\<int\> \></tt>. This will only
Modified: trunk/boost/proto/proto_fwd.hpp
==============================================================================
--- trunk/boost/proto/proto_fwd.hpp	(original)
+++ trunk/boost/proto/proto_fwd.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -272,10 +272,19 @@
 
     struct deduce_domain;
 
+    template<typename Domain, typename Void = void>
+    struct wants_basic_expr;
+
+    template<typename Domain, typename Tag, typename Args, typename Void = void>
+    struct base_expr;
+
+    template<typename Domain>
+    struct use_basic_expr;
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     namespace exprns_
     {
-        template<typename Tag, typename Args, long Arity>
+        template<typename Tag, typename Args, long Arity = Args::arity>
         struct basic_expr;
 
         template<typename Tag, typename Args, long Arity = Args::arity>
@@ -646,6 +655,7 @@
     #define BOOST_PROTO_UNEXPR() typedef int proto_is_expr_;
     #define BOOST_PROTO_CALLABLE() typedef void proto_is_callable_;
     #define BOOST_PROTO_AGGREGATE() typedef void proto_is_aggregate_;
+    #define BOOST_PROTO_USE_BASIC_EXPR() typedef void proto_use_basic_expr_;
 
     struct callable
     {
Modified: trunk/boost/proto/traits.hpp
==============================================================================
--- trunk/boost/proto/traits.hpp	(original)
+++ trunk/boost/proto/traits.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -41,6 +41,7 @@
     #include <boost/proto/proto_fwd.hpp>
     #include <boost/proto/args.hpp>
     #include <boost/proto/tags.hpp>
+    #include <boost/proto/generate.hpp>
     #include <boost/proto/transform/pass_through.hpp>
 
     #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
@@ -84,19 +85,19 @@
         /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a
         /// callable transform or an object transform. (The former are evaluated
         /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If
-        /// <tt>is_callable\<R\>::::value</tt> is \c true, the function type is
+        /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is
         /// a callable transform; otherwise, it is an object transform.
         ///
-        /// Unless specialized for a type \c T, <tt>is_callable\<T\>::::value</tt>
+        /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt>
         /// is computed as follows:
         ///
         /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx
-        /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::::value</tt>
-        /// is <tt>is_same\<YN, proto::callable\>::::value</tt>.
+        /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt>
+        /// is <tt>is_same\<YN, proto::callable\>::value</tt>.
         /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef
-        /// for \c void, <tt>is_callable\<T\>::::value</tt> is \c true. (Note: this is
+        /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is
         /// the case for any type that derives from \c proto::callable.)
-        /// \li Otherwise, <tt>is_callable\<T\>::::value</tt> is \c false.
+        /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false.
         template<typename T>
         struct is_callable
           : proto::detail::is_callable_<T>
@@ -122,6 +123,12 @@
         struct is_callable<proto::expr<Tag, Args, N> >
           : mpl::false_
         {};
+
+        // work around GCC bug
+        template<typename Tag, typename Args, long N>
+        struct is_callable<proto::basic_expr<Tag, Args, N> >
+          : mpl::false_
+        {};
         #endif
 
         /// \brief A Boolean metafunction that indicates whether a type requires
@@ -130,7 +137,7 @@
         /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform
         /// to determine how to construct an object of some type \c T, given some
         /// initialization arguments <tt>a0,a1,...aN</tt>.
-        /// If <tt>is_aggregate\<T\>::::value</tt> is \c true, then an object of
+        /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of
         /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise,
         /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>.
         template<typename T, typename Void>
@@ -145,6 +152,11 @@
           : mpl::true_
         {};
 
+        template<typename Tag, typename Args, long N>
+        struct is_aggregate<proto::basic_expr<Tag, Args, N>, void>
+          : mpl::true_
+        {};
+
         /// INTERNAL ONLY
         template<typename T>
         struct is_aggregate<T, typename T::proto_is_aggregate_>
@@ -166,11 +178,11 @@
         /// type \c T is a Proto expression type.
         ///
         /// If \c T has a nested type \c proto_is_expr_ that is a typedef
-        /// for \c void, <tt>is_expr\<T\>::::value</tt> is \c true. (Note, this
+        /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
         /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
         /// from <tt>proto::extends\<\></tt> or that uses the
         /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
-        /// <tt>is_expr\<T\>::::value</tt> is \c false.
+        /// <tt>is_expr\<T\>::value</tt> is \c false.
         template<typename T, typename Void /* = void*/>
         struct is_expr
           : mpl::false_
@@ -180,11 +192,11 @@
         /// type \c T is a Proto expression type.
         ///
         /// If \c T has a nested type \c proto_is_expr_ that is a typedef
-        /// for \c void, <tt>is_expr\<T\>::::value</tt> is \c true. (Note, this
+        /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
         /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
         /// from <tt>proto::extends\<\></tt> or that uses the
         /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
-        /// <tt>is_expr\<T\>::::value</tt> is \c false.
+        /// <tt>is_expr\<T\>::value</tt> is \c false.
         template<typename T>
         struct is_expr<T, typename T::proto_is_expr_>
           : mpl::true_
@@ -235,8 +247,8 @@
             ///
             /// If \c T is a function type, let \c A be <tt>T &</tt>.
             /// Otherwise, let \c A be the type \c T stripped of cv-qualifiers.
-            /// Then, the result type <tt>as_expr\<T, Domain\>::::type</tt> is
-            /// <tt>boost::result_of\<Domain(expr\< tag::terminal, term\<A\> \>)\>::::type</tt>.
+            /// Then, the result type <tt>as_expr\<T, Domain\>::type</tt> is
+            /// <tt>boost::result_of\<Domain(expr\< tag::terminal, term\<A\> \>)\>::type</tt>.
             template<
                 typename T
               , typename Domain // = default_domain
@@ -254,7 +266,7 @@
                       , remove_cv<T>
                     >::type
                 arg0_;
-                typedef proto::expr<proto::tag::terminal, term<arg0_>, 0> expr_;
+                typedef typename base_expr<Domain, proto::tag::terminal, term<arg0_> >::type expr_;
                 typedef typename Domain::proto_generator proto_generator;
                 typedef typename proto_generator::template result<Domain(expr_)>::type type;
                 typedef type const reference;
@@ -264,7 +276,7 @@
                 template<typename T2>
                 static reference call(T2 &t)
                 {
-                    return proto_generator()(expr_::make(t));
+                    return proto_generator()(expr_::make(static_cast<T &>(t)));
                 }
             };
 
@@ -276,7 +288,7 @@
             /// possible. Types which are already Proto types are left alone.
             ///
             /// This specialization is selected when the type is already a Proto type.
-            /// The result type <tt>as_expr\<T, Domain\>::::type</tt> is \c T stripped
+            /// The result type <tt>as_expr\<T, Domain\>::type</tt> is \c T stripped
             /// of cv-qualifiers.
             template<typename T, typename Domain>
             struct as_expr<
@@ -298,7 +310,7 @@
                 template<typename T2>
                 static reference call(T2 &t)
                 {
-                    return proto_generator()(t);
+                    return proto_generator()(static_cast<T &>(t));
                 }
             };
 
@@ -318,7 +330,7 @@
                 /// INTERNAL ONLY
                 ///
                 template<typename T2>
-                static T2 &call(T2 &t)
+                static reference call(T2 &t)
                 {
                     return t;
                 }
@@ -332,8 +344,8 @@
             /// Types which are already Proto types are returned by reference.
             ///
             /// This specialization is selected when the type is not yet a Proto type.
-            /// The result type <tt>as_child\<T, Domain\>::::type</tt> is
-            /// <tt>boost::result_of\<Domain(expr\< tag::terminal, term\<T &\> \>)\>::::type</tt>.
+            /// The result type <tt>as_child\<T, Domain\>::type</tt> is
+            /// <tt>boost::result_of\<Domain(expr\< tag::terminal, term\<T &\> \>)\>::type</tt>.
             template<
                 typename T
               , typename Domain // = default_domain
@@ -344,7 +356,7 @@
             >
             struct as_child
             {
-                typedef proto::expr<proto::tag::terminal, term<T &>, 0> expr_;
+                typedef typename base_expr<Domain, proto::tag::terminal, term<T &> >::type expr_;
                 typedef typename Domain::proto_generator proto_generator;
                 typedef typename proto_generator::template result<proto_generator(expr_)>::type type;
 
@@ -353,7 +365,7 @@
                 template<typename T2>
                 static type call(T2 &t)
                 {
-                    return proto_generator()(expr_::make(t));
+                    return proto_generator()(expr_::make(static_cast<T &>(t)));
                 }
             };
 
@@ -365,7 +377,7 @@
             /// Types which are already Proto types are returned by reference.
             ///
             /// This specialization is selected when the type is already a Proto type.
-            /// The result type <tt>as_child\<T, Domain\>::::type</tt> is
+            /// The result type <tt>as_child\<T, Domain\>::type</tt> is
             /// <tt>T &</tt>.
             template<typename T, typename Domain>
             struct as_child<
@@ -397,7 +409,7 @@
                 template<typename T2>
                 static type call(T2 &t)
                 {
-                    return proto_generator()(t);
+                    return proto_generator()(static_cast<T &>(t));
                 }
             };
 
@@ -409,7 +421,7 @@
             /// Types which are already Proto types are returned by reference.
             ///
             /// This specialization is selected when the type is already a Proto type.
-            /// The result type <tt>as_child\<T, Domain\>::::type</tt> is
+            /// The result type <tt>as_child\<T, Domain\>::type</tt> is
             /// <tt>T &</tt>.
             template<typename T>
             struct as_child<
@@ -426,9 +438,9 @@
                 /// INTERNAL ONLY
                 ///
                 template<typename T2>
-                static T2 &call(T2 &t)
+                static type call(T2 &t)
                 {
-                    return t;
+                    return static_cast<T &>(t);
                 }
             };
 
@@ -544,7 +556,7 @@
                 typedef Expr result_type;
 
                 /// \param e The current expression
-                /// \pre <tt>matches\<Expr, terminal\<T\> \>::::value</tt> is \c true.
+                /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true.
                 /// \return \c e
                 /// \throw nothrow
                 #ifdef BOOST_PROTO_STRICT_RESULT_OF
@@ -614,7 +626,7 @@
                 typedef Expr result_type;
 
                 /// \param e The current expression
-                /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::::value</tt> is \c true.
+                /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true.
                 /// \return \c e
                 /// \throw nothrow
                 #ifdef BOOST_PROTO_STRICT_RESULT_OF
@@ -906,7 +918,7 @@
 
                 /// \brief Return the Nth child of the given expression.
                 /// \param expr The expression node.
-                /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true
+                /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
                 /// \pre <tt>N \< Expr::proto_arity::value</tt>
                 /// \return <tt>proto::child_c\<N\>(expr)</tt>
                 /// \throw nothrow
@@ -949,7 +961,7 @@
 
                 /// \brief Return the Nth child of the given expression.
                 /// \param expr The expression node.
-                /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true
+                /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
                 /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
                 /// \return <tt>proto::child\<N\>(expr)</tt>
                 /// \throw nothrow
@@ -987,7 +999,7 @@
 
                 /// \brief Return the value of the given terminal expression.
                 /// \param expr The terminal expression node.
-                /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true
+                /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
                 /// \pre <tt>0 == Expr::proto_arity::value</tt>
                 /// \return <tt>proto::value(expr)</tt>
                 /// \throw nothrow
@@ -1025,7 +1037,7 @@
 
                 /// \brief Return the left child of the given binary expression.
                 /// \param expr The expression node.
-                /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true
+                /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
                 /// \pre <tt>2 == Expr::proto_arity::value</tt>
                 /// \return <tt>proto::left(expr)</tt>
                 /// \throw nothrow
@@ -1063,7 +1075,7 @@
 
                 /// \brief Return the right child of the given binary expression.
                 /// \param expr The expression node.
-                /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true
+                /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
                 /// \pre <tt>2 == Expr::proto_arity::value</tt>
                 /// \return <tt>proto::right(expr)</tt>
                 /// \throw nothrow
@@ -1097,12 +1109,12 @@
         /// without (i.e., <tt>as_expr(t)</tt>). If no domain is
         /// specified, \c default_domain is assumed.
         ///
-        /// If <tt>is_expr\<T\>::::value</tt> is \c true, then the argument is
+        /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
         /// returned unmodified, by reference. Otherwise, the argument is wrapped
         /// in a Proto terminal expression node according to the following rules.
         /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let
         /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr()
-        /// returns <tt>Domain()(terminal\<A\>::::type::make(t))</tt>.
+        /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>.
         ///
         /// \param t The object to wrap.
         template<typename T>
@@ -1153,9 +1165,9 @@
         /// without (i.e., <tt>as_child(t)</tt>). If no domain is
         /// specified, \c default_domain is assumed.
         ///
-        /// If <tt>is_expr\<T\>::::value</tt> is \c true, then the argument is
+        /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
         /// returned as-is. Otherwise, \c as_child() returns
-        /// <tt>Domain()(terminal\<T &\>::::type::make(t))</tt>.
+        /// <tt>Domain()(terminal\<T &\>::type::make(t))</tt>.
         ///
         /// \param t The object to wrap.
         template<typename T>
@@ -1200,7 +1212,7 @@
         /// reference.
         ///
         /// \param expr The Proto expression.
-        /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true.
+        /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
         /// \pre \c N is an MPL Integral Constant.
         /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
         /// \throw nothrow
@@ -1245,7 +1257,7 @@
         /// is returned by reference.
         ///
         /// \param expr The Proto expression.
-        /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true.
+        /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
         /// \pre <tt>N \< Expr::proto_arity::value</tt>
         /// \throw nothrow
         /// \return A reference to the Nth child
@@ -1299,7 +1311,7 @@
         /// child is returned by reference.
         ///
         /// \param expr The Proto expression.
-        /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true.
+        /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
         /// \pre <tt>2 == Expr::proto_arity::value</tt>
         /// \throw nothrow
         /// \return A reference to the left child
@@ -1326,7 +1338,7 @@
         /// child is returned by reference.
         ///
         /// \param expr The Proto expression.
-        /// \pre <tt>is_expr\<Expr\>::::value</tt> is \c true.
+        /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
         /// \pre <tt>2 == Expr::proto_arity::value</tt>
         /// \throw nothrow
         /// \return A reference to the right child
Modified: trunk/boost/proto/transform/arg.hpp
==============================================================================
--- trunk/boost/proto/transform/arg.hpp	(original)
+++ trunk/boost/proto/transform/arg.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -150,7 +150,7 @@
             result_type;
 
             /// Returns the N-th child of \c e
-            /// \pre <tt>arity_of\<Expr\>::::value \> N</tt> 
+            /// \pre <tt>arity_of\<Expr\>::value \> N</tt> 
             /// \param e The current expression.
             /// \return <tt>proto::child_c\<N\>(e)</tt>
             /// \throw nothrow
@@ -190,7 +190,7 @@
             result_type;
 
             /// Returns the value of the specified terminal expression.
-            /// \pre <tt>arity_of\<Expr\>::::value == 0</tt>.
+            /// \pre <tt>arity_of\<Expr\>::value == 0</tt>.
             /// \param e The current expression.
             /// \return <tt>proto::value(e)</tt>
             /// \throw nothrow
Modified: trunk/boost/proto/transform/call.hpp
==============================================================================
--- trunk/boost/proto/transform/call.hpp	(original)
+++ trunk/boost/proto/transform/call.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -121,8 +121,8 @@
             /// \param d An arbitrary data
 
             /// If \c Fun is a nullary PolymorphicFunctionObject, \c type is a typedef
-            /// for <tt>boost::result_of\<Fun()\>::::type</tt>. Otherwise, it is
-            /// a typedef for <tt>boost::result_of\<Fun(Expr, State, Data)\>::::type</tt>.
+            /// for <tt>boost::result_of\<Fun()\>::type</tt>. Otherwise, it is
+            /// a typedef for <tt>boost::result_of\<Fun(Expr, State, Data)\>::type</tt>.
             template<typename Expr, typename State, typename Data>
             struct impl
               : impl2<Expr, State, Data, is_transform<Fun>::value>
@@ -175,8 +175,8 @@
             /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
             /// be the type of \c x.
             /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
-            /// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::::type</tt>.
-            /// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Data)\>::::type</tt>.
+            /// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::type</tt>.
+            /// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Data)\>::type</tt>.
 
             /// Either call the PolymorphicFunctionObject with 1 argument:
             /// the result of applying the \c A0 transform; or
@@ -251,8 +251,8 @@
                 /// be the type of \c y.
                 /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
                 /// and \c y, then \c type is a typedef for
-                /// <tt>boost::result_of\<Fun(X, Y)\>::::type</tt>. Otherwise, it is
-                /// a typedef for <tt>boost::result_of\<Fun(X, Y, Data)\>::::type</tt>.
+                /// <tt>boost::result_of\<Fun(X, Y)\>::type</tt>. Otherwise, it is
+                /// a typedef for <tt>boost::result_of\<Fun(X, Y, Data)\>::type</tt>.
 
             /// Either call the PolymorphicFunctionObject with 2 arguments:
             /// the result of applying the \c A0 transform, and the
Modified: trunk/boost/proto/transform/make.hpp
==============================================================================
--- trunk/boost/proto/transform/make.hpp	(original)
+++ trunk/boost/proto/transform/make.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -89,6 +89,14 @@
                 typedef proto::expr<Tag, Args, N> type;
                 typedef void not_applied_;
             };
+
+            // work around GCC bug
+            template<typename Tag, typename Args, long N, typename Expr, typename State, typename Data>
+            struct make_if_<proto::basic_expr<Tag, Args, N>, Expr, State, Data, false>
+            {
+                typedef proto::basic_expr<Tag, Args, N> type;
+                typedef void not_applied_;
+            };
             #endif
 
             // TODO could optimize this if R is a transform
@@ -207,23 +215,23 @@
         ///
         /// \li Function types
         /// \li Function pointer types
-        /// \li Types for which <tt>proto::is_callable\< type \>::::value</tt> is \c true
+        /// \li Types for which <tt>proto::is_callable\< type \>::value</tt> is \c true
         ///
-        /// <tt>boost::result_of\<make\<T\<X0,X1,...\> \>(Expr, State, Data)\>::::type</tt>
+        /// <tt>boost::result_of\<make\<T\<X0,X1,...\> \>(Expr, State, Data)\>::type</tt>
         /// is evaluated as follows. For each \c X in <tt>X0,X1,...</tt>, do:
         ///
         /// \li If \c X is a template like <tt>U\<Y0,Y1,...\></tt>, then let <tt>X'</tt>
-        ///     be <tt>boost::result_of\<make\<U\<Y0,Y1,...\> \>(Expr, State, Data)\>::::type</tt>
+        ///     be <tt>boost::result_of\<make\<U\<Y0,Y1,...\> \>(Expr, State, Data)\>::type</tt>
         ///     (which evaluates this procedure recursively). Note whether any
         ///     substitutions took place during this operation.
         /// \li Otherwise, if \c X is a transform, then let <tt>X'</tt> be
-        ///     <tt>boost::result_of\<when\<_, X\>(Expr, State, Data)\>::::type</tt>.
+        ///     <tt>boost::result_of\<when\<_, X\>(Expr, State, Data)\>::type</tt>.
         ///     Note that a substitution took place.
         /// \li Otherwise, let <tt>X'</tt> be \c X, and note that no substitution
         ///     took place.
         /// \li If any substitutions took place in any of the above steps and
         ///     <tt>T\<X0',X1',...\></tt> has a nested <tt>::type</tt> typedef,
-        ///     the result type is <tt>T\<X0',X1',...\>::::type</tt>.
+        ///     the result type is <tt>T\<X0',X1',...\>::type</tt>.
         /// \li Otherwise, the result type is <tt>T\<X0',X1',...\></tt>.
         ///
         /// Note that <tt>when\<\></tt> is implemented in terms of <tt>call\<\></tt>
@@ -362,6 +370,18 @@
                     return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a));
                 }
             };
+
+            template<typename T, typename A>
+            struct construct_<proto::basic_expr<T, A, N>, true>
+            {
+                typedef proto::basic_expr<T, A, N> result_type;
+
+                template<BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), typename A)>
+                result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_MAX(N, 1), A, &a)) const
+                {
+                    return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a));
+                }
+            };
         }
 
         /// \brief A PrimitiveTransform which computes a type by evaluating any
@@ -375,7 +395,7 @@
             template<typename Expr, typename State, typename Data>
             struct impl : transform_impl<Expr, State, Data>
             {
-                /// \brief <tt>boost::result_of\<make\<Object\>(Expr, State, Data)\>::::type</tt>
+                /// \brief <tt>boost::result_of\<make\<Object\>(Expr, State, Data)\>::type</tt>
                 typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
                 //typedef typename detail::make_<Object, Expr, State, Data>::type result_type;
 
@@ -437,6 +457,34 @@
                 }
             };
         };
+
+        template<typename Tag, typename Args, long Arity BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
+        struct make<proto::basic_expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))>
+          : transform<make<proto::basic_expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))> >
+        {
+            template<typename Expr, typename State, typename Data>
+            struct impl : transform_impl<Expr, State, Data>
+            {
+                typedef proto::basic_expr<Tag, Args, Arity> result_type;
+
+                result_type operator ()(
+                    typename impl::expr_param   e
+                  , typename impl::state_param  s
+                  , typename impl::data_param   d
+                ) const
+                {
+                    return proto::basic_expr<Tag, Args, Arity>::make(
+                        #define TMP(Z, M, DATA)                                                     \
+                            detail::as_lvalue(                                                      \
+                                typename when<_, BOOST_PP_CAT(A, M)>                                \
+                                    ::template impl<Expr, State, Data>()(e, s, d)                   \
+                            )
+                        BOOST_PP_ENUM(N, TMP, DATA)
+                        #undef TMP
+                    );
+                }
+            };
+        };
         #endif
 
     #undef N
Modified: trunk/boost/proto/transform/pass_through.hpp
==============================================================================
--- trunk/boost/proto/transform/pass_through.hpp	(original)
+++ trunk/boost/proto/transform/pass_through.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -91,7 +91,7 @@
         /// a Grammar.
         ///
         /// Given a Grammar such as <tt>plus\<T0, T1\></tt>, an expression type
-        /// that matches the grammar such as <tt>plus\<E0, E1\>::::type</tt>, a
+        /// that matches the grammar such as <tt>plus\<E0, E1\>::type</tt>, a
         /// state \c S and a data \c V, the result of applying the
         /// <tt>pass_through\<plus\<T0, T1\> \></tt> transform is:
         ///
@@ -167,13 +167,15 @@
             {
                 typedef typename pass_through_impl::expr unref_expr;
 
-                typedef proto::expr<
-                    typename unref_expr::proto_tag
-                  , BOOST_PP_CAT(list, N)<
-                        BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_TRANSFORM_TYPE, ~)
-                    >
-                  , N
-                > expr_type;
+                typedef
+                    typename base_expr<
+                        typename unref_expr::proto_domain
+                      , typename unref_expr::proto_tag
+                      , BOOST_PP_CAT(list, N)<
+                            BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_TRANSFORM_TYPE, ~)
+                        >
+                    >::type
+                expr_type;
 
                 typedef typename unref_expr::proto_generator proto_generator;
                 typedef typename boost::tr1_result_of<proto_generator(expr_type)>::type result_type;
Modified: trunk/boost/proto/transform/when.hpp
==============================================================================
--- trunk/boost/proto/transform/when.hpp	(original)
+++ trunk/boost/proto/transform/when.hpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -46,8 +46,8 @@
         /// In <tt>when\<G, T\></tt>, when \c T is a class type it is a
         /// PrimitiveTransform and the following equivalencies hold:
         ///
-        /// <tt>boost::result_of\<when\<G,T\>(E,S,V)\>::::type</tt> is the same as
-        /// <tt>boost::result_of\<T(E,S,V)\>::::type</tt>.
+        /// <tt>boost::result_of\<when\<G,T\>(E,S,V)\>::type</tt> is the same as
+        /// <tt>boost::result_of\<T(E,S,V)\>::type</tt>.
         ///
         /// <tt>when\<G,T\>()(e,s,d)</tt> is the same as
         /// <tt>T()(e,s,d)</tt>.
@@ -130,7 +130,7 @@
         ///
         /// The <tt>when\<G, R(A0,A1,...)\></tt> form accepts either a
         /// CallableTransform or an ObjectTransform as its second parameter.
-        /// <tt>when\<\></tt> uses <tt>is_callable\<R\>::::value</tt> to
+        /// <tt>when\<\></tt> uses <tt>is_callable\<R\>::value</tt> to
         /// distinguish between the two, and uses <tt>call\<\></tt> to
         /// evaluate CallableTransforms and <tt>make\<\></tt> to evaluate
         /// ObjectTransforms.
@@ -159,13 +159,13 @@
 
                 /// Evaluate <tt>R(A0,A1,...)</tt> as a transform either with
                 /// <tt>call\<\></tt> or with <tt>make\<\></tt> depending on
-                /// whether <tt>is_callable\<R\>::::value</tt> is \c true or
+                /// whether <tt>is_callable\<R\>::value</tt> is \c true or
                 /// \c false.
                 ///
                 /// \param e The current expression
                 /// \param s The current state
                 /// \param d An arbitrary data
-                /// \pre <tt>matches\<Expr, Grammar\>::::value</tt> is \c true
+                /// \pre <tt>matches\<Expr, Grammar\>::value</tt> is \c true
                 /// \return <tt>which()(e, s, d)</tt>
                 result_type operator ()(
                     typename impl::expr_param   e
Modified: trunk/libs/proto/doc/glossary.qbk
==============================================================================
--- trunk/libs/proto/doc/glossary.qbk	(original)
+++ trunk/libs/proto/doc/glossary.qbk	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -45,9 +45,9 @@
        within that problem space.]]
   [ [ [anchor expression] expression]
       [In Proto, an /expression/ is a heterogeneous tree where each node is either 
-       an instantiation of `boost::proto::expr<>` or some type that is an extension 
-       (via `boost::proto::extends<>` or `BOOST_PROTO_EXTENDS()`) of such an 
-       instantiation.]]
+       an instantiation of `boost::proto::expr<>`, `boost::proto::basic_expr<>` or
+	   some type that is an extension  (via `boost::proto::extends<>` or 
+	   `BOOST_PROTO_EXTENDS()`) of such an instantiation.]]
   [ [ [anchor expression_template] expression template]
       [A C++ technique using templates and operator overloading to cause 
        expressions to build trees that represent the expression for lazy evaluation 
Modified: trunk/libs/proto/doc/proto.qbk
==============================================================================
--- trunk/libs/proto/doc/proto.qbk	(original)
+++ trunk/libs/proto/doc/proto.qbk	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -47,6 +47,8 @@
   [@../../libs/typeof/index.html Boost.Typeof]]
 [def _expr_                 
   [classref  boost::proto::expr `proto::expr<>`]]
+[def _basic_expr_                 
+  [classref  boost::proto::basic_expr `proto::basic_expr<>`]]
 [def _deep_copy_            
   [funcref   boost::proto::deep_copy `proto::deep_copy()`]]
 [def _domain_              
Modified: trunk/libs/proto/doc/reference.xml
==============================================================================
--- trunk/libs/proto/doc/reference.xml	(original)
+++ trunk/libs/proto/doc/reference.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -77,6 +77,16 @@
       </listitem>
       <listitem>
         <computeroutput>
+          <classname alt="boost::proto::base_expr">proto::base_expr</classname>
+        </computeroutput>
+      </listitem>
+      <listitem>
+        <computeroutput>
+          <classname alt="boost::proto::basic_expr">proto::basic_expr</classname>
+        </computeroutput>
+      </listitem>
+      <listitem>
+        <computeroutput>
           <classname alt="boost::proto::binary_expr">proto::binary_expr</classname>
         </computeroutput>
       </listitem>
@@ -912,6 +922,11 @@
       </listitem>
       <listitem>
         <computeroutput>
+          <classname alt="boost::proto::use_basic_expr">proto::use_basic_expr</classname>
+        </computeroutput>
+      </listitem>
+      <listitem>
+        <computeroutput>
           <classname alt="boost::proto::unexpr">proto::unexpr</classname>
         </computeroutput>
       </listitem>
@@ -922,6 +937,11 @@
       </listitem>
       <listitem>
         <computeroutput>
+          <classname alt="boost::proto::wants_basic_expr">proto::wants_basic_expr</classname>
+        </computeroutput>
+      </listitem>
+      <listitem>
+        <computeroutput>
           <classname alt="boost::proto::when">proto::when</classname>
         </computeroutput>
       </listitem>
Modified: trunk/libs/proto/doc/reference/args.xml
==============================================================================
--- trunk/libs/proto/doc/reference/args.xml	(original)
+++ trunk/libs/proto/doc/reference/args.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -16,13 +16,16 @@
         <template>
           <template-type-parameter name="T"/>
         </template>
-        <purpose>A type sequence, for use as the 2<superscript>nd</superscript> parameter to the <computeroutput>
-          <classname alt="proto::expr">proto::expr<></classname></computeroutput> class template.</purpose>
+        <purpose>A type sequence, for use as the 2<superscript>nd</superscript> parameter to the
+        <computeroutput><classname alt="proto::expr">proto::expr<></classname></computeroutput> and 
+        <computeroutput><classname alt="proto::basic_expr">proto::basic_expr<></classname></computeroutput>
+        class templates.</purpose>
         <description>
           <para>
-            A type sequence, for use as the 2<superscript>nd</superscript> parameter to the <computeroutput>
-            <classname alt="proto::expr">proto::expr<></classname></computeroutput> class template. The
-            types in the sequence correspond to the children of a node in an expression tree.
+            A type sequence with one element, for use as the 2<superscript>nd</superscript> parameter to the 
+            <computeroutput><classname alt="proto::expr">proto::expr<></classname></computeroutput> and 
+            <computeroutput><classname alt="proto::basic_expr">proto::basic_expr<></classname></computeroutput>
+            class templates. The sequence element represents the value of a terminal.
           </para>
         </description>
         <data-member name="arity" specifiers="static">
@@ -40,12 +43,14 @@
           <template-type-parameter name="Arg" pack="1"/>
         </template>
         <purpose><computeroutput>proto::list1<></computeroutput>, <computeroutput>proto::list2<></computeroutput>, etc.,
-          are type sequences for use as the 2<superscript>nd</superscript> parameter to the <computeroutput>
-          <classname>proto::expr<></classname></computeroutput> class template.</purpose>
+          are type sequences for use as the 2<superscript>nd</superscript> parameter to the 
+          <computeroutput><classname>proto::expr<></classname></computeroutput> or
+          <computeroutput><classname>proto::basic_expr<></classname></computeroutput> class templates.</purpose>
         <description>
           <para>
-            Type sequences, for use as the 2<superscript>nd</superscript> parameter to the <computeroutput>
-            <classname>proto::expr<></classname></computeroutput> class template. The
+            Type sequences, for use as the 2<superscript>nd</superscript> parameter to the
+            <computeroutput><classname>proto::expr<></classname></computeroutput> or
+            <computeroutput><classname>proto::basic_expr<></classname></computeroutput> class template. The
             types in the sequence correspond to the children of a node in an expression tree.
             There is no type literally named "<computeroutput>listN</computeroutput>"; rather, there is
             a set of types named
Modified: trunk/libs/proto/doc/reference/concepts/Expr.xml
==============================================================================
--- trunk/libs/proto/doc/reference/concepts/Expr.xml	(original)
+++ trunk/libs/proto/doc/reference/concepts/Expr.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -95,7 +95,8 @@
     <description>
       <simpara>
         A typedef for an instantiation of
-        <classname alt="boost::proto::expr"><code>proto::expr<></code></classname>
+        <classname alt="boost::proto::expr"><code>proto::expr<></code></classname> or
+        <classname alt="boost::proto::basic_expr"><code>proto::basic_expr<></code></classname>
         that is equivalent to Expr. Expression types are equivalent if they have the
         same <code>proto_tag</code>, <code>proto_args</code>, and <code>proto_arity</code>.
       </simpara>
@@ -180,7 +181,8 @@
     </return-type>
     <semantics>
         Returns an object of type
-        <classname alt="boost::proto::expr"><code>proto::expr<></code></classname>
+        <classname alt="boost::proto::expr"><code>proto::expr<></code></classname> or
+        <classname alt="boost::proto::basic_expr"><code>proto::basic_expr<></code></classname>
         that is equivalent to <code>e</code>.
     </semantics>
   </valid-expression>
Modified: trunk/libs/proto/doc/reference/domain.xml
==============================================================================
--- trunk/libs/proto/doc/reference/domain.xml	(original)
+++ trunk/libs/proto/doc/reference/domain.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -132,6 +132,69 @@
         </typedef>
       </struct>
 
+      <!-- proto::use_basic_expr -->
+      <struct name="use_basic_expr">
+        <template>
+          <template-type-parameter name="Domain"/>
+        </template>
+        <description>
+          <para>
+            Annotate a domain to indicate that its generator would
+            prefer to be passed instances of
+            <computeroutput><classname>proto::basic_expr</classname><></computeroutput> rather than
+            <computeroutput><classname>proto::expr</classname><></computeroutput>.
+            <computeroutput>use_basic_expr< Domain ></computeroutput> is itself a domain.
+          </para>
+        </description>
+      </struct>
+
+      <!-- proto::wants_basic_expr -->
+      <struct name="wants_basic_expr">
+        <template>
+          <template-type-parameter name="Domain"/>
+        </template>
+        <description>
+          <para>
+            A Boolean metafunction that tests a domain to see whether
+            its generator would prefer to be passed instances of
+            <computeroutput><classname>proto::basic_expr</classname><></computeroutput> rather than
+            <computeroutput><classname>proto::expr</classname><></computeroutput>.
+          </para>
+        </description>
+        <inherit>
+          <type>mpl::bool_< <replaceable>true-or-false</replaceable> ></type>
+        </inherit>
+      </struct>
+
+      <!-- proto::wants_basic_expr -->
+      <struct name="base_expr">
+        <template>
+          <template-type-parameter name="Domain"/>
+          <template-type-parameter name="Tag"/>
+          <template-type-parameter name="Args"/>
+        </template>
+        <description>
+          <para>
+            Given a domain, a tag type and an argument list,
+            compute the type of the expression to generate. This is
+            either an instance of 
+            <computeroutput><classname>proto::basic_expr</classname><></computeroutput> or
+            <computeroutput><classname>proto::expr</classname><></computeroutput>.
+            </para>
+        </description>
+        <typedef name="A">
+          <purpose>For exposition only</purpose>
+          <type><classname>proto::basic_expr</classname>< Tag, Args ></type>
+        </typedef>
+        <typedef name="B">
+          <purpose>For exposition only</purpose>
+          <type><classname>proto::expr</classname>< Tag, Args ></type>
+        </typedef>
+        <typedef name="type">
+          <type>typename mpl::if_<<classname>proto::wants_basic_expr</classname>< Domain >, A, B>::type</type>
+        </typedef>
+      </struct>
+
     </namespace>
   </namespace>
 </header>
Modified: trunk/libs/proto/doc/reference/expr.xml
==============================================================================
--- trunk/libs/proto/doc/reference/expr.xml	(original)
+++ trunk/libs/proto/doc/reference/expr.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -11,10 +11,130 @@
           <template-type-parameter name="Args"/>
           <template-nontype-parameter name="Arity">
             <type>long</type>
+            <default>Args::arity</default>
           </template-nontype-parameter>
         </template>
 
         <purpose>Simplified representation of a node in an expression tree.</purpose>
+
+        <description>
+          <para>
+            <computeroutput>proto::basic_expr<></computeroutput> is a node in an expression
+            template tree. It is a container for its child sub-trees. It also serves as the
+            terminal nodes of the tree.
+          </para>
+          <para>
+            <computeroutput>Tag</computeroutput> is type that represents the operation
+            encoded by this expression. It is typically one of the structs in the
+            <computeroutput>boost::proto::tag</computeroutput> namespace, but it doesn't
+            have to be. If <computeroutput>Arity</computeroutput> is 0 then this
+            <computeroutput>expr<></computeroutput> type represents a leaf in the
+            expression tree.
+          </para>
+          <para>
+            <computeroutput>Args</computeroutput> is a list of types representing
+            the children of this expression. It is an instantiation of one of
+            <computeroutput><classname alt="proto::listN">proto::list1<></classname></computeroutput>,
+            <computeroutput><classname alt="proto::listN">proto::list2<></classname></computeroutput>,
+            etc. The child types
+            must all themselves be either <computeroutput>proto::expr<></computeroutput>
+            or <computeroutput>proto::basic_expr<>&</computeroutput> (or extensions thereof via
+            <computeroutput><classname>proto::extends<></classname></computeroutput> or
+            <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>), unless
+            <computeroutput>Arity</computeroutput> is 0, in which case
+            <computeroutput>Args</computeroutput> must be
+            <computeroutput>proto::term<T></computeroutput>, where
+            <computeroutput>T</computeroutput> can be any type.
+          </para>
+          <para>
+            <computeroutput>proto::basic_expr<></computeroutput> is a valid Fusion
+            random-access sequence, where the elements of the sequence are the child
+            expressions.
+          </para>
+        </description>
+
+        <!-- typedefs -->
+
+        <typedef name="proto_tag">
+          <type>Tag</type>
+        </typedef>
+
+        <typedef name="proto_args">
+          <type>Args</type>
+        </typedef>
+
+        <typedef name="proto_arity">
+          <type>mpl::long_< Arity ></type>
+        </typedef>
+
+        <typedef name="proto_domain">
+          <type><classname>proto::default_domain</classname></type>
+        </typedef>
+
+        <typedef name="proto_grammar">
+          <type>basic_expr</type>
+        </typedef>
+
+        <typedef name="proto_base_expr">
+          <type>basic_expr</type>
+        </typedef>
+
+        <typedef name="proto_derived_expr">
+          <type>basic_expr</type>
+        </typedef>
+
+        <typedef name="proto_childN">
+          <type>typename Args::child<replaceable>N</replaceable></type>
+          <purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(Arity,1))</replaceable>.</purpose>
+        </typedef>
+
+        <method-group name="public static functions">
+
+          <!-- make -->
+          <method name="make" specifiers="static">
+            <type>basic_expr const</type>
+            <template>
+              <template-type-parameter name="A" pack="1"/>
+            </template>
+            <parameter name="a" pack="1">
+              <paramtype>A const &</paramtype>
+            </parameter>
+            <requires>
+              <para>
+                The number of supplied arguments must be <computeroutput>max(Arity,1)</computeroutput>.
+              </para>
+            </requires>
+            <returns>
+              <para>
+                A new <computeroutput>basic_expr</computeroutput> object initialized with the specified arguments.
+              </para>
+            </returns>
+          </method>
+
+        </method-group>
+
+        <method-group name="public member functions">
+
+          <method name="proto_base">
+            <type>basic_expr &</type>
+            <returns>
+              <para>
+                <computeroutput>*this</computeroutput>
+              </para>
+            </returns>
+          </method>
+
+          <method name="proto_base" cv="const">
+            <type>basic_expr const &</type>
+            <description>
+              <para>
+                This is an overloaded member function, provided for convenience. It differs from
+                the above function only in what argument(s) it accepts.
+              </para>
+            </description>
+          </method>
+
+        </method-group>
       </struct>
 
       <!-- boost::proto::expr -->
@@ -52,7 +172,7 @@
             <computeroutput><classname alt="proto::listN">proto::list2<></classname></computeroutput>,
             etc. The child types
             must all themselves be either <computeroutput>proto::expr<></computeroutput>
-            or <computeroutput>proto::expr<>&</computeroutput> (or extensions thereof via
+            or <computeroutput>proto::basic_expr<>&</computeroutput> (or extensions thereof via
             <computeroutput><classname>proto::extends<></classname></computeroutput> or
             <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>), unless
             <computeroutput>Arity</computeroutput> is 0, in which case
Modified: trunk/libs/proto/doc/reference/make_expr.xml
==============================================================================
--- trunk/libs/proto/doc/reference/make_expr.xml	(original)
+++ trunk/libs/proto/doc/reference/make_expr.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -209,15 +209,15 @@
                 If <computeroutput>Tag</computeroutput> is
                 <computeroutput><classname>proto::tag::terminal</classname></computeroutput>, then
                 <computeroutput>type</computeroutput> is a typedef for
-                <computeroutput>boost::result_of<Domain(<classname>proto::expr</classname><
-                <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><
-                A<subscript>0</subscript> > >)>::type</computeroutput>.
+                <computeroutput>boost::result_of<Domain(typename <classname>proto::base_expr</classname><
+                Domain, <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><
+                A<subscript>0</subscript> > >::type)>::type</computeroutput>.
               </para>
               <para>
                 Otherwise, <computeroutput>type</computeroutput> is a typedef for
-                <computeroutput>boost::result_of<Domain(<classname>proto::expr</classname><
-                Tag, <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname><
-                typename <classname>proto::result_of::as_child</classname><A>::type...> >)>::type</computeroutput>
+                <computeroutput>boost::result_of<Domain(typename <classname>proto::base_expr</classname><
+                Domain, Tag, <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname><
+                typename <classname>proto::result_of::as_child</classname><A>::type...> >::type)>::type</computeroutput>
               </para>
             </description>
             <type><emphasis>see-below</emphasis></type>
@@ -352,7 +352,7 @@
               </listitem>
             </itemizedlist>
             Let <computeroutput><replaceable>MAKE</replaceable><Tag>(a...)</computeroutput> be defined as
-            <computeroutput><classname>proto::expr</classname><Tag,
+            <computeroutput><classname>proto::base_expr</classname><Domain, Tag,
             <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname><A...> >::make(a...)</computeroutput>
             where
             <computeroutput>A<subscript>x</subscript></computeroutput> is the type of 
@@ -426,7 +426,7 @@
               </listitem>
             </itemizedlist>
             Let <computeroutput><replaceable>MAKE</replaceable><Tag>(a...)</computeroutput> be defined as
-            <computeroutput><classname>proto::expr</classname><Tag,
+            <computeroutput><classname>proto::base_expr</classname><Domain, Tag,
             <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname><A...> >::make(a...)</computeroutput>
             where
             <computeroutput>A<subscript>x</subscript></computeroutput> is the type of 
Modified: trunk/libs/proto/doc/reference/matches.xml
==============================================================================
--- trunk/libs/proto/doc/reference/matches.xml	(original)
+++ trunk/libs/proto/doc/reference/matches.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -503,9 +503,9 @@
         <purpose>For matching a Grammar to a variable number of sub-expressions.</purpose>
         <description>
           <para>
-            An expression type <computeroutput><classname>proto::expr</classname><AT,
+            An expression type <computeroutput><classname>proto::basic_expr</classname><AT,
             <classname alt="proto::listN">proto::list<replaceable>N</replaceable></classname><A<subscript>0</subscript>,...A<subscript>n</subscript>,U<subscript>0</subscript>,...U<subscript>m</subscript>> ></computeroutput>
-            matches a grammar <computeroutput><classname>proto::expr</classname><BT,
+            matches a grammar <computeroutput><classname>proto::basic_expr</classname><BT,
             <classname alt="proto::listN">proto::list<replaceable>M</replaceable></classname><B<subscript>0</subscript>,...B<subscript>n</subscript>,proto::vararg<V> > ></computeroutput>
             if <computeroutput>BT</computeroutput> is <computeroutput><classname>proto::_</classname></computeroutput>
             or <computeroutput>AT</computeroutput>, and if
@@ -559,7 +559,7 @@
                 <para>
                   An expression
                   <computeroutput>
-                    <classname>proto::expr</classname><AT,
+                    <classname>proto::basic_expr</classname><AT,
                     <classname alt="proto::listN">
                       proto::list<replaceable>N</replaceable>
                     </classname><A<subscript>0</subscript>,...A<subscript>n</subscript>>
@@ -567,7 +567,7 @@
                   </computeroutput>
                   matches a grammar
                   <computeroutput>
-                    <classname>proto::expr</classname><BT,
+                    <classname>proto::basic_expr</classname><BT,
                     <classname alt="proto::listN">
                       proto::list<replaceable>N</replaceable>
                     </classname><B<subscript>0</subscript>,...B<subscript>n</subscript>>
@@ -588,14 +588,14 @@
                 <para>
                   An expression
                   <computeroutput>
-                    <classname>proto::expr</classname><AT,
+                    <classname>proto::basic_expr</classname><AT,
                     <classname alt="proto::listN">
                       proto::list<replaceable>N</replaceable>
                     </classname><A<subscript>0</subscript>,...A<subscript>n</subscript>,U<subscript>0</subscript>,...U<subscript>m</subscript>>
                     >
                   </computeroutput> matches a grammar
                   <computeroutput>
-                    <classname>proto::expr</classname><BT,
+                    <classname>proto::basic_expr</classname><BT,
                     <classname alt="proto::listN">
                       proto::list<replaceable>M</replaceable>
                     </classname><B<subscript>0</subscript>,...B<subscript>n</subscript>,<classname>proto::vararg</classname><V>
@@ -700,11 +700,11 @@
           <para>
             A terminal expression
             <computeroutput>
-              <classname>proto::expr</classname><AT,
+              <classname>proto::basic_expr</classname><AT,
               <classname>proto::term</classname><A> >
             </computeroutput> matches a grammar
             <computeroutput>
-              <classname>proto::expr</classname><BT, <classname>proto::term</classname><B> >
+              <classname>proto::basic_expr</classname><BT, <classname>proto::term</classname><B> >
             </computeroutput>
             if <computeroutput>BT</computeroutput> is <computeroutput><classname>proto::_</classname></computeroutput>
             or <computeroutput>AT</computeroutput> and one of the following is true:
Modified: trunk/libs/proto/doc/reference/traits.xml
==============================================================================
--- trunk/libs/proto/doc/reference/traits.xml	(original)
+++ trunk/libs/proto/doc/reference/traits.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -71,7 +71,8 @@
             <computeroutput>T t(a<subscript>0</subscript>,...a<subscript>n</subscript>)</computeroutput>.
           </para>
           <para>
-            Note: <computeroutput><classname>proto::expr<></classname> is an aggregate.</computeroutput>
+            Note: <computeroutput><classname>proto::expr<></classname></computeroutput> and
+            <computeroutput><classname>proto::basic_expr<></classname></computeroutput>are aggregates.
           </para>
         </description>
         <inherit><type>mpl::bool_<<replaceable>true-or-false</replaceable>></type></inherit>
@@ -2046,8 +2047,9 @@
           is a Proto expression type.</purpose>
         <description>
           <para>
-            If <computeroutput>T</computeroutput> is an instantiation of <computeroutput>
-            <classname alt="proto::expr">proto::expr<></classname></computeroutput> or is an extension
+            If <computeroutput>T</computeroutput> is an instantiation of 
+            <computeroutput><classname alt="proto::expr">proto::expr<></classname></computeroutput> or
+            <computeroutput><classname alt="proto::basic_expr">proto::basic_expr<></classname></computeroutput> or is an extension
             (via <classname alt="proto::extends">proto::extends<></classname> or
             <macroname>BOOST_PROTO_EXTENDS</macroname>()) of such an instantiation, 
             <computeroutput><classname>proto::is_expr</classname><T>::value</computeroutput>
@@ -2101,7 +2103,7 @@
               <computeroutput>A</computeroutput> be <computeroutput>T &</computeroutput>. Otherwise, let
               <computeroutput>A</computeroutput> be the type <computeroutput>T</computeroutput> stripped of
               cv-qualifiers. Then, the result type <computeroutput>proto::result_of::as_expr<T, Domain>::type</computeroutput>
-              is <computeroutput>boost::result_of<Domain(<classname>proto::expr</classname>< <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><A> >)>::type</computeroutput>.
+              is <computeroutput>boost::result_of<Domain(typename <classname>proto::base_expr</classname><Domain, <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><A> >::type)>::type</computeroutput>.
             </para>
           </description>
           <typedef name="type">
@@ -2127,7 +2129,7 @@
             <para>
               When <computeroutput>T</computeroutput> is not yet a Proto type,
               the result type <computeroutput>proto::result_of::as_child<T, Domain>::type</computeroutput> is
-              <computeroutput>boost::result_of<Domain(<classname>proto::expr</classname>< <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><T &> >)>::type</computeroutput>.
+              <computeroutput>boost::result_of<Domain(typename <classname>proto::base_expr</classname><Domain, <classname>proto::tag::terminal</classname>, <classname>proto::term</classname><T &> >::type)>::type</computeroutput>.
             </para>
             <para>
               When <computeroutput>T</computeroutput> is already a Proto type
Modified: trunk/libs/proto/doc/reference/transform/pass_through.xml
==============================================================================
--- trunk/libs/proto/doc/reference/transform/pass_through.xml	(original)
+++ trunk/libs/proto/doc/reference/transform/pass_through.xml	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -106,7 +106,7 @@
           </typedef>
           <typedef name="expr_type">
             <purpose>For exposition only</purpose>
-            <type><classname>proto::expr</classname><T, <classname>proto::listN</classname><R0,...RN> ></type>
+            <type>typename <classname>proto::base_expr</classname><D, T, <classname>proto::listN</classname><R0,...RN> >::type</type>
           </typedef>
           <typedef name="result_type">
             <type>typename boost::result_of<D(expr_type)>::type</type>
Modified: trunk/libs/proto/test/make_expr.cpp
==============================================================================
--- trunk/libs/proto/test/make_expr.cpp	(original)
+++ trunk/libs/proto/test/make_expr.cpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -38,13 +38,31 @@
     unary_plus<terminal<int>::type>::type p2 = make_expr<tag::unary_plus>(i);
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int>::type> >::type> p3 = make_expr<tag::unary_plus, mydomain>(i);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = make_expr<tag::unary_plus, mydomain>(i);
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int>::type> >::type>
-      , ewrap<terminal<int>::type>
-    >::type> p4 = make_expr<tag::plus>(p3, 0);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = make_expr<tag::plus>(p3, 0);
     BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
 }
 
@@ -58,13 +76,31 @@
     unary_plus<terminal<int &>::type>::type p2 = make_expr<tag::unary_plus>(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> p3 = make_expr<tag::unary_plus, mydomain>(boost::ref(i));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int &> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = make_expr<tag::unary_plus, mydomain>(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> &
-      , ewrap<terminal<int>::type>
-    >::type> p4 = make_expr<tag::plus>(boost::ref(p3), 0);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type &
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = make_expr<tag::plus>(boost::ref(p3), 0);
     BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
 }
 
@@ -77,14 +113,31 @@
     unary_plus<terminal<int>::type>::type p2 = functional::make_expr<tag::unary_plus>()(i);
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int>::type> >::type> p3 = functional::make_expr<tag::unary_plus, mydomain>()(i);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = functional::make_expr<tag::unary_plus, mydomain>()(i);
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int>::type> >::type>
-      , ewrap<terminal<int>::type>
-    >::type> p4 = functional::make_expr<tag::plus, mydomain>()(p3, 0);
-    BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = functional::make_expr<tag::plus>()(p3, 0);
 }
 
 void test_make_expr_functional_ref()
@@ -97,13 +150,31 @@
     unary_plus<terminal<int &>::type>::type p2 = functional::make_expr<tag::unary_plus>()(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> p3 = functional::make_expr<tag::unary_plus, mydomain>()(boost::ref(i));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int &> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = functional::make_expr<tag::unary_plus, mydomain>()(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> &
-      , ewrap<terminal<int>::type>
-    >::type> p4 = functional::make_expr<tag::plus, mydomain>()(boost::ref(p3), 0);
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type &
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = functional::make_expr<tag::plus>()(boost::ref(p3), 0);
     BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
 }
 
@@ -116,13 +187,31 @@
     unary_plus<terminal<int &>::type>::type p2 = unpack_expr<tag::unary_plus>(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> p3 = unpack_expr<tag::unary_plus, mydomain>(fusion::make_tuple(boost::ref(i)));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int &> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = unpack_expr<tag::unary_plus, mydomain>(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> &
-      , ewrap<terminal<int>::type>
-    >::type> p4 = unpack_expr<tag::plus>(fusion::make_tuple(boost::ref(p3), 0));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type &
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = unpack_expr<tag::plus>(fusion::make_tuple(boost::ref(p3), 0));
     BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
 }
 
@@ -135,13 +224,31 @@
     unary_plus<terminal<int &>::type>::type p2 = functional::unpack_expr<tag::unary_plus>()(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
 
-    ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> p3 = functional::unpack_expr<tag::unary_plus, mydomain>()(fusion::make_tuple(boost::ref(i)));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::unary_plus
+              , proto::list1<
+                    ewrap<proto::basic_expr<tag::terminal, proto::term<int &> > >
+                >
+            >
+        >
+    p3_type;
+    p3_type p3 = functional::unpack_expr<tag::unary_plus, mydomain>()(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
 
-    ewrap<plus<
-        ewrap<unary_plus<ewrap<terminal<int &>::type> >::type> &
-      , ewrap<terminal<int>::type>
-    >::type> p4 = functional::unpack_expr<tag::plus>()(fusion::make_tuple(boost::ref(p3), 0));
+    typedef
+        ewrap<
+            proto::basic_expr<
+                tag::plus
+              , proto::list2<
+                    p3_type &
+                  , ewrap<proto::basic_expr<tag::terminal, proto::term<int> > >
+                >
+            >
+        >
+    p4_type;
+    p4_type p4 = functional::unpack_expr<tag::plus>()(fusion::make_tuple(boost::ref(p3), 0));
     BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
 }
 
Modified: trunk/libs/proto/test/proto_fusion_s.cpp
==============================================================================
--- trunk/libs/proto/test/proto_fusion_s.cpp	(original)
+++ trunk/libs/proto/test/proto_fusion_s.cpp	2010-06-08 20:14:39 EDT (Tue, 08 Jun 2010)
@@ -28,6 +28,12 @@
     return sout << boost::proto::value(*op);
 }
 
+template<typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<boost::proto::tag::terminal, Args, 0> const *op)
+{
+    return sout << boost::proto::value(*op);
+}
+
 template<typename Tag, typename Args>
 std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 1> const *op)
 {
@@ -35,11 +41,23 @@
 }
 
 template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 1> const *op)
+{
+    return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base());
+}
+
+template<typename Tag, typename Args>
 std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 2> const *op)
 {
     return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
 }
 
+template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 2> const *op)
+{
+    return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // to_string
 //