[section:concepts Concepts] [heading Expression] _Expr_ is the central concept in _yap_. It must contain at least an _kind_ and a _tuple_ of values. Here is a summary of the requirements on _Expr_. In the tables below, `E` is a type that models _Expr_; `e` is an object of type `E`; `Tuple` is an instantiation of _tuple_; and `t` is an object of type `Tuple`. [table Expression Requirements [[Expression] [Type] [Description] [Notes]] [[`E::kind`] [_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 Expression Requirements [[`E::kind`] [`hana::size(e.elements)`] [Possible Tuple Element Types] [Notes]] [[`expr_kind::expr_ref`] [1] [ Any non-_expr_ref_ _Expr_. ] []] [[`expr_kind::terminal`] [1] [ Any non-_Expr_. ] [A terminal with a _placeholder_ value will be treated as a placeholder. ]] [[Any unary operator] [1] [ Any _Expr_. ] []] [[Any binary operator] [2] [ Any _Expr_. ] []] [[`expr_kind::if_else`] [3] [ Any _Expr_. ] []] [[`expr_kind::call`] [Any number >= 1.] [ Any _Expr_. ] []] ] [heading ExpressionTemplate] _ExprTmpl_ is any template with two parameters that, when instantiated with an _kind_ and a _tuple_, results in an _Expr_. [heading Transform] _xform_ takes a _XForm_ as its second parameter. A _XForm_ is a _Callable_ that takes expressions and returns values of unconstrained type. There are two sorts of overloads _XForm_ may use: _ExprXForm_ and _TagXForm_. A _XForm_ may have any number of overloads, including none. [heading ExpressionTransform] _ExprXForm_ takes an _Expr_ as its only parameter. Here are some examples. This one takes any _Expr_: struct xform { template auto operator() (Expr const & expr) { // ... } }; This one takes any type of _Expr_ that satisfies the constraints imposed by its template parameters: template 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{{0.0}} * number{} + number{}) const & expr ) { // ... } [heading TagTransform] _TagXForm_ 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 _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 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) { // ... } } [endsect]