Definition of the ``proto::when<>`` and ``proto::otherwise<>`` transforms.

The type used to define the global `proto::transforms`, a key for use when creating and accessing a slot in a transform environment for a set of external transforms.

The `proto::transforms_type` type, along with the `proto::transforms` global, are declared using the `BOOST_PROTO_DEFINE_ENV_VAR()` macro.

`env`<transforms_type, see-below> `Value &`
`env`<transforms_type, see-below> `Value const &`

If `Value` is a specialization `boost::reference_wrapper<T>`, this function returns ``env`<transforms_type, T &>(value.get())`.

Else, if the type `Value` is non-copyable (i.e., a function, an array, abstract, or an ostream), this function returns ``env`<transforms_type, Value cv &>(value)`, where `cv` is `const` for the second overload, and empty for the first.

Otherwise, this function returns ``env`<transforms_type, Value>(value)`.

A key key for use when creating and accessing a slot in a transform environment for a set of external transforms.

`proto::transforms_type` const
Grammar
A grammar element and a PrimitiveTransform that associates a transform with the grammar.

Use `proto::when<>` 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.

    // Count the terminals in an expression tree.
    // Must be invoked with initial state == mpl::int_<0>().
    struct CountLeaves :
      proto::or_<
        proto::when<proto::terminal<proto::_>, mpl::next<proto::_state>()>,
        proto::otherwise<proto::fold<proto::_, proto::_state, CountLeaves> >
      >
    {};

In `proto::when<G, T>`, when `T` is a class type it is a PrimitiveTransform and the following equivalencies hold:

- `boost::result_of<proto::when<G,T>(E,S,V)>::type` is the same as `boost::result_of<T(E,S,V)>::type`.

- `proto::when<G,T>()(e,s,d)` is the same as `T()(e,s,d)`.

PrimitiveTransform
typename Grammar::proto_grammar
Grammar
Fun *
`proto::when`< Grammar, Fun >
A specialization that treats function pointer Transforms as if they were function type Transforms.

This specialization requires that `Fun` is actually a function type.

This specialization is required for nested transforms such as `proto::when<G, T0(T1(_))>`. In C++, functions that are used as parameters to other functions automatically decay to funtion pointer types. In other words, the type `T0(T1(_))` is indistinguishable from `T0(T1(*)(_))`. This specialization is required to handle these nested function pointer type transforms properly.

Grammar
R(A...)
`proto::transform`< when<Grammar, R(A...)> >
A grammar element and a Transform that associates a transform with the grammar.

Use `proto::when<>` 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.

The `when<G, R(A...)>` form accepts either a CallableTransform or an ObjectTransform as its second parameter. `proto::when<>` uses ``proto::is_callable`<R>::value` to distinguish between the two, and uses ``proto::call<>`` to evaluate CallableTransforms and ``proto::make<>`` to evaluate ObjectTransforms.

`proto::transform_impl`< Expr, State, Data >
For exposition only
`proto::call`<R(A...)>
For exposition only
`proto::make`<R(A...)>
For exposition only
typename mpl::if_<`proto::is_callable`<R>,call_,make_>::type
typename boost::result_of<which(Expr, State, Data)>::type
result_type `typename impl::expr_param

The current expression

` `typename impl::state_param

The current state

` `typename impl::data_param

An arbitrary data

`

Evaluate `R(A...)` as a transform either with ``proto::call<>`` or with ``proto::make<>`` depending on whether ``proto::is_callable`<R>::value` is `true` or `false`.

``proto::matches`<Expr, Grammar>::value` is `true`.

`which()(expr, state, data)`

typename Grammar::proto_grammar
Grammar
R(A..., ...)
`proto::transform`< when<Grammar, R(A..., ...)> >
A grammar element and a Transform that associates a transform with the grammar.

Use `proto::when<>` 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.

The `when<G, R(A..., ...)>` form accepts either a CallableTransform or an ObjectTransform as its second parameter. `proto::when<>` uses ``proto::is_callable`<R>::value` to distinguish between the two, and uses ``proto::call<>`` to evaluate CallableTransforms and ``proto::make<>`` to evaluate ObjectTransforms.

Note: In the specialization `when<G, R(A..., ...)>`, 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.

`proto::transform_impl`< Expr, State, Data >
For exposition only
`proto::call`<R(A..., ...)>
For exposition only
`proto::make`<R(A..., ...)>
For exposition only
typename mpl::if_<`proto::is_callable`<R>,call_,make_>::type
typename boost::result_of<which(Expr, State, Data)>::type
result_type `typename impl::expr_param

The current expression

` `typename impl::state_param

The current state

` `typename impl::data_param

An arbitrary data

`

Evaluate `R(A..., ...)` as a transform either with ``proto::call<>`` or with ``proto::make<>`` depending on whether ``proto::is_callable`<R>::value` is `true` or `false`.

``proto::matches`<Expr, Grammar>::value` is `true`.

`which()(expr, state, data)`

typename Grammar::proto_grammar
Grammar
proto::external_transform
`proto::transform`< when<Grammar, `proto::external_transform`> >
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.

Use `proto::when<>` 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.

The `when<G, `proto::external_transform`>` 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 `Grammar` 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.

See ``proto::external_transforms`` for an example.

boost::remove_reference< typename mpl::eval_if_c< `proto::result_of::has_env_var`<Data, `proto::transforms_type`>::value, `proto::result_of::env_var`<Data, `proto::transforms_type`>, `proto::result_of::env_var`<Data, `proto::data_type`> >::type >::type ::template when< Grammar > ::template impl< Expr, State, Data >

The implementation of the `impl` struct depends on whether the `Data` parameter is a transform environment that contains a value corresponding to the `proto::transforms_type` key. If so, that value is treated as a map from rules to transforms. Otherwise, the `Data` type itself is treated as such a map.

typename Grammar::proto_grammar
`proto::when`< `proto::_`, Fun >
Syntactic sugar for ``proto::when`< `proto::_`, Fun >`, for use in grammars to handle all the cases not yet handled.

Use `proto::otherwise<T>` in your grammars as a synonym for ``proto::when`< `proto::_`, Fun >` as in the following transform which counts the number of terminals in an expression.

    // Count the terminals in an expression tree.
    // Must be invoked with initial state == mpl::int_<0>().
    struct CountLeaves :
      proto::or_<
        proto::when<proto::terminal<proto::_>, mpl::next<proto::_state>()>,
        proto::otherwise<proto::fold<proto::_, proto::_state, CountLeaves> >
      >
    {};

A placeholder for use as the second parameter for ``proto::when`` to indicate that the rule's transform is specified externally.

See ``proto::external_transforms`` for an example.

A map from grammars to transforms, used as a way to externally associate transforms.
For exposition only.
mpl::map< typename to_mpl_pair< When >::type... >
`proto::otherwise`< typename mpl::at< map_type, Grammar >::type >

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 ``proto::external_transform``; for example: `proto::when< some_grammar, proto::external_transform >`. Then, when invoking the grammar, you can pass an approriately-defined instance of `proto::external_transforms` as the Data parameter. When an expression matches `some_grammar`, Proto will look up the approprite transform in the Data parameter using `some_grammar` as a key.

    struct int_terminal
      : proto::terminal<int>
    {};

    struct char_terminal
      : proto::terminal<char>
    {};

    struct my_grammar
      : proto::or_<
            // The next two grammar rules are customization points.
            // The associated transforms are specified externally
            // using external_transforms below.
            proto::when< int_terminal, proto::external_transform >
          , proto::when< char_terminal, proto::external_transform >
          , proto::when<
                proto::plus< my_grammar, my_grammar >
              , proto::fold< proto::_, int(), my_grammar >
            >
        >
    {};

    // Here is where the transforms are associated with the
    // grammar rules above.
    struct my_transforms
      : proto::external_transforms<
            proto::when<int_terminal, print(proto::_value)>
          , proto::when<char_terminal, print(proto::_value)>
        >
    {};

    // ...

    proto::literal<int> i(1);
    proto::literal<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));