Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r74513 - in trunk: boost/proto boost/proto/detail boost/proto/transform libs/proto/doc/reference libs/proto/test
From: eric_at_[hidden]
Date: 2011-09-22 13:34:23


Author: eric_niebler
Date: 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
New Revision: 74513
URL: http://svn.boost.org/trac/boost/changeset/74513

Log:
add second template parameter to proto::siwtch_ to control dispatching to cases
Added:
   trunk/libs/proto/test/switch.cpp (contents, props changed)
Text files modified:
   trunk/boost/proto/detail/reverse.hpp | 4
   trunk/boost/proto/make_expr.hpp | 6 +-
   trunk/boost/proto/matches.hpp | 85 +++++++++++++++++++++++++++------------
   trunk/boost/proto/proto_fwd.hpp | 8 +-
   trunk/boost/proto/transform/default.hpp | 4
   trunk/libs/proto/doc/reference/matches.xml | 41 +++++++++++--------
   trunk/libs/proto/test/Jamfile.v2 | 1
   7 files changed, 95 insertions(+), 54 deletions(-)

Modified: trunk/boost/proto/detail/reverse.hpp
==============================================================================
--- trunk/boost/proto/detail/reverse.hpp (original)
+++ trunk/boost/proto/detail/reverse.hpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -49,8 +49,8 @@
         typedef typename meta::end<seq>::type last_type;
 
         reverse_view(Sequence& seq)
- : first(fusion::begin(seq))
- , last(fusion::end(seq))
+ : first(fusion::begin(seq))
+ , last(fusion::end(seq))
         {}
 
         first_type first;

Modified: trunk/boost/proto/make_expr.hpp
==============================================================================
--- trunk/boost/proto/make_expr.hpp (original)
+++ trunk/boost/proto/make_expr.hpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -310,9 +310,9 @@
>
             struct impl
               : detail::make_expr_<
- Tag
- , Domain
- BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
+ Tag
+ , Domain
+ BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
>
             {};
         };

Modified: trunk/boost/proto/matches.hpp
==============================================================================
--- trunk/boost/proto/matches.hpp (original)
+++ trunk/boost/proto/matches.hpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -402,6 +402,24 @@
         {};
 
         // handle proto::switch_
+ template<typename Expr, typename Tag, typename Args, long Arity, typename Cases, typename Transform>
+ struct matches_<Expr, proto::basic_expr<Tag, Args, Arity>, switch_<Cases, Transform> >
+ : matches_<
+ Expr
+ , proto::basic_expr<Tag, Args, Arity>
+ , typename Cases::template case_<
+ typename when<_,Transform>::template impl<Expr,int,int>::result_type
+ >::proto_grammar
+ >
+ {
+ typedef
+ typename Cases::template case_<
+ typename when<_, Transform>::template impl<Expr, int, int>::result_type
+ >
+ which;
+ };
+
+ // handle proto::switch_ with the default Transform for specially for better compile times
         template<typename Expr, typename Tag, typename Args, long Arity, typename Cases>
         struct matches_<Expr, proto::basic_expr<Tag, Args, Arity>, switch_<Cases> >
           : matches_<
@@ -447,8 +465,9 @@
     /// and \c V defaults to \c not_\<_\>.)
     /// \li An expression \c E matches <tt>not_\<T\></tt> if \c E does
     /// not match \c T.
- /// \li An expression \c E matches <tt>switch_\<C\></tt> if
- /// \c E matches <tt>C::case_\<E::proto_tag\></tt>.
+ /// \li An expression \c E matches <tt>switch_\<C,T\></tt> if
+ /// \c E matches <tt>C::case_\<boost::result_of\<T(E)\>::type\></tt>.
+ /// (Note: T defaults to <tt>tag_of\<_\>()</tt>.)
     ///
     /// A terminal expression <tt>expr\<AT,term\<A\> \></tt> matches
     /// a grammar <tt>expr\<BT,term\<B\> \></tt> if \c BT is \c AT or
@@ -604,8 +623,8 @@
             #endif
             operator()(
                 typename impl::expr_param e
- , typename impl::state_param
- , typename impl::data_param
+ , typename impl::state_param
+ , typename impl::data_param
             ) const
             {
                 return e;
@@ -769,33 +788,47 @@
     };
 
     /// \brief For matching one of a set of alternate grammars, which
- /// are looked up based on an expression's tag type. When used as a
- /// transform, \c switch_\<\> applies the transform associated with
- /// the grammar that matches the expression.
+ /// are looked up based on some property of an expression. The
+ /// property on which to dispatch is specified by the \c Transform
+ /// template parameter, which defaults to <tt>tag_of\<_\>()</tt>.
+ /// That is, when the \c Trannsform is not specified, the alternate
+ /// grammar is looked up using the tag type of the current expression.
     ///
- /// \note \c switch_\<\> is functionally identical to \c or_\<\> but
- /// is often more efficient. It does a fast, O(1) lookup based on an
- /// expression's tag type to find a sub-grammar that may potentially
- /// match the expression.
+ /// When used as a transform, \c switch_\<\> applies the transform
+ /// associated with the grammar that matches the expression.
     ///
