| Home | Libraries | People | FAQ | More

## Concepts

#### Expression

Expression is the central concept in Boost.YAP. It must contain at least an `expr_kind` and a `boost::hana::tuple<>` of values.

Here is a summary of the requirements on Expression. In the tables below, `E` is a type that models Expression; `e` is an object of type `E`; `Tuple` is an instantiation of `boost::hana::tuple<>`; and `t` is an object of type `Tuple`.

Table 47.6. Expression Requirements

Expression | Type | Description | Notes
--- | --- | --- | ---
`E::kind` | `expr_kind` | The kind of expression `E` is. | Must be a compile-time constant.
`e.elements` | `Tuple` | The child expressions of `e`. | The types of the elements must be appropriate to the kind of the expression.
`E e{t}` |  | Construction/initialization of `e`. | `t` must be stored in `e.elements`.

As stated above, the `elements` data member must match the kind of the expression:

Table 47.7. Expression Requirements

`E::kind` | `hana::size(e.elements)` | Possible Tuple Element Types | Notes
--- | --- | --- | ---
`expr_kind::expr_ref` | 1 | Any non-`expr_kind::expr_ref` Expression. |
`expr_kind::terminal` | 1 | Any non-Expression. | A terminal with a `placeholder<>` value will be treated as a placeholder.
Any unary operator | 1 | Any Expression. |
Any binary operator | 2 | Any Expression. |
`expr_kind::if_else` | 3 | Any Expression. |
`expr_kind::call` | Any number >= 1. | Any Expression. |

#### ExpressionTemplate

ExpressionTemplate is any template with two parameters that, when instantiated with an `expr_kind` and a `boost::hana::tuple<>`, results in an Expression.

#### Transform

`transform()` takes a Transform as its second parameter. A Transform is a Callable that takes expressions and returns values of unconstrained type. There are two sorts of overloads Transform may use: ExpressionTransform and TagTransform.

A Transform may have any number of overloads, including none.

#### ExpressionTransform

ExpressionTransform takes an Expression as its only parameter. Here are some examples.

This one takes any Expression:

    struct xform
    {
        template <typename Expr>
        auto operator() (Expr const & expr)
        {
            // ...
        }
    };

This one takes any type of Expression that satisfies the constraints imposed by its template parameters:

    template <typename Expr1, typename Expr2, typename Expr3>
    decltype(auto) xform (
        boost::yap::expression<
            boost::yap::expr_kind::plus,
            boost::hana::tuple<
                boost::yap::expression<
                    boost::yap::expr_kind::multiplies,
                    boost::hana::tuple<
                        Expr1,
                        Expr2
                    >
                >,
                Expr3
            >
        > const & expr
    ) {
        // ...
    }

This one takes only a specific type:

    decltype(auto) xform (
        decltype(term<number>{{0.0}} * number{} + number{}) const & expr
    ) {
        // ...
    }

#### TagTransform

TagTransform takes a tag-type as its first parameter, and the individual elements of an expression as the remaining parameters.

Tags are named such that the tag for an expression with `expr_kind` `expr_kind::foo` is named `foo_tag`. Here are some examples.

This one takes any terminal that contains a `user::number` (or reference to such a terminal):

    struct xform
    {
        decltype(auto) operator() (boost::yap::terminal_tag, user::number const & n)
        {
            // ...
        }
    };

This one takes any plus expression that contains a pair of `user::number` terminals (or references to terminals):

    decltype(auto) xform (boost::yap::plus_tag, user::number lhs, user::number rhs)
    {
        // ...
    }

This one takes any negation expression:

    struct xform
    {
        template <typename Expr>
        decltype(auto) operator() (boost::yap::negate_tag, Expr const & expr)
        {
            // ...
        }
    };

This one takes any call expression with two terminals (or references to terminals) containing values convertible to `double`:

    struct xform
    {
        decltype(auto) operator() (boost::yap::call_tag, tag_type, double a, double b)
        {
            // ...
        }
    }