|
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><switch_<Cases> ></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><switch_<Cases, Transform> ></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_<></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_<C></computeroutput> if
- <computeroutput>E</computeroutput> matches
- <computeroutput>C::case_<E::proto_tag></computeroutput>.
- </para>
- <para>
- When applying <computeroutput>proto::switch_<C></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_<E::proto_tag>()(e, s, d)</computeroutput>.
+ <para>
+ An expression type <computeroutput>E</computeroutput> matches
+ <computeroutput>proto::switch_<C,T></computeroutput> if
+ <computeroutput>E</computeroutput> matches
+ <computeroutput>C::case_<boost::result_of<T(E)>::type></computeroutput>.
+ </para>
+ <para>
+ When applying <computeroutput>proto::switch_<C,T></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_<boost::result_of<T(E,S,D)>::type>()(e, s, d)</computeroutput>.
</para>
</description>
<struct name="impl">
@@ -455,7 +459,10 @@
<template-type-parameter name="Data"/>
</template>
<inherit><type>
- Cases::template case_<typename Expr::tag_type>::template impl<Expr, State, Data></type></inherit>
+ Cases::template case_<
+ typename <classname>when</classname><_, Transform>::template impl<Expr, State, Data>::result_type
+ >::template impl<Expr, State, Data></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