- /// An expression type \c E matches <tt>switch_\<C\></tt> if \c E
- /// matches <tt>C::case_\<E::proto_tag\></tt>.
+ /// \note \c switch_\<\> is functionally identical to \c or_\<\> but
+ /// is often more efficient. It does a fast, O(1) lookup using the
+ /// result of the specified transform to find a sub-grammar that may
+ /// potentially match the expression.
+ ///
+ /// An expression type \c E matches <tt>switch_\<C,T\></tt> if \c E
+ /// matches <tt>C::case_\<boost::result_of\<T(E)\>::type\></tt>.
+ ///
+ /// When applying <tt>switch_\<C,T\></tt> as a transform with an
+ /// expression \c e of type \c E, state \c s of type \S and data
+ /// \c d of type \c D, it is equivalent to
+ /// <tt>C::case_\<boost::result_of\<T(E,S,D)\>::type\>()(e, s, d)</tt>.
+ template<typename Cases, typename Transform>
+ struct switch_ : transform<switch_<Cases, Transform> >
+ {
+ typedef switch_ proto_grammar;
+
+ template<typename Expr, typename State, typename Data>
+ struct impl
+ : Cases::template case_<
+ typename when<_, Transform>::template impl<Expr, State, Data>::result_type
+ >::template impl<Expr, State, Data>
+ {};
+ };
+
+ /// INTERNAL ONLY (This is merely a compile-time optimization for the common case)
     ///
- /// When applying <tt>switch_\<C\></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>C::case_\<E::proto_tag\>()(e, s, d)</tt>.
     template<typename Cases>
