123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- <?xml version="1.0" encoding="utf-8"?>
- <!--
- Copyright 2012 Eric Niebler
- 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)
- -->
- <header name="boost/proto/transform/when.hpp">
- <para>
- Definition of the
- <computeroutput>
- <classname alt="boost::proto::when">proto::when<></classname>
- </computeroutput> and
- <computeroutput>
- <classname alt="boost::proto::otherwise">proto::otherwise<></classname>
- </computeroutput> transforms.
- </para>
- <namespace name="boost">
- <namespace name="proto">
-
- <!-- struct transforms_type -->
- <struct name="transforms_type">
- <purpose>
- The type used to define the global <code><globalname>proto::transforms</globalname></code>,
- a key for use when creating and accessing a slot in a transform environment for
- a set of external transforms.
- </purpose>
- <description>
- <para>
- The <code>proto::transforms_type</code> type, along with the <code><globalname>proto::transforms</globalname></code>
- global, are declared using the <code><macroname>BOOST_PROTO_DEFINE_ENV_VAR</macroname>()</code> macro.
- </para>
- </description>
- <method-group name="public member functions">
- <overloaded-method name="operator=">
- <signature cv="const">
- <template>
- <template-type-parameter name="Value"/>
- </template>
- <type><classname>env</classname><transforms_type, <replaceable>see-below</replaceable>></type>
- <parameter name="value">
- <paramtype>Value &</paramtype>
- </parameter>
- </signature>
- <signature cv="const">
- <template>
- <template-type-parameter name="Value"/>
- </template>
- <type><classname>env</classname><transforms_type, <replaceable>see-below</replaceable>></type>
- <parameter name="value">
- <paramtype>Value const &</paramtype>
- </parameter>
- </signature>
- <description>
- <para>
- If <code>Value</code> is a specialization <code>boost::reference_wrapper<T></code>,
- this function returns <code><classname>env</classname><transforms_type, T &>(value.get())</code>.
- </para>
- <para>
- Else, if the type <code>Value</code> is non-copyable (i.e., a function, an array, abstract, or an ostream),
- this function returns <code><classname>env</classname><transforms_type, Value <replaceable>cv</replaceable> &>(value)</code>,
- where <code><replaceable>cv</replaceable></code> is <code>const</code> for the second overload, and empty
- for the first.
- </para>
- <para>
- Otherwise, this function returns <code><classname>env</classname><transforms_type, Value>(value)</code>.
- </para>
- </description>
- </overloaded-method>
- </method-group>
- </struct>
-
- <data-member name="transforms">
- <description>
- <para>
- A key key for use when creating and accessing a slot in a transform environment for
- a set of external transforms.
- </para>
- </description>
- <type><classname>proto::transforms_type</classname> const</type>
- </data-member>
-
- <struct name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- <template-type-parameter name="PrimitiveTransform">
- <default>Grammar</default>
- </template-type-parameter>
- </template>
- <purpose>A grammar element and a <conceptname>PrimitiveTransform</conceptname> that associates
- a transform with the grammar.</purpose>
- <description>
- <para>
- Use <computeroutput>proto::when<></computeroutput> to override a grammar's default
- transform with a custom transform. It is for used when composing larger transforms by
- associating smaller transforms with individual rules in your grammar, as in the following
- transform which counts the number of terminals in an expression.
- <programlisting>// Count the terminals in an expression tree.
- // Must be invoked with initial state == mpl::int_<0>().
- struct CountLeaves :
- <classname>proto::or_</classname><
- proto::when<<classname>proto::terminal</classname><<classname>proto::_</classname>>, mpl::next<<classname>proto::_state</classname>>()>,
- proto::otherwise<<classname>proto::fold</classname><<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves> >
- >
- {};</programlisting>
- </para>
- <para>
- In <computeroutput>proto::when<G, T></computeroutput>, when <computeroutput>T</computeroutput>
- is a class type it is a <conceptname>PrimitiveTransform</conceptname> and the following equivalencies hold:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <computeroutput>boost::result_of<proto::when<G,T>(E,S,V)>::type</computeroutput> is the same as
- <computeroutput>boost::result_of<T(E,S,V)>::type</computeroutput>.
- </para>
- </listitem>
- <listitem>
- <para>
- <computeroutput>proto::when<G,T>()(e,s,d)</computeroutput> is the same as
- <computeroutput>T()(e,s,d)</computeroutput>.
- </para>
- </listitem>
- </itemizedlist>
- </description>
- <inherit><type>PrimitiveTransform</type></inherit>
- <typedef name="proto_grammar">
- <type>typename Grammar::proto_grammar</type>
- </typedef>
- </struct>
- <struct-specialization name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- <template-type-parameter name="Fun"/>
- </template>
- <specialization>
- <template-arg>Grammar</template-arg>
- <template-arg>Fun *</template-arg>
- </specialization>
- <inherit><type><classname>proto::when</classname>< Grammar, Fun ></type></inherit>
- <purpose>A specialization that treats function pointer <conceptname>Transform</conceptname>s as if they
- were function type <conceptname>Transform</conceptname>s.</purpose>
- <description>
- <para>
- This specialization requires that <computeroutput>Fun</computeroutput> is actually a function type.
- </para>
- <para>
- This specialization is required for nested transforms such as
- <computeroutput>proto::when<G, T0(T1(_))></computeroutput>. In C++, functions that are used
- as parameters to other functions automatically decay to funtion pointer types. In other words, the
- type <computeroutput>T0(T1(_))</computeroutput> is indistinguishable from
- <computeroutput>T0(T1(*)(_))</computeroutput>. This specialization is required to handle these
- nested function pointer type transforms properly.
- </para>
- </description>
- </struct-specialization>
- <struct-specialization name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- <template-type-parameter name="R"/>
- <template-type-parameter name="A" pack="1"/>
- </template>
- <specialization>
- <template-arg>Grammar</template-arg>
- <template-arg>R(A...)</template-arg>
- </specialization>
- <inherit><type><classname>proto::transform</classname>< when<Grammar, R(A...)> ></type></inherit>
- <purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
- transform with the grammar. </purpose>
- <description>
- <para>
- Use <computeroutput>proto::when<></computeroutput> to override a grammar's default
- transform with a custom transform. It is for use when composing larger transforms by associating
- smaller transforms with individual rules in your grammar.
- </para>
- <para>
- The <computeroutput>when<G, R(A...)></computeroutput> form accepts either a
- <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
- second parameter. <computeroutput>proto::when<></computeroutput> uses
- <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput> to
- distinguish between the two, and uses
- <computeroutput><classname>proto::call<></classname></computeroutput> to evaluate
- <conceptname>CallableTransform</conceptname>s and
- <computeroutput><classname>proto::make<></classname></computeroutput> to evaluate
- <conceptname>ObjectTransform</conceptname>s.
- </para>
- </description>
- <struct name="impl">
- <template>
- <template-type-parameter name="Expr"/>
- <template-type-parameter name="State"/>
- <template-type-parameter name="Data"/>
- </template>
- <inherit><type><classname>proto::transform_impl</classname>< Expr, State, Data ></type></inherit>
- <typedef name="call_">
- <purpose>For exposition only</purpose>
- <type><classname>proto::call</classname><R(A...)></type>
- </typedef>
- <typedef name="make_">
- <purpose>For exposition only</purpose>
- <type><classname>proto::make</classname><R(A...)></type>
- </typedef>
- <typedef name="which">
- <purpose>For exposition only</purpose>
- <type>typename mpl::if_<<classname>proto::is_callable</classname><R>,call_,make_>::type</type>
- </typedef>
- <typedef name="result_type">
- <type>typename boost::result_of<which(Expr, State, Data)>::type</type>
- </typedef>
- <method-group name="public member functions">
- <method name="operator()" cv="const">
- <type>result_type</type>
- <parameter name="expr">
- <paramtype>typename impl::expr_param</paramtype>
- <description>
- <para>The current expression </para>
- </description>
- </parameter>
- <parameter name="state">
- <paramtype>typename impl::state_param</paramtype>
- <description>
- <para>The current state </para>
- </description>
- </parameter>
- <parameter name="data">
- <paramtype>typename impl::data_param</paramtype>
- <description>
- <para>An arbitrary data </para>
- </description>
- </parameter>
- <description>
- <para>
- Evaluate <computeroutput>R(A...)</computeroutput> as a transform either with
- <computeroutput><classname>proto::call<></classname></computeroutput> or with
- <computeroutput><classname>proto::make<></classname></computeroutput> depending
- on whether <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput>
- is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
- </para>
- </description>
- <requires>
- <para>
- <computeroutput><classname>proto::matches</classname><Expr, Grammar>::value</computeroutput>
- is <computeroutput>true</computeroutput>.
- </para>
- </requires>
- <returns>
- <para>
- <computeroutput>which()(expr, state, data)</computeroutput>
- </para>
- </returns>
- </method>
- </method-group>
- </struct>
- <typedef name="proto_grammar">
- <type>typename Grammar::proto_grammar</type>
- </typedef>
- </struct-specialization>
- <struct-specialization name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- <template-type-parameter name="R"/>
- <template-type-parameter name="A" pack="1"/>
- </template>
- <specialization>
- <template-arg>Grammar</template-arg>
- <template-arg>R(A..., ...)</template-arg>
- </specialization>
- <inherit><type><classname>proto::transform</classname>< when<Grammar, R(A..., ...)> ></type></inherit>
- <purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
- transform with the grammar. </purpose>
- <description>
- <para>
- Use <computeroutput>proto::when<></computeroutput> to override a grammar's default
- transform with a custom transform. It is for use when composing larger transforms by associating
- smaller transforms with individual rules in your grammar.
- </para>
- <para>
- The <computeroutput>when<G, R(A..., ...)></computeroutput> form accepts either a
- <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
- second parameter. <computeroutput>proto::when<></computeroutput> uses
- <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput> to
- distinguish between the two, and uses
- <computeroutput><classname>proto::call<></classname></computeroutput> to evaluate
- <conceptname>CallableTransform</conceptname>s and
- <computeroutput><classname>proto::make<></classname></computeroutput> to evaluate
- <conceptname>ObjectTransform</conceptname>s.
- </para>
- <para>
- <emphasis role="bold">Note:</emphasis> In the specialization
- <computeroutput>when<G, R(A..., ...)></computeroutput>, the first ellipsis denotes a
- C++11-style variadic template (which is emulated for C++98 compilers). The second ellipsis
- is a C-style vararg.
- </para>
- </description>
- <struct name="impl">
- <template>
- <template-type-parameter name="Expr"/>
- <template-type-parameter name="State"/>
- <template-type-parameter name="Data"/>
- </template>
- <inherit><type><classname>proto::transform_impl</classname>< Expr, State, Data ></type></inherit>
- <typedef name="call_">
- <purpose>For exposition only</purpose>
- <type><classname>proto::call</classname><R(A..., ...)></type>
- </typedef>
- <typedef name="make_">
- <purpose>For exposition only</purpose>
- <type><classname>proto::make</classname><R(A..., ...)></type>
- </typedef>
- <typedef name="which">
- <purpose>For exposition only</purpose>
- <type>typename mpl::if_<<classname>proto::is_callable</classname><R>,call_,make_>::type</type>
- </typedef>
- <typedef name="result_type">
- <type>typename boost::result_of<which(Expr, State, Data)>::type</type>
- </typedef>
- <method-group name="public member functions">
- <method name="operator()" cv="const">
- <type>result_type</type>
- <parameter name="expr">
- <paramtype>typename impl::expr_param</paramtype>
- <description>
- <para>The current expression </para>
- </description>
- </parameter>
- <parameter name="state">
- <paramtype>typename impl::state_param</paramtype>
- <description>
- <para>The current state </para>
- </description>
- </parameter>
- <parameter name="data">
- <paramtype>typename impl::data_param</paramtype>
- <description>
- <para>An arbitrary data </para>
- </description>
- </parameter>
- <description>
- <para>
- Evaluate <computeroutput>R(A..., ...)</computeroutput> as a transform either with
- <computeroutput><classname>proto::call<></classname></computeroutput> or with
- <computeroutput><classname>proto::make<></classname></computeroutput> depending
- on whether <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput>
- is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
- </para>
- </description>
- <requires>
- <para>
- <computeroutput><classname>proto::matches</classname><Expr, Grammar>::value</computeroutput>
- is <computeroutput>true</computeroutput>.
- </para>
- </requires>
- <returns>
- <para>
- <computeroutput>which()(expr, state, data)</computeroutput>
- </para>
- </returns>
- </method>
- </method-group>
- </struct>
- <typedef name="proto_grammar">
- <type>typename Grammar::proto_grammar</type>
- </typedef>
- </struct-specialization>
- <struct-specialization name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- </template>
- <specialization>
- <template-arg>Grammar</template-arg>
- <template-arg><classname>proto::external_transform</classname></template-arg>
- </specialization>
- <inherit><type>
- <classname>proto::transform</classname>< when<Grammar, <classname>proto::external_transform</classname>> ></type></inherit>
- <purpose>A grammar element that associates an externally-specified transform with the grammar.
- The transform is looked up in the Data parameter using the Grammar as a key.</purpose>
- <description>
- <para>
- Use <computeroutput>proto::when<></computeroutput> to override a grammar's default
- transform with a custom transform. It is for use when composing larger transforms by associating
- smaller transforms with individual rules in your grammar.
- </para>
- <para>
- The <computeroutput>when<G, <classname>proto::external_transform</classname>></computeroutput>
- indicates that the associated transform is not yet known. It should be looked up when the transform
- is about to be applied. It is found by looking it up in the passed-in Data parameter, which
- behaves like a compile-time map from grammar types to transform types. The map is indexed using
- <computeroutput>Grammar</computeroutput> as a key. The associated value type is used as the transform
- to apply. In this way, the same grammar can be used to define multiple evaluating strategies that
- can be added post-hoc.
- </para>
- <para>
- See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
- </para>
- </description>
- <struct name="impl">
- <template>
- <template-type-parameter name="Expr"/>
- <template-type-parameter name="State"/>
- <template-type-parameter name="Data"/>
- </template>
- <inherit><type>
- boost::remove_reference<
- typename mpl::eval_if_c<
- <classname>proto::result_of::has_env_var</classname><Data, <classname>proto::transforms_type</classname>>::value,
- <classname>proto::result_of::env_var</classname><Data, <classname>proto::transforms_type</classname>>,
- <classname>proto::result_of::env_var</classname><Data, <classname>proto::data_type</classname>>
- >::type
- >::type
- ::template when< Grammar >
- ::template impl< Expr, State, Data ></type></inherit>
- <description>
- <para>
- The implementation of the <code>impl</code> struct depends on whether the <code>Data</code>
- parameter is a transform environment that contains a value corresponding to the
- <classname>proto::transforms_type</classname> key. If so, that value is treated as a
- map from rules to transforms. Otherwise, the <code>Data</code> type itself is treated
- as such a map.
- </para>
- </description>
- </struct>
- <typedef name="proto_grammar">
- <type>typename Grammar::proto_grammar</type>
- </typedef>
- </struct-specialization>
-
- <struct name="otherwise">
- <template>
- <template-type-parameter name="Fun"/>
- </template>
- <inherit><type><classname>proto::when</classname>< <classname>proto::_</classname>, Fun ></type></inherit>
- <purpose>
- Syntactic sugar for <computeroutput><classname>proto::when</classname>< <classname>proto::_</classname>, Fun ></computeroutput>,
- for use in grammars to handle all the cases not yet handled.
- </purpose>
- <description>
- <para>
- Use <computeroutput>proto::otherwise<T></computeroutput> in your grammars as a synonym for
- <computeroutput><classname>proto::when</classname>< <classname>proto::_</classname>, Fun ></computeroutput>
- as in the following transform which counts the number of terminals in an expression.
- </para>
- <para>
- <programlisting>// Count the terminals in an expression tree.
- // Must be invoked with initial state == mpl::int_<0>().
- struct CountLeaves :
- <classname>proto::or_</classname><
- proto::when<<classname>proto::terminal</classname><<classname>proto::_</classname>>, mpl::next<<classname>proto::_state</classname>>()>,
- proto::otherwise<<classname>proto::fold</classname><<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves> >
- >
- {};</programlisting>
- </para>
- </description>
- </struct>
- <struct name="external_transform">
- <purpose>A placeholder for use as the second parameter for <computeroutput><classname>proto::when</classname></computeroutput>
- to indicate that the rule's transform is specified externally.</purpose>
- <description>
- <para>
- See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
- </para>
- </description>
- </struct>
-
- <struct name="external_transforms">
- <template>
- <template-type-parameter name="When" pack="1"/>
- </template>
- <purpose>A map from grammars to transforms, used as a way to externally associate transforms.</purpose>
- <typedef name="map_type">
- <purpose>For exposition only.</purpose>
- <type>mpl::map< typename to_mpl_pair< When >::type... ></type>
- </typedef>
- <struct name="when">
- <template>
- <template-type-parameter name="Grammar"/>
- </template>
- <inherit><type><classname>proto::otherwise</classname>< typename mpl::at< map_type, Grammar >::type ></type></inherit>
- </struct>
- <description>
- <para>
- It is sometimes desirable to define a grammar that can be customized with different sets of transforms.
- To do that, where you would normally specify a transform within a grammar, you can instead put
- <computeroutput><classname>proto::external_transform</classname></computeroutput>; for example:
- <computeroutput>proto::when< some_grammar, proto::external_transform ></computeroutput>. Then, when
- invoking the grammar, you can pass an approriately-defined instance of <computeroutput>proto::external_transforms</computeroutput>
- as the Data parameter. When an expression matches <computeroutput>some_grammar</computeroutput>, Proto
- will look up the approprite transform in the Data parameter using <computeroutput>some_grammar</computeroutput>
- as a key.
- </para>
- <para>
- <programlisting>struct int_terminal
- : <classname>proto::terminal</classname><int>
- {};
- struct char_terminal
- : <classname>proto::terminal</classname><char>
- {};
- struct my_grammar
- : <classname>proto::or_</classname><
- // The next two grammar rules are customization points.
- // The associated transforms are specified externally
- // using external_transforms below.
- <classname>proto::when</classname>< int_terminal, <classname>proto::external_transform</classname> >
- , <classname>proto::when</classname>< char_terminal, <classname>proto::external_transform</classname> >
- , <classname>proto::when</classname><
- <classname>proto::plus</classname>< my_grammar, my_grammar >
- , <classname>proto::fold</classname>< <classname>proto::_</classname>, int(), my_grammar >
- >
- >
- {};
- // Here is where the transforms are associated with the
- // grammar rules above.
- struct my_transforms
- : proto::external_transforms<
- <classname>proto::when</classname><int_terminal, print(<classname>proto::_value</classname>)>
- , <classname>proto::when</classname><char_terminal, print(<classname>proto::_value</classname>)>
- >
- {};
- // ...
- <classname>proto::literal</classname><int> i(1);
- <classname>proto::literal</classname><char> c('a');
- my_transforms trx;
- // Evaluate "i+c" using my_grammar with the specified transforms:
- my_grammar()(i + c, 0, trx);
- // If you would also like to pass arbitrary data along with the
- // transforms, you can use a transform environment, as so:
- my_grammar()(i + c, 0, (proto::data = 42, proto::transforms = trx));</programlisting>
- </para>
- </description>
- </struct>
- </namespace>
- </namespace>
- </header>
|