Ticket #5905: new_switch.2.patch

File new_switch.2.patch, 12.1 KB (added by Pierre Esterie <pesterie@…>, 11 years ago)
  • boost/proto/proto_fwd.hpp

     
    269269
    270270    using namespace tagns_;
    271271
     272    template<typename Expr>
     273    struct tag_of;
     274
    272275    ////////////////////////////////////////////////////////////////////////////////////////////////
    273276    struct _;
    274277
     
    359362    template<typename Condition, typename Then = _, typename Else = not_<_> >
    360363    struct if_;
    361364
    362     template<typename Cases>
     365    template<typename Cases, typename Transform = tag_of<_>() >
    363366    struct switch_;
    364367
    365368    template<typename T>
     
    462465    struct is_sub_domain_of;
    463466
    464467    template<typename Expr>
    465     struct tag_of;
    466 
    467     template<typename Expr>
    468468    struct arity_of;
    469469
    470470    template<typename T, typename Void = void>
     
    741741    template<typename Grammar>
    742742    struct pass_through;
    743743
    744     template<typename Grammar = detail::_default>
     744    template<typename Grammar = detail::_default >
    745745    struct _default;
    746746
    747747    struct _expr;
  • boost/proto/matches.hpp

     
    1010#ifndef BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006
    1111#define BOOST_PROTO_MATCHES_HPP_EAN_11_03_2006
    1212
     13
    1314#include <boost/config.hpp>
    1415#include <boost/detail/workaround.hpp>
    1516#include <boost/preprocessor/cat.hpp>
     
    402403        {};
    403404
    404405        // handle proto::switch_
    405         template<typename Expr, typename Tag, typename Args, long Arity, typename Cases>
    406         struct matches_<Expr, proto::basic_expr<Tag, Args, Arity>, switch_<Cases> >
    407           : matches_<
    408                 Expr
    409               , proto::basic_expr<Tag, Args, Arity>
    410               , typename Cases::template case_<Tag>::proto_grammar
    411             >
     406        template< typename Expr, typename Tag, typename Args, long Arity, typename Cases, typename Transform>
     407        struct matches_ < Expr, proto::basic_expr<Tag, Args, Arity>, switch_<Cases,Transform> >
     408          : matches_< Expr, proto::basic_expr<Tag, Args, Arity>
     409                    , typename Cases::template case_<typename
     410                      when<_,Transform>::template impl<Expr,int,int>::result_type
     411                          >::proto_grammar
     412                    >
    412413        {
     414            typedef when<_,Transform> applicant;
     415            typedef typename applicant::template impl<Expr,int,int>::result_type selected_type;
     416            typedef typename Cases::template case_<selected_type> which;
     417        };
     418
     419        template< typename Expr, typename Tag, typename Args, long Arity, typename Cases >
     420        struct matches_ < Expr, proto::basic_expr<Tag, Args, Arity> , switch_<Cases> >
     421          : matches_< Expr, proto::basic_expr<Tag, Args, Arity>
     422                    , typename  Cases::template
     423                      case_<Tag>::proto_grammar
     424                    >
     425        {
    413426            typedef typename Cases::template case_<Tag> which;
    414427        };
    415428    }
     
    449462    ///     not match \c T.
    450463    /// \li An expression \c E matches <tt>switch_\<C\></tt> if
    451464    ///     \c E matches <tt>C::case_\<E::proto_tag\></tt>.
     465    /// \li An expression \c E matches <tt>switch_\<C,T\></tt> if
     466    ///     the result type of the transform \c T on \c E matches
     467    ///     <tt>C::case_\<boost::result_of\<T(E)\>::type\></tt>.
    452468    ///
    453469    /// A terminal expression <tt>expr\<AT,term\<A\> \></tt> matches
    454470    /// a grammar <tt>expr\<BT,term\<B\> \></tt> if \c BT is \c AT or
     
    784800    /// When applying <tt>switch_\<C\></tt> as a transform with an
    785801    /// expression \c e of type \c E, state \c s and data \c d, it is
    786802    /// equivalent to <tt>C::case_\<E::proto_tag\>()(e, s, d)</tt>.
    787     template<typename Cases>
    788     struct switch_ : transform<switch_<Cases> >
     803    template<typename Cases, typename Transform>
     804    struct switch_ : transform< switch_<Cases,Transform> >
    789805    {
    790806        typedef switch_ proto_grammar;
     807        typedef when<_,Transform> applicant;
    791808
    792809        /// \param e An expression
    793810        /// \param s The current state
    794811        /// \param d A data of arbitrary type
    795812        /// \pre <tt>matches\<Expr,switch_\>::value</tt> is \c true.
    796813        /// \return <tt>which()(e, s, d)</tt>, where <tt>which</tt> is
    797         /// <tt>Cases::case_<typename Expr::proto_tag></tt>
     814        /// <tt>Cases::case_< typename boost::result_of< Transform(Expr) >::type ></tt>
    798815
    799816        template<typename Expr, typename State, typename Data>
    800817        struct impl
    801           : Cases::template case_<typename Expr::proto_tag>::template impl<Expr, State, Data>
     818        : Cases::template
     819            case_ < typename applicant::template impl<Expr,State,Data>::result_type
     820            >::template impl<Expr, State, Data>
    802821        {};
    803822
    804823        template<typename Expr, typename State, typename Data>
    805824        struct impl<Expr &, State, Data>
    806           : Cases::template case_<typename Expr::proto_tag>::template impl<Expr &, State, Data>
     825        : Cases::template
     826            case_ <typename applicant::template impl<Expr,State,Data>::result_type
     827            >::template impl<Expr &, State, Data>
    807828        {};
    808829    };
    809830
     
    901922
    902923    /// INTERNAL ONLY
    903924    ///
    904     template<typename Cases>
    905     struct is_callable<switch_<Cases> >
     925    template<typename Cases, typename Transform>
     926    struct is_callable<switch_<Cases,Transform> >
    906927      : mpl::true_
    907928    {};
    908929
  • libs/proto/test/new_switch.cpp

     
     1///////////////////////////////////////////////////////////////////////////////
     2// new_switch.cpp
     3//
     4//  Copyright 2011 Eric Niebler
     5//  Copyright Pierre Esterie & Joel Falcou.
     6//  Distributed under the Boost
     7//  Software License, Version 1.0. (See accompanying file
     8//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
     9
     10#include <boost/proto/core.hpp>
     11#include <boost/proto/transform.hpp>
     12#include <boost/detail/workaround.hpp>
     13#include <boost/proto/debug.hpp>
     14#include <boost/test/unit_test.hpp>
     15#include <boost/mpl/long.hpp>
     16#include <boost/mpl/bool.hpp>
     17
     18using namespace boost;
     19using namespace proto;
     20
     21struct MyCases
     22{
     23    template<typename Tag>
     24    struct case_
     25    : proto::not_<proto::_>
     26    {};
     27};
     28
     29template<>
     30struct MyCases::case_<proto::tag::shift_right>
     31: proto::_
     32{};
     33
     34template<>
     35struct MyCases::case_<proto::tag::plus>
     36: proto::_
     37{};
     38
     39struct ArityOf;
     40
     41struct ArityOfCases
     42{
     43    template<typename ArityOf>
     44    struct  case_
     45    :  proto::not_<proto::_> {};
     46};
     47
     48
     49template<>
     50struct  ArityOfCases::case_< boost::mpl::long_<1> >
     51: boost::proto::when<boost::proto::_,boost::mpl::false_() >
     52{};
     53
     54template<>
     55struct  ArityOfCases::case_< boost::mpl::long_<2> >
     56: boost::proto::when<boost::proto::_, boost::mpl::true_() >
     57{};
     58
     59struct ArityOf
     60: boost::proto::switch_ < ArityOfCases
     61                        , proto::arity_of<proto::_>()
     62                        >
     63{};
     64
     65void test_switch()
     66{
     67    // Tests for backward compatibility
     68    assert_matches< proto::switch_<MyCases> >( lit(1) >> 'a' );
     69    assert_matches< proto::switch_<MyCases> >( lit(1) + 'a' );
     70    assert_matches_not< proto::switch_<MyCases> >( lit(1) << 'a' );
     71
     72    //Test new matching on the Transform result type
     73    ArityOf ar;
     74
     75    assert_matches_not< ArityOf >( lit(1) );
     76    assert_matches< ArityOf >( lit(1) + 2 );
     77    assert_matches< ArityOf >( !lit(1));
     78    BOOST_CHECK_EQUAL( ar( !lit(1) ), false);
     79    BOOST_CHECK_EQUAL( ar( lit(1) + 2 ), true);
     80}
     81
     82using namespace unit_test;
     83///////////////////////////////////////////////////////////////////////////////
     84// init_unit_test_suite
     85//
     86test_suite* init_unit_test_suite( int argc, char* argv[] )
     87{
     88    test_suite *test = BOOST_TEST_SUITE("test proto::switch_<>");
     89
     90    test->add(BOOST_TEST_CASE(&test_switch));
     91
     92    return test;
     93}
     94
  • libs/proto/test/Jamfile.v2

     
    3131        [ run make_expr.cpp ]
    3232        [ run matches.cpp ]
    3333        [ run flatten.cpp ]
     34        [ run new_switch.cpp ]
    3435        [ run toy_spirit.cpp ]
    3536        [ run toy_spirit2.cpp ]
    3637        [ run make.cpp ]
  • libs/proto/doc/reference/matches.xml

     
    1 <?xml version="1.0" encoding="utf-8"?>
     1<?xml version="1.0" encoding="utf-8"?>
    22<header name="boost/proto/matches.hpp">
    33  <para>
    44    Contains definition of the
     
    427427      <struct name="switch_">
    428428        <template>
    429429          <template-type-parameter name="Cases"/>
     430          <template-type-parameter name="Transform"/>
    430431        </template>
    431         <inherit><classname>proto::transform</classname>&lt;switch_&lt;Cases&gt; &gt;</inherit>
    432         <purpose>For matching one of a set of alternate grammars, which are looked up based on an
    433           expression's tag type. When used as a transform,
     432        <inherit><classname>proto::transform</classname>&lt;switch_&lt;Cases, Transform&gt; &gt;</inherit>
     433        <purpose>For matching one of a set of alternate grammars, which are looked up based on
     434          the result type of the transform passed in second template parameter.
     435          If no transform is passed, the default one is <computeroutput>proto::tag_of()</computeroutput>
     436          so the default matching is based on the expression's tag type. When used as a transform,
    434437          <computeroutput>proto::switch_&lt;&gt;</computeroutput> applies the transform associated
    435438          with the sub-grammar that matches the expression.</purpose>
    436439        <description>
     
    439442            <computeroutput>proto::switch_&lt;C&gt;</computeroutput> if
    440443            <computeroutput>E</computeroutput> matches
    441444            <computeroutput>C::case_&lt;E::proto_tag&gt;</computeroutput>.
     445          </para>
     446          <para>
     447            An expression type <computeroutput>E</computeroutput> matches
     448            <computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> if
     449            the result type of the transform <computeroutput>T</computeroutput>
     450            on <computeroutput>E</computeroutput> matches
     451            <computeroutput>C::case_&lt;boost::result_of&lt;T(E)&gt; &gt;</computeroutput>.
    442452          </para>
    443453          <para>
    444454            When applying <computeroutput>proto::switch_&lt;C&gt;</computeroutput> as a transform
     
    446456            <computeroutput>E</computeroutput>, state <computeroutput>s</computeroutput> and
    447457            data <computeroutput>d</computeroutput>, it is equivalent to
    448458            <computeroutput>C::case_&lt;E::proto_tag&gt;()(e, s, d)</computeroutput>.
     459          </para>
     460          <para>
     461            When applying <computeroutput>proto::switch_&lt;C,T&gt;</computeroutput> as a transform
     462            with an expression <computeroutput>e</computeroutput> of type
     463            <computeroutput>E</computeroutput>, state <computeroutput>s</computeroutput> and
     464            data <computeroutput>d</computeroutput>, it is equivalent to
     465            <computeroutput>C::case_&lt;boost::result_of&lt;T(E)&gt; &gt;()(e, s, d)</computeroutput>.
    449466          </para>
    450467        </description>
    451468        <struct name="impl">
     
    455472            <template-type-parameter name="Data"/>
    456473          </template>
    457474          <inherit><type>
    458     Cases::template case_&lt;typename Expr::tag_type&gt;::template impl&lt;Expr, State, Data&gt;</type></inherit>
     475  Cases::template case_&lt; typename applicant::template impl&lt;Expr, State, Data&gt;::result_type
     476                       &gt;::template impl&lt;Expr, State, Data&gt;</type>
     477          </inherit>
    459478        </struct>
    460479        <typedef name="proto_grammar">
    461480          <type>switch_</type>
    462481        </typedef>
     482        <typedef name="applicant">
     483          <type>when&lt;_, Transform&gt;</type>
     484        </typedef>
    463485      </struct>
    464486
    465487      <!-- proto::exact -->