- struct switch_ : transform<switch_<Cases> >
+ struct switch_<Cases> : transform<switch_<Cases> >
     {
         typedef switch_ proto_grammar;
 
- /// \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.
- /// \return <tt>which()(e, s, d)</tt>, where <tt>which</tt> is
- /// <tt>Cases::case_<typename Expr::proto_tag></tt>
-
         template<typename Expr, typename State, typename Data>
         struct impl
           : Cases::template case_<typename Expr::proto_tag>::template impl<Expr, State, Data>
@@ -901,8 +934,8 @@
 
     /// INTERNAL ONLY
     ///
- template<typename Cases>
- struct is_callable<switch_<Cases> >
+ template<typename Cases, typename Transform>
+ struct is_callable<switch_<Cases, Transform> >
       : mpl::true_
     {};
 

Modified: trunk/boost/proto/proto_fwd.hpp
==============================================================================
--- trunk/boost/proto/proto_fwd.hpp (original)
+++ trunk/boost/proto/proto_fwd.hpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -269,6 +269,9 @@
 
     using namespace tagns_;
 
+ template<typename Expr>
+ struct tag_of;
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     struct _;
 
@@ -359,7 +362,7 @@
     template<typename Condition, typename Then = _, typename Else = not_<_> >
     struct if_;
 
- template<typename Cases>
+ template<typename Cases, typename Transform = tag_of<_>()>
     struct switch_;
 
     template<typename T>
@@ -462,9 +465,6 @@
     struct is_sub_domain_of;
 
     template<typename Expr>
- struct tag_of;
-
- template<typename Expr>
     struct arity_of;
 
     template<typename T, typename Void = void>

Modified: trunk/boost/proto/transform/default.hpp
==============================================================================
--- trunk/boost/proto/transform/default.hpp (original)
+++ trunk/boost/proto/transform/default.hpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -173,8 +173,8 @@
                 typename uncvref<
                     typename Grammar::template impl<
                         typename result_of::child_c<Expr, 1>::type
- , State
- , Data
+ , State
+ , Data
>::result_type
>::type
>

Modified: trunk/libs/proto/doc/reference/matches.xml
==============================================================================
--- trunk/libs/proto/doc/reference/matches.xml (original)
+++ trunk/libs/proto/doc/reference/matches.xml 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <header name="boost/proto/matches.hpp">
   <para>
     Contains definition of the
@@ -427,25 +427,29 @@
       <struct name="switch_">
         <template>
           <template-type-parameter name="Cases"/>
+ <template-type-parameter name="Transform"/>
         </template>
- <inherit><classname>proto::transform</classname>&lt;switch_&lt;Cases&gt; &gt;</inherit>
- <purpose>For matching one of a set of alternate grammars, which are looked up based on an
- expression's tag type. When used as a transform,
+ <inherit><classname>proto::transform</classname>&lt;switch_&lt;Cases, Transform&gt; &gt;</inherit>
+ <purpose>For matching one of a set of alternate grammars, which are looked up based on
+ the result type of the transform passed in second template parameter.
+ If no transform is passed, the default one is <computeroutput>proto::tag_of()</computeroutput>
+ so the default matching is based on the expression's tag type. When used as a transform,
           <computeroutput>proto::switch_&lt;&gt;</computeroutput> applies the transform associated
           with the sub-grammar that matches the expression.</purpose>
         <description>
- <para>
- An expression type <computeroutput>E</computeroutput> matches
- <computeroutput>proto::switch_&lt;C&gt;</computeroutput> if
- <computeroutput>E</computeroutput> matches
- <computeroutput>C::case_&lt;E::proto_tag&gt;</computeroutput>.
- </para>
- <para>
- When applying <computeroutput>proto::switch_&lt;C&gt;</computeroutput> as a transform
- with an expression <computeroutput>e</computeroutput> of type
- <computeroutput>E</computeroutput>, state <computeroutput>s</computeroutput> and
- data <computeroutput>d</computeroutput>, it is equivalent to
- <computeroutput>C::case_&lt;E::proto_tag&gt;()(e, s, d)</computeroutput>.
+ <para>
+ An expression type <computeroutput>E</computeroutput> matches
+ <computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> if
+ <computeroutput>E</computeroutput> matches
+ <computeroutput>C::case_&lt;boost::result_of&lt;T(E)&gt;::type&gt;</computeroutput>.
+ </para>
+ <para>
+ When applying <computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> as a
+ transform with an expression <computeroutput>e</computeroutput> of type
+ <computeroutput>E</computeroutput>, state <computeroutput>s</computeroutput> of
+ type <computeroutput>S</computeroutput> and data <computeroutput>d</computeroutput>
+ of type <computeroutput>D</computeroutput>, it is equivalent to
+ <computeroutput>C::case_&lt;boost::result_of&lt;T(E,S,D)&gt;::type&gt;()(e, s, d)</computeroutput>.
           </para>
         </description>
         <struct name="impl">
@@ -455,7 +459,10 @@
             <template-type-parameter name="Data"/>
           </template>
           <inherit><type>
- Cases::template case_&lt;typename Expr::tag_type&gt;::template impl&lt;Expr, State, Data&gt;</type></inherit>
+ Cases::template case_&lt;
+ typename <classname>when</classname>&lt;_, Transform&gt;::template impl&lt;Expr, State, Data&gt;::result_type
+ &gt;::template impl&lt;Expr, State, Data&gt;</type>
+ </inherit>
         </struct>
         <typedef name="proto_grammar">
           <type>switch_</type>

Modified: trunk/libs/proto/test/Jamfile.v2
==============================================================================
--- trunk/libs/proto/test/Jamfile.v2 (original)
+++ trunk/libs/proto/test/Jamfile.v2 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -31,6 +31,7 @@
         [ run make_expr.cpp ]
         [ run matches.cpp ]
         [ run flatten.cpp ]
+ [ run switch.cpp ]
         [ run toy_spirit.cpp ]
         [ run toy_spirit2.cpp ]
         [ run make.cpp ]

Added: trunk/libs/proto/test/switch.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/proto/test/switch.cpp 2011-09-22 13:34:21 EDT (Thu, 22 Sep 2011)
@@ -0,0 +1,96 @@
+///////////////////////////////////////////////////////////////////////////////
+// new_switch.cpp
+//
+// Copyright 2011 Eric Niebler
+// Copyright Pierre Esterie & Joel Falcou.
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/bool.hpp>
+
+using namespace boost;
+using namespace proto;
+
+struct MyCases
+{
+ template<typename Tag>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+template<>
+struct MyCases::case_<proto::tag::shift_right>
+ : proto::_
+{};
+
+template<>
+struct MyCases::case_<proto::tag::plus>
+ : proto::_
+{};
+
+struct ArityOf;
+
+struct ArityOfCases
+{
+ template<typename ArityOf>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+
+template<>
+struct ArityOfCases::case_<boost::mpl::long_<1> >
+: boost::proto::when<boost::proto::_, boost::mpl::false_()>
+{};
+
+template<>
+struct ArityOfCases::case_<boost::mpl::long_<2> >
+ : boost::proto::when<boost::proto::_, boost::mpl::true_()>
+{};
+
+struct ArityOf
+ : boost::proto::switch_<
+ ArityOfCases
+ , proto::arity_of<proto::_>()
+ >
+{};
+
+void test_switch()
+{
+ // Tests for backward compatibility
+ assert_matches<proto::switch_<MyCases> >(lit(1) >> 'a');
+ assert_matches<proto::switch_<MyCases> >(lit(1) + 'a');
+ assert_matches_not<proto::switch_<MyCases> >(lit(1) << 'a');
+
+ //Test new matching on the Transform result type
+ ArityOf ar;
+
+ assert_matches_not<ArityOf>(lit(1));
+ assert_matches<ArityOf>(lit(1) + 2);
+ assert_matches<ArityOf>(!lit(1));
+ BOOST_CHECK_EQUAL(ar(!lit(1)), false);
+ BOOST_CHECK_EQUAL(ar(lit(1) + 2), true);
+}
+
+using namespace unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::switch_<>");
+
+ test->add(BOOST_TEST_CASE(&test_switch));
+
+ return test;
+}
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk