|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r49369 - trunk/libs/proto/doc
From: eric_at_[hidden]
Date: 2008-10-16 22:48:47
Author: eric_niebler
Date: 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
New Revision: 49369
URL: http://svn.boost.org/trac/boost/changeset/49369
Log:
reorged docs
Added:
trunk/libs/proto/doc/back_end.qbk (contents, props changed)
trunk/libs/proto/doc/front_end.qbk (contents, props changed)
trunk/libs/proto/doc/intermediate_form.qbk (contents, props changed)
Removed:
trunk/libs/proto/doc/construction.qbk
trunk/libs/proto/doc/evaluation.qbk
trunk/libs/proto/doc/extensibility.qbk
trunk/libs/proto/doc/grammars.qbk
trunk/libs/proto/doc/transforms.qbk
Text files modified:
trunk/libs/proto/doc/calculator.qbk | 48 ++++++++--------------
trunk/libs/proto/doc/installation.qbk | 15 ++++++
trunk/libs/proto/doc/proto.qbk | 85 +++++++++++++++++++--------------------
3 files changed, 71 insertions(+), 77 deletions(-)
Added: trunk/libs/proto/doc/back_end.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/proto/doc/back_end.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,1568 @@
+[/
+ / Copyright (c) 2007 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)
+ /]
+
+[/================================================================================]
+[section:back_end Back Ends:
+ Making Expression Templates Do Useful Work]
+[/================================================================================]
+
+[section:expression_evaluation Expression Evaluation: Imparting Behaviors With A Context]
+
+Once you have constructed a Proto expression tree, either by using Proto's
+operator overloads or with _make_expr_ and friends, you probably want to
+actually /do/ something with it. The simplest option is to use `proto::eval()`,
+a generic expression evaluator. To use _eval_, you'll need to define a
+/context/ that tells _eval_ how each node should be evaluated. This section
+goes through the nuts and bolts of using _eval_, defining evaluation contexts,
+and using the contexts that Proto provides.
+
+[note `proto::eval()` is a less powerful but easier-to-use evaluation technique
+than Proto transforms, which are covered later. Although very powerful,
+transforms have a steep learning curve and can be more difficult to debug.
+`proto::eval()` is a rather weak tree traversal algorithm. Dan Marsden has
+been working on a more general and powerful tree traversal library. When it is
+ready, I anticipate that it will eliminate the need for `proto::eval()`.]
+
+[/================================================================]
+[section:proto_eval Evaluating An Expression with [^proto::eval()]]
+[/================================================================]
+
+[:[*Synopsis:]]
+
+ namespace proto
+ {
+ namespace result_of
+ {
+ // A metafunction for calculating the return
+ // type of proto::eval() given certain Expr
+ // and Context types.
+ template<typename Expr, typename Context>
+ struct eval
+ {
+ typedef
+ typename Context::template eval<Expr>::result_type
+ type;
+ };
+ }
+
+ namespace functional
+ {
+ // A callable function object type for evaluating
+ // a Proto expression with a certain context.
+ struct eval : callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename Expr, typename Context>
+ typename proto::result_of::eval<Expr, Context>::type
+ operator ()(Expr &expr, Context &context) const;
+
+ template<typename Expr, typename Context>
+ typename proto::result_of::eval<Expr, Context>::type
+ operator ()(Expr &expr, Context const &context) const;
+ };
+ }
+
+ template<typename Expr, typename Context>
+ typename proto::result_of::eval<Expr, Context>::type
+ eval(Expr &expr, Context &context);
+
+ template<typename Expr, typename Context>
+ typename proto::result_of::eval<Expr, Context>::type
+ eval(Expr &expr, Context const &context);
+ }
+
+Given an expression and an evaluation context, using _eval_ is quite simple.
+Simply pass the expression and the context to _eval_ and it does the rest and
+returns the result. You can use the `eval<>` metafunction in the
+`proto::result_of` namespace to compute the return type of _eval_. The
+following demonstrates a use of _eval_:
+
+ template<typename Expr>
+ typename proto::result_of::eval<Expr const, MyContext>::type
+ MyEvaluate(Expr const &expr)
+ {
+ // Some user-defined context type
+ MyContext ctx;
+
+ // Evaluate an expression with the context
+ return proto::eval(expr, ctx);
+ }
+
+What _eval_ does is also very simple. It defers most of the work to the
+context itself. Here essentially is the implementation of _eval_:
+
+ // eval() dispatches to a nested "eval<>" function
+ // object within the Context:
+ template<typename Expr, typename Context>
+ typename Context::template eval<Expr>::result_type
+ eval(Expr &expr, Context &ctx)
+ {
+ typename Context::template eval<Expr> eval_fun;
+ return eval_fun(expr, ctx);
+ }
+
+Really, _eval_ is nothing more than a thin wrapper that dispatches to the
+appropriate handler within the context class. In the next section, we'll see
+how to implement a context class from scratch.
+
+[endsect]
+
+[/==============================================]
+[section:contexts Defining an Evaluation Context]
+[/==============================================]
+
+As we saw in the previous section, there is really not much to the _eval_
+function. Rather, all the interesting expression evaluation goes on within
+a context class. This sections shows how to implement one from scratch.
+
+All context classes have roughly the following form:
+
+ // A prototypical user-defined context.
+ struct MyContext
+ {
+ // A nested eval<> class template
+ template<
+ typename Expr
+ , typename Tag = typename proto::tag_of<Expr>::type
+ >
+ struct eval;
+
+ // Handle terminal nodes here...
+ template<typename Expr>
+ struct eval<Expr, proto::tag::terminal>
+ {
+ // Must have a nested result_type typedef.
+ typedef ... result_type;
+
+ // Must have a function call operator that takes
+ // an expression and the context.
+ result_type operator()(Expr &expr, MyContext &ctx) const
+ {
+ return ...;
+ }
+ };
+
+ // ... other specializations of struct eval<> ...
+ };
+
+Context classes are nothing more than a collection of specializations of a
+nested `eval<>` class template. Each specialization handles a different
+expression type.
+
+In the [link boost_proto.users_guide.hello_calculator Hello Calculator]
+section, we saw an example of a user-defined context class for evaluating
+calculator expressions. That context class was implemented with the help
+of Proto's _callable_context_. If we were to implement it from scratch, it
+would look something like this:
+
+ // The calculator_contest from the "Hello Calculator" section,
+ // implemented from scratch.
+ struct calculator_context
+ {
+ // The values with which we'll replace the placeholders
+ std::vector<double> args;
+
+ template<
+ typename Expr
+ // defaulted template parameters, so we can
+ // specialize on the expressions that need
+ // special handling.
+ , typename Tag = typename proto::tag_of<Expr>::type
+ , typename Arg0 = typename proto::child_c<Expr, 0>::type
+ >
+ struct eval;
+
+ // Handle placeholder terminals here...
+ template<typename Expr, int I>
+ struct eval<Expr, proto::tag::terminal, placeholder<I> >
+ {
+ typedef double result_type;
+
+ result_type operator()(Expr &, MyContext &ctx) const
+ {
+ return ctx.args[I];
+ }
+ };
+
+ // Handle other terminals here...
+ template<typename Expr, typename Arg0>
+ struct eval<Expr, proto::tag::terminal, Arg0>
+ {
+ typedef double result_type;
+
+ result_type operator()(Expr &expr, MyContext &) const
+ {
+ return proto::child(expr);
+ }
+ };
+
+ // Handle addition here...
+ template<typename Expr, typename Arg0>
+ struct eval<Expr, proto::tag::plus, Arg0>
+ {
+ typedef double result_type;
+
+ result_type operator()(Expr &expr, MyContext &ctx) const
+ {
+ return proto::eval(proto::left(expr), ctx)
+ + proto::eval(proto::right(expr), ctx);
+ }
+ };
+
+ // ... other eval<> specializations for other node types ...
+ };
+
+Now we can use _eval_ with the context class above to evaluate calculator
+expressions as follows:
+
+ // Evaluate an expression with a calculator_context
+ calculator_context ctx;
+ ctx.args.push_back(5);
+ ctx.args.push_back(6);
+ double d = proto::eval(_1 + _2, ctx);
+ assert(11 == d);
+
+Defining a context from scratch this way is tedious and verbose, but it gives
+you complete control over how the expression is evaluated. The context class in
+the [link boost_proto.users_guide.hello_calculator Hello Calculator] example
+was much simpler. In the next section we'll see the helper class Proto provides
+to ease the job of implementing context classes.
+
+[endsect]
+
+[/======================================]
+[section:canned_contexts Canned Contexts]
+[/======================================]
+
+Proto provides some ready-made context classes that you can use as-is, or that
+you can use to help while implementing your own contexts. They are:
+
+[variablelist
+ [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.default_context [^default_context]]]
+ [An evaluation context that assigns the usual C++ meanings to all the
+ operators. For example, addition nodes are handled by evaluating the
+ left and right children and then adding the results. The _default_context_
+ uses Boost.Typeof to deduce the types of the expressions it evaluates.] ]
+ [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.null_context [^null_context]]]
+ [A simple context that recursively evaluates children but does not combine
+ the results in any way and returns void.] ]
+ [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.callable_context [^callable_context<>]]]
+ [A helper that simplifies the job of writing context classes. Rather than
+ writing template specializations, with _callable_context_ you write a
+ function object with an overloaded function call operator. Any expressions
+ not handled by an overload are automatically dispatched to a default
+ evaluation context that you can specify.] ]
+]
+
+[/=========================================]
+[section:default_context [^default_context]]
+[/=========================================]
+
+The _default_context_ is an evaluation context that assigns the usual C++
+meanings to all the operators. For example, addition nodes are handled by
+evaluating the left and right children and then adding the results. The
+_default_context_ uses Boost.Typeof to deduce the types of the expressions it
+evaluates.
+
+For example, consider the following "Hello World" example:
+
+ #include <iostream>
+ #include <boost/proto/proto.hpp>
+ #include <boost/proto/context.hpp>
+ #include <boost/typeof/std/ostream.hpp>
+ using namespace boost;
+
+ proto::terminal< std::ostream & >::type cout_ = { std::cout };
+
+ template< typename Expr >
+ void evaluate( Expr const & expr )
+ {
+ // Evaluate the expression with default_context,
+ // to give the operators their C++ meanings:
+ proto::default_context ctx;
+ proto::eval(expr, ctx);
+ }
+
+ int main()
+ {
+ evaluate( cout_ << "hello" << ',' << " world" );
+ return 0;
+ }
+
+This program outputs the following:
+
+[pre
+hello, world
+]
+
+_default_context_ is trivially defined in terms of a `default_eval<>`
+template, as follows:
+
+ // Definition of default_context
+ struct default_context
+ {
+ template<typename Expr>
+ struct eval
+ : default_eval<
+ Expr
+ , default_context const
+ , typename tag_of<Expr>::type
+ >
+ {};
+ };
+
+There are a bunch of `default_eval<>` specializations, each of which handles
+a different C++ operator. Here, for instance, is the specialization for binary
+addition:
+
+ // A default expression evaluator for binary addition
+ template<typename Expr, typename Context>
+ struct default_eval<Expr, Context, proto::tag::plus>
+ {
+ private:
+ static Expr & s_expr;
+ static Context & s_ctx;
+
+ public:
+ typedef
+ decltype(
+ proto::eval(proto::child_c<0>(s_expr), s_ctx)
+ + proto::eval(proto::child_c<1>(s_expr), s_ctx)
+ )
+ result_type;
+
+ result_type operator ()(Expr &expr, Context &ctx) const
+ {
+ return proto::eval(proto::child_c<0>(expr), ctx)
+ + proto::eval(proto::child_c<1>(expr), ctx);
+ }
+ };
+
+The above code uses `decltype` to calculate the return type of the function
+call operator. `decltype` is a new keyword in the next version of C++ that gets
+the type of any expression. Most compilers do not yet support `decltype`
+directly, so `default_eval<>` uses the Boost.Typeof library to emulate it. On
+some compilers, that may mean that `default_context` either doesn't work or
+that it requires you to register your types with the Boost.Typeof library.
+Check the documentation for Boost.Typeof to see.
+
+[endsect]
+
+[/===================================]
+[section:null_context [^null_context]]
+[/===================================]
+
+The _null_context_ is a simple context that recursively evaluates children
+but does not combine the results in any way and returns void. It is useful
+in conjunction with `callable_context<>`, or when defining your own contexts
+which mutate an expression tree in-place rather than accumulate a result, as
+we'll see below.
+
+_null_context_ is trivially implemented in terms of `null_eval<>` as follows:
+
+ // Definition of null_context
+ struct null_context
+ {
+ template<typename Expr>
+ struct eval
+ : null_eval<Expr, null_context const, Expr::proto_arity::value>
+ {};
+ };
+
+And `null_eval<>` is also trivially implemented. Here, for instance is
+a binary `null_eval<>`:
+
+ // Binary null_eval<>
+ template<typename Expr, typename Context>
+ struct null_eval<Expr, Context, 2>
+ {
+ typedef void result_type;
+
+ void operator()(Expr &expr, Context &ctx) const
+ {
+ proto::eval(proto::child_c<0>(expr), ctx);
+ proto::eval(proto::child_c<1>(expr), ctx);
+ }
+ };
+
+When would such classes be useful? Imagine you have an expression tree with
+integer terminals, and you would like to increment each integer in-place. You
+might define an evaluation context as follows:
+
+ struct increment_ints
+ {
+ // By default, just evaluate all children by defering
+ // to the null_eval<>
+ template<typename Expr, typename Arg = proto::result_of::child<Expr>::type>
+ struct eval
+ : null_eval<Expr, increment_ints const>
+ {};
+
+ // Increment integer terminals
+ template<typename Expr>
+ struct eval<Expr, int>
+ {
+ typedef void result_type;
+
+ void operator()(Expr &expr, increment_ints const &) const
+ {
+ ++proto::child(expr);
+ }
+ };
+ };
+
+In the next section on _callable_context_, we'll see an even simpler way to
+achieve the same thing.
+
+[endsect]
+
+[/=============================================]
+[section:callable_context [^callable_context<>]]
+[/=============================================]
+
+The _callable_context_ is a helper that simplifies the job of writing context
+classes. Rather than writing template specializations, with _callable_context_
+you write a function object with an overloaded function call operator. Any
+expressions not handled by an overload are automatically dispatched to a
+default evaluation context that you can specify.
+
+Rather than an evaluation context in its own right, _callable_context_ is more
+properly thought of as a context adaptor. To use it, you must define your own
+context that inherits from _callable_context_.
+
+In the [link boost_proto.users_guide.expression_evaluation.canned_contexts.null_context [^null_context]]
+section, we saw how to implement an evaluation context that increments all the
+integers within an expression tree. Here is how to do the same thing with the
+_callable_context_:
+
+ // An evaluation context that increments all
+ // integer terminals in-place.
+ struct increment_ints
+ : callable_context<
+ increment_ints const // derived context
+ , null_context const // fall-back context
+ >
+ {
+ typedef void result_type;
+
+ // Handle int terminals here:
+ void operator()(proto::tag::terminal, int &i) const
+ {
+ ++i;
+ }
+ };
+
+With such a context, we can do the following:
+
+ literal<int> i = 0, j = 10;
+ proto::eval( i - j * 3.14, increment_ints() );
+
+ std::cout << "i = " << i.get() << std::endl;
+ std::cout << "j = " << j.get() << std::endl;
+
+This program outputs the following, which shows that the integers `i` and `j`
+have been incremented by `1`:
+
+[pre
+i = 1
+j = 11
+]
+
+In the `increment_ints` context, we didn't have to define any nested `eval<>`
+templates. That's because _callable_context_ implements them for us.
+_callable_context_ takes two template parameters: the derived context and a
+fall-back context. For each node in the expression tree being evaluated,
+_callable_context_ checks to see if there is an overloaded `operator()` in the
+derived context that accepts it. Given some expression `expr` of type `Expr`,
+and a context `ctx`, it attempts to call:
+
+ ctx(
+ typename Expr::proto_tag()
+ , proto::child_c<0>(expr)
+ , proto::child_c<1>(expr)
+ ...
+ );
+
+Using function overloading and metaprogramming tricks, _callable_context_ can
+detect at compile-time whether such a function exists or not. If so, that
+function is called. If not, the current expression is passed to the fall-back
+evaluation context to be processed.
+
+We saw another example of the _callable_context_ when we looked at the simple
+calculator expression evaluator. There, we wanted to customize the evaluation
+of placeholder terminals, and delegate the handling of all other nodes to the
+_default_context_. We did that as follows:
+
+ // An evaluation context for calculator expressions that
+ // explicitly handles placeholder terminals, but defers the
+ // processing of all other nodes to the default_context.
+ struct calculator_context
+ : proto::callable_context< calculator_context const >
+ {
+ std::vector<double> args;
+
+ // Define the result type of the calculator.
+ typedef double result_type;
+
+ // Handle the placeholders:
+ template<int I>
+ double operator()(proto::tag::terminal, placeholder<I>) const
+ {
+ return this->args[I];
+ }
+ };
+
+In this case, we didn't specify a fall-back context. In that case,
+_callable_context_ uses the _default_context_. With the above
+`calculator_context` and a couple of appropriately defined placeholder
+terminals, we can evaluate calculator expressions, as demonstrated
+below:
+
+ template<int I>
+ struct placeholder
+ {};
+
+ terminal<placeholder<0> >::type const _1 = {{}};
+ terminal<placeholder<1> >::type const _2 = {{}};
+ // ...
+
+ calculator_context ctx;
+ ctx.args.push_back(4);
+ ctx.args.push_back(5);
+
+ double j = proto::eval( (_2 - _1) / _2 * 100, ctx );
+ std::cout << "j = " << j << std::endl;
+
+The above code displays the following:
+
+[pre
+j = 20
+]
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+[import ../test/examples.cpp]
+
+[/============================================================================]
+[section:expression_transformation Expression Transformation: Semantic Actions]
+[/============================================================================]
+
+If you have ever built a parser with the help of a tool like Antlr, yacc or Boost.Spirit, you might be familiar with /semantic actions/. In addition to allowing you to define the grammar of the language recognized by the parser, these tools let you embed code within your grammar that executes when parts of the grammar participate in a parse. Proto has the equivalent of semantic actions. They are called /transforms/. This section describes how to embed transforms within your Proto grammars, turning your grammars into function objects that can manipulate or evaluate expressions in powerful ways.
+
+Proto transforms are an advanced topic. We'll take it slow, using examples to illustrate the key concepts, starting simple.
+
+[/==================================]
+[section ["Activating] Your Grammars]
+[/==================================]
+
+The Proto grammars we've seen so far are static. You can check at compile-time to see if an expression type matches a grammar, but that's it. Things get more interesting when you give them runtime behaviors. A grammar with embedded transforms is more than just a static grammar. It is a function object that accepts expressions that match the grammar and does /something/ with them.
+
+Below is a very simple grammar. It matches terminal expressions.
+
+ // A simple Proto grammar that matches all terminals
+ proto::terminal< _ >
+
+Here is the same grammar with a transform that extracts the value from the terminal:
+
+ // A simple Proto grammar that matches all terminals
+ // *and* a function object that extracts the value from
+ // the terminal
+ proto::when<
+ proto::terminal< _ >
+ , proto::_value // <-- Look, a transform!
+ >
+
+You can read this as follows: when you match a terminal expression, extract the value. The type `proto::_value` is a so-called transform. Later we'll see what makes it a transform, but for now just think of it as a kind of function object. Note the use of _when_: the first template parameter is the grammar to match and the second is the transform to execute. The result is both a grammar that matches terminal expressions and a function object that accepts terminal expressions and extracts their values.
+
+As with ordinary grammars, we can define an empty struct that inherits from a grammar+transform to give us an easy way to refer back to the thing we're defining, as follows:
+
+ // A grammar and a function object, as before
+ struct Value
+ : proto::when<
+ proto::terminal< _ >
+ , proto::_value
+ >
+ {};
+
+ // "Value" is a grammar that matches terminal expressions
+ BOOST_MPL_ASSERT(( proto::matches< proto::terminal<int>::type, Value > ));
+
+ // "Value" also defines a function object that accepts terminals
+ // and extracts their value.
+ proto::terminal<int>::type answer = {42};
+ Value get_value;
+ int i = get_value( answer );
+
+As already mentioned, `Value` is a grammar that matches terminal expressions and a function object that operates on terminal expressions. It would be an error to pass a non-terminal expression to the `Value` function object. This is a general property of grammars with transforms; when using them as function objects, expressions passed to them must match the grammar.
+
+Proto grammars are valid TR1-style function objects. That means you can use `boost::result_of<>` to ask a grammar what its return type will be, given a particular expression type. For instance, we can access the `Value` grammar's return type as follows:
+
+ // We can use boost::result_of<> to get the return type
+ // of a Proto grammar.
+ typedef
+ typename boost::result_of<Value(proto::terminal<int>::type)>::type
+ result_type;
+
+ // Check that we got the type we expected
+ BOOST_MPL_ASSERT(( boost::is_same<result_type, int> ));
+
+[note A grammar with embedded transforms is both a grammar and a function object. Calling these things "grammars with transforms" would get tedious. We could call them something like "active grammars", but as we'll see /every/ grammar that you can define with Proto is "active"; that is, every grammar has some behavior when used as a function object. So we'll continue calling these things plain "grammars". The term "transform" is reserved for the thing that is used as the second parameter to the _when_ template.]
+
+[endsect]
+
+[/=========================================]
+[section Handling Alternation and Recursion]
+[/=========================================]
+
+Most grammars are a little more complicated than the one in the preceeding section. For the sake of illustration, let's define a rather nonsensical grammar that matches any expression and recurses to the leftmost terminal and returns its value. It will demonstrate how two key concepts of Proto grammars -- alternation and recursion -- interact with transforms. The grammar is described below.
+
+ // A grammar that matches any expression, and a function object
+ // that returns the value of the leftmost terminal.
+ struct LeftmostLeaf
+ : proto::or_<
+ // If the expression is a terminal, return its value
+ proto::when<
+ proto::terminal< _ >
+ , proto::_value
+ >
+ // Otherwise, it is a non-terminal. Return the result
+ // of invoking LeftmostLeaf on the 0th (leftmost) child.
+ , proto::when<
+ _
+ , LeftmostLeaf( proto::_child0 )
+ >
+ >
+ {};
+
+ // A Proto terminal wrapping std::cout
+ proto::terminal< std::ostream & >::type cout_ = { std::cout };
+
+ // Create an expression and use LeftmostLeaf to extract the
+ // value of the leftmost terminal, which will be std::cout.
+ std::ostream & sout = LeftmostLeaf()( cout_ << "the answer: " << 42 << '\n' );
+
+We've seen `proto::or_<>` before. Here it is serving two roles. First, it is a grammar that matches any of its alternate sub-grammars; in this case, either a terminal or a non-terminal. Second, it is also a function object that accepts an expression, finds the alternate sub-grammar that matches the expression, and applies its transform. And since `LeftmostLeaf` inherits from `proto::or_<>`, `LeftmostLeaf` is also both a grammar and a function object.
+
+[def _some_transform_ [~some-transform]]
+
+[note The second alternate uses `proto::_` as its grammar. Recall that `proto::_` is the wildcard grammar that matches any expression. Since alternates in `proto::or_<>` are tried in order, and since the first alternate handles all terminals, the second alternate handles all (and only) non-terminals. Often enough, `proto::when< _, _some_transform_ >` is the last alternate in a grammar, so for improved readability, you could use the equivalent `proto::otherwise< _some_transform_ >`.]
+
+The next section describes this grammar further.
+
+[endsect]
+
+[/==========================]
+[section Callable Transforms]
+[/==========================]
+
+[def __bold_transform__ [*LeftmostLeaf( proto::_child0 )]]
+
+In the grammar defined in the preceeding section, the transform associated with non-terminals is a little strange-looking:
+
+ proto::when<
+ _
+ , __bold_transform__ // <-- a "callable" transform
+ >
+
+It has the effect of accepting non-terminal expressions, taking the 0th (leftmost) child and recursively invoking the `LeftmostLeaf` function on it. But `LeftmostLeaf( proto::_child0 )` is actually a /function type/. Literally, it is the type of a function that accepts an object of type `proto::_child0` and returns an object of type `LeftmostLeaf`. So how do we make sense of this transform? Clearly, there is no function that actually has this signature, nor would such a function be useful. The key is in understanding how `proto::when<>` /interprets/ its second template parameter.
+
+When the second template parameter to _when_ is a function type, _when_ interprets the function type as a transform. In this case, `LeftmostLeaf` is treated as the type of a function object to invoke, and `proto::_child0` is treated as a transform. First, `proto::_child0` is applied to the current expression (the non-terminal that matched this alternate sub-grammar), and the result (the 0th child) is passed as an argument to `LeftmostLeaf`.
+
+[note *Transforms are a Domain-Specific Language*
+
+`LeftmostLeaf( proto::_child0 )` /looks/ like an invocation of the `LeftmostLeaf` function object, but it's not, but then it actually is! Why this confusing subterfuge? Function types give us a natural and concise syntax for composing more complicated transforms from simpler ones. The fact that the syntax is suggestive of a function invocation is on purpose. It is a domain-specific embedded language for defining expression transformations. If the subterfuge worked, it may have fooled you into thinking the transform is doing exactly what it actually does! And that's the point.]
+
+The type `LeftmostLeaf( proto::_child0 )` is an example of a /callable transform/. It is a function type that represents a function object to call and its arguments. The types `proto::_child0` and `proto::_value` are /primitive transforms/. They are plain structs, not unlike function objects, from which callable transforms can be composed. There is one other type of transform, /object transforms/, that we'll encounter next.
+
+[endsect]
+
+[/========================]
+[section Object Transforms]
+[/========================]
+
+The very first transform we looked at simply extracted the value of terminals. Let's do the same thing, but this time we'll promote all ints to longs first. (Please forgive the contrived-ness of the examples so far; they get more interesting later.) Here's the grammar:
+
+ // A simple Proto grammar that matches all terminals,
+ // and a function object that extracts the value from
+ // the terminal, promoting ints to longs:
+ struct ValueWithPomote
+ : proto::or_<
+ proto::when<
+ proto::terminal< int >
+ , long(proto::_value) // <-- an "object" transform
+ >
+ , proto::when<
+ proto::terminal< _ >
+ , proto::_value
+ >
+ >
+ {};
+
+You can read the above grammar as follows: when you match an int terminal, extract the value from the terminal and use it to initialize a long; otherwise, when you match another kind of terminal, just extract the value. The type `long(proto::_value)` is a so-called /object/ transform. It looks like the creation of a temporary long, but it's really a function type. Just as a callable transform is a function type that represents a function to call and its arguments, an object transforms is a function type that represents an object to construct and the arguments to its constructor.
+
+[/================================================]
+[note *Object Transforms vs. Callable Transforms*
+
+When using function types as Proto transforms, they can either represent an object to construct or a function to call. It is similar to "normal" C++ where the syntax `foo("arg")` can either be interpreted as an object to construct or a function to call, depending on whether `foo` is a type or a function. But consider two of the transforms we've seen so far:
+
+``
+ LeftmostLeaf(proto::_child0) // <-- a callable transform
+ long(proto::_value) // <-- an object transform
+``
+
+Proto can't know in general which is which, so it uses a trait, `proto::is_callable<>`, to differentiate. `is_callable< long >::value` is false so `long(proto::_value)` is an object to construct, but `is_callable< LeftmostLeaf >::value` is true so `LeftmostLeaf(proto::_child0)` is a function to call. Later on, we'll see how Proto recognizes a type as "callable".]
+[/================================================]
+
+[endsect]
+
+[/================================]
+[section Example: Calculator Arity]
+[/================================]
+
+Now that we have the basics of Proto transforms down, let's consider a slightly more realistic example. We can use transforms to improve the type-safety of the [link boost_proto.users_guide.getting_started.hello_calculator calculator DSEL]. If you recall, it lets you write infix arithmetic expressions involving argument placeholders like `_1` and `_2` and pass them to STL algorithms as function objects, as follows:
+
+ double a1[4] = { 56, 84, 37, 69 };
+ double a2[4] = { 65, 120, 60, 70 };
+ double a3[4] = { 0 };
+
+ // Use std::transform() and a calculator expression
+ // to calculate percentages given two input sequences:
+ std::transform(a1, a1+4, a2, a3, (_2 - _1) / _2 * 100);
+
+This works because we gave calculator expressions an `operator()` that evaluates the expression, replacing the placeholders with the arguments to `operator()`. The overloaded `calculator<>::operator()` looked like this:
+
+ // Overload operator() to invoke proto::eval() with
+ // our calculator_context.
+ template<typename Expr>
+ double
+ calculator<Expr>::operator()(double a1 = 0, double a2 = 0) const
+ {
+ calculator_context ctx;
+ ctx.args.push_back(a1);
+ ctx.args.push_back(a2);
+
+ return proto::eval(*this, ctx);
+ }
+
+Although this works, it's not ideal because it doesn't warn users if they supply too many or too few arguments to a calculator expression. Consider the following mistakes:
+
+ (_1 * _1)(4, 2); // Oops, too many arguments!
+ (_2 * _2)(42); // Oops, too few arguments!
+
+The expression `_1 * _1` defines a unary calculator expression; it takes one argument and squares it. If we pass more than one argument, the extra arguments will be silently ignored, which might be surprising to users. The next expression, `_2 * _2` defines a binary calculator expression; it takes two arguments, ignores the first and squares the second. If we only pass one argument, the code silently fills in `0.0` for the second argument, which is also probably not what users expect. What can be done?
+
+We can say that the /arity/ of a calculator expression is the number of arguments it expects, and it is equal to the largest placeholder in the expression. So, the arity of `_1 * _1` is one, and the arity of `_2 * _2` is two. We can increase the type-safety of our calculator DSEL by making sure the artiy of an expression equals the actual number of arguments supplied. Computing the artiy of an expression is simple with the help of Proto transforms.
+
+It's straightforward to describe in words how the arity of an expression should
+be calculated. Consider that calculator expressions can be made of `_1`, `_2`, literals, unary expressions and binary expressions. The following table shows the arities for each of these 5 constituents.
+
+[table Calculator Sub-Expression Arities
+ [[Sub-Expression] [Arity]]
+ [[Placeholder 1] [`1`]]
+ [[Placeholder 2] [`2`]]
+ [[Literal] [`0`]]
+ [[Unary Expression] [ /arity of the operand/ ]]
+ [[Binary Expression] [ /max arity of the two operands/ ]]
+]
+
+Using this information, we can write the grammar for calculator expressions and attach transforms for computing the arity of each constituent. The code below computes the expression arity as a compile-time integer, using integral wrappers and metafunctions from the Boost MPL Library. The grammar is described below.
+
+[CalcArity]
+
+When we find a placeholder terminal or a literal, we use an /object transform/ such as `mpl::int_<1>()` to create a (default-constructed) compile-time integer representing the arity of that terminal.
+
+For unary expressions, we use `CalcArity(proto::_child)` which is a /callable transform/ that computes the arity of the expression's child.
+
+The transform for binary expressions has a few new tricks. Let's look more closely:
+
+ // Compute the left and right arities and
+ // take the larger of the two.
+ mpl::max<CalcArity(proto::_left),
+ CalcArity(proto::_right)>()
+
+This is an object transform; it default-constructs ... what exactly? The `mpl::max<>` template is an MPL metafunction that accepts two compile-time integers. It has a nested `::type` typedef (not shown) that is the maximum of the two. But here, we appear to be passing it two things that are /not/ compile-time integers; they're Proto callable transforms. Proto is smart enough to recognize that fact. It first evaluates the two nested callable transforms, computing the arities of the left and right child expressions. Then it puts the resulting integers into `mpl::max<>` and evaluates the metafunction by asking for the nested `::type`. That is the type of the object that gets default-constructed and returned.
+
+More generally, when evaluating object transforms, Proto looks at the object type and checks whether it is a template specialization, like `mpl::max<>`. If it is, Proto looks for nested transforms that it can evaluate. After any nested transforms have been evaluated and substituted back into the template, the new template specialization is the result type, unless that type has a nested `::type`, in which case that becomes the result.
+
+Now that we can calculate the arity of a calculator expression, let's redefine the `calculator<>` expression wrapper we wrote in the Getting Started guide to use the `CalcArity` grammar and some macros from Boost.MPL to issue compile-time errors when users specify too many or too few arguments.
+
+ // The calculator expression wrapper, as defined in the Hello
+ // Calculator example in the Getting Started guide. It behaves
+ // just like the expression it wraps, but with extra operator()
+ // member functions that evaluate the expression.
+ // NEW: Use the CalcArity grammar to ensure that the correct
+ // number of arguments are supplied.
+ template<typename Expr>
+ struct calculator
+ : proto::extends<Expr, calculator<Expr>, calculator_domain>
+ {
+ typedef
+ proto::extends<Expr, calculator<Expr>, calculator_domain>
+ base_type;
+
+ calculator(Expr const &expr = Expr())
+ : base_type(expr)
+ {}
+
+ typedef double result_type;
+
+ // Use CalcArity to compute the arity of Expr:
+ static int const arity = boost::result_of<CalcArity(Expr)>::type::value;
+
+ double operator()() const
+ {
+ BOOST_MPL_ASSERT_RELATION(0, ==, arity);
+ calculator_context ctx;
+ return proto::eval(*this, ctx);
+ }
+
+ double operator()(double a1) const
+ {
+ BOOST_MPL_ASSERT_RELATION(1, ==, arity);
+ calculator_context ctx;
+ ctx.args.push_back(a1);
+ return proto::eval(*this, ctx);
+ }
+
+ double operator()(double a1, double a2) const
+ {
+ BOOST_MPL_ASSERT_RELATION(2, ==, arity);
+ calculator_context ctx;
+ ctx.args.push_back(a1);
+ ctx.args.push_back(a2);
+ return proto::eval(*this, ctx);
+ }
+ };
+
+Note the use of `boost::result_of<>` to access the return type of the `CalcArity` function object. Since we used compile-time integers in our transforms, the arity of the expression is encoded in the return type of the `CalcArity` function object. Proto grammars are valid TR1-style function objects, so you can use `boost::result_of<>` to figure out their return types.
+
+With our compile-time assertions in place, when users provide too many or too few arguments to a calculator expression, as in:
+
+ (_2 * _2)(42); // Oops, too few arguments!
+
+... they will get a compile-time error message on the line with the assertion that reads something like this[footnote This error message was generated with Microsoft Visual C++ 9.0. Different compilers will emit different messages with varying degrees of readability.]:
+
+[pre
+c:\boost\org\trunk\libs\proto\scratch\main.cpp(97) : error C2664: 'boost::mpl::asse
+rtion\_failed' : cannot convert parameter 1 from 'boost::mpl::failed \*\*\*\*\*\*\*\*\*\*\*\*boo
+st::mpl::assert\_relation<x,y,\_\_formal>::\*\*\*\*\*\*\*\*\*\*\*\*' to 'boost::mpl::assert<false>
+::type'
+ with
+ \[
+ x\=1,
+ y\=2,
+ \_\_formal\=bool boost::mpl::operator\=\=(boost::mpl::failed,boost::mpl::failed)
+ \]
+]
+
+The point of this exercise was to show that we can write a fairly simple Proto grammar with embedded transforms that is declarative and readable and can compute interesting properties of arbitrarily complicated expressions. But transforms can do more than that. Boost.Xpressive uses transforms to turn expressions into finite state automata for matching regular expressions, and Boost.Spirit uses transforms to build recursive descent parser generators. Proto comes with a collection of built-in transforms that you can use to perform very sophisticated expression manipulations like these. In the next few sections we'll see some of them in action.
+
+[endsect]
+
+[/===============================================]
+[section:state Transforms With State Accumulation]
+[/===============================================]
+
+So far, we've only seen examples of grammars with transforms that accept one argument: the expression to transform. But consider for a moment how, in ordinary procedural code, you would turn a binary tree into a linked list. You would start with an empty list. Then, you would recursively convert the right branch to a list, and use the result as the initial state while converting the left branch to a list. That is, you would need a function that takes two parameters: the current node and the list so far. These sorts of /accumulation/ problems are quite common when processing trees. The linked list is an example of an accumulation variable or /state/. Each iteration of the algorithm takes the current element and state, applies some binary function to the two and creates a new state. In the STL, this algorithm is called `std::accumulate()`. In many other languages, it is called /fold/. Let's see how to implement a fold algorithm with Proto transforms.
+
+All Proto grammars can optionally accept a state parameter in addition to the expression to transform. If you want to fold a tree to a list, you'll need to make use of the state parameter to pass around the list you've built so far. As for the list, the Boost.Fusion library provides a `fusion::cons<>` type from which you can build heterogenous lists. The type `fusion::nil` represents an empty list.
+
+Below is a grammar that recognizes output expressions like `cout_ << 42 << '\n'` and puts the arguments into a Fusion list. It is explained below.
+
+ // Fold the terminals in output statements like
+ // "cout_ << 42 << '\n'" into a Fusion cons-list.
+ struct FoldToList
+ : proto::or_<
+ // Don't add the ostream terminal to the list
+ proto::when<
+ proto::terminal< std::ostream & >
+ , proto::_state
+ >
+ // Put all other terminals at the head of the
+ // list that we're building in the "state" parameter
+ , proto::when<
+ proto::terminal<_>
+ , fusion::cons<proto::_value, proto::_state>(
+ proto::_value, proto::_state
+ )
+ >
+ // For left-shift operations, first fold the right
+ // child to a list using the current state. Use
+ // the result as the state parameter when folding
+ // the left child to a list.
+ , proto::when<
+ proto::shift_left<FoldToList, FoldToList>
+ , FoldToList(
+ proto::_left
+ , FoldToList(proto::_right, proto::_state)
+ )
+ >
+ >
+ {};
+
+Before reading on, see if you can apply what you know already about object, callable and primitive transforms to figure out how this grammar works.
+
+When you use the `FoldToList` function, you'll need to pass two arguments: the expression to fold, and the initial state: an empty list. Those two arguments get passed around to each transform. We learned previously that `proto::_value` is a primitive transform that accepts a terminal expression and extracts its value. What we didn't know until now was that it also accepts the current state /and ignores it/. `proto::_state` is also a primitive transform. It accepts the current expression, which it ignores, and the current state, which it returns.
+
+When we find a terminal, we stick it at the head of the cons list, using the current state as the tail of the list. (The first alternate causes the `ostream` to be skipped. We don't want `cout` in the list.) When we find a shift-left node, we apply the following transform:
+
+ // Fold the right child and use the result as
+ // state while folding the right.
+ FoldToList(
+ proto::_left
+ , FoldToList(proto::_right, proto::_state)
+ )
+
+You can read this transform as follows: using the current state, fold the right child to a list. Use the new list as the state while folding the left child to a list.
+
+[tip If your compiler is Microsoft Visual C++, you'll find that the above transform does not compile. The compiler has bugs with its handling of nested function types. You can work around the bug by wrapping the inner transform in `proto::call<>` as follows:
+
+``
+ FoldToList(
+ proto::_left
+ , proto::call<FoldToList(proto::_right, proto::_state)>
+ )
+``
+
+`proto::call<>` turns a callable transform into a primitive transform, but more on that later.
+]
+
+Now that we have defined the `FoldToList` function object, we can use it to turn output expressions into lists as follows:
+
+ proto::terminal<std::ostream &>::type const cout_ = {std::cout};
+
+ // This is the type of the list we build below
+ typedef
+ fusion::cons<
+ int
+ , fusion::cons<
+ double
+ , fusion::cons<
+ char
+ , fusion::nil
+ >
+ >
+ >
+ result_type;
+
+ // Fold an output expression into a Fusion list, using
+ // fusion::nil as the initial state of the transformation.
+ FoldToList to_list;
+ result_type args = to_list(cout_ << 1 << 3.14 << '\n', fusion::nil());
+
+ // Now "args" is the list: {1, 3.14, '\n'}
+
+When writing transforms, "fold" is such a basic operation that Proto provides a number of built-in fold transforms. We'll get to them later. For now, rest assured that you won't always have to strech your brain so far to do such basic things.
+
+[endsect]
+
+[/================================================]
+[section:data Passing Auxiliary Data To Transforms]
+[/================================================]
+
+In the last section, we saw that we can pass a second parameter to grammars with transforms: an accumulation variable or /state/ that gets updated as your transform executes. There are times when your transforms will need to access auxiliary data that does /not/ accumulate, so bundling it with the state parameter is impractical. Instead, you can pass auxiliary data as a third parameter, known as the /data/ parameter. Below we show an example involving string processing where the data parameter is essential.
+
+[note All Proto grammars are function objects that take one, two or three arguments: the expression, the state, and the data. There are no additional arguments to know about, we promise. In Haskell, there is set of a tree traversal technologies known collectively as _SYB_. In that framework, there are also three parameters: the term, the accumulator, and the context. These are Proto's expression, state and data parameters under different names.]
+
+Expression templates are often used as an optimization to eliminate temporary objects. Condsier the problem of string concatenation: a series of concatenations would result in the needless creation of temporary strings. We can use Proto to make string concatenation very efficient. To make the problem more interesting, we can apply a locale-sensitive transformation to each character during the concatenation. The locale information will be passed as the data parameter.
+
+Consider the following expression template:
+
+ proto::lit("hello") + " " + "world";
+
+We would like to concatenate this string into a statically allocated wide character buffer, widening each charater in turn using the specified locale. The first step is to write a grammar that describes this expression, with transforms that calculate the total string length. Here it is:
+
+ // A grammar that matches string concatenation expressions, and
+ // a transform that calculates the total string length.
+ struct StringLength
+ : proto::or_<
+ proto::when<
+ // When you find a character array ...
+ proto::terminal<char[proto::N]>
+ // ... the length is the size of the array minus 1.
+ , mpl::prior<mpl::sizeof_<proto::_value> >()
+ >
+ , proto::when<
+ // The length of a concatenated string is ...
+ proto::plus<StringLength, StringLength>
+ // ... the sum of the lengths of each sub-string.
+ , proto::fold<
+ _
+ , mpl::size_t<0>()
+ , mpl::plus<StringLength, proto::_state>()
+ >
+ >
+ >
+ {};
+
+Notice the use of _fold_pt_. It is a primitive transform that takes a sequence, a state, and function, just like `std::accumulate()`. The three template parameters are transforms. The first yields the sequence of expressions over which to fold, the second yields the initial state of the fold, and the third is the function to apply at each iteration. The use of `proto::_` as the first parameter might have you confused. In addition to being Proto's wildcard, `proto::_` is also a primitive transform that returns the current expression, which (if it is a non-terminal) is a sequence of its child expressions.
+
+Next, we need a function object that accepts a narrow string, a wide character buffer, and a `std::ctype<>` facet for doing the locale-specific stuff. It's fairly straightforward.
+
+ // A function object that writes a narrow string
+ // into a wide buffer.
+ struct WidenCopy : proto::callable
+ {
+ typedef wchar_t *result_type;
+
+ wchar_t *
+ operator()(char const *str, wchar_t *buf, std::ctype<char> const &ct) const
+ {
+ for(; *str; ++str, ++buf)
+ *buf = ct.widen(*str);
+ return buf;
+ }
+ };
+
+Finally, we need some transforms that actually walk the concatenated string expression, widens the characters and writes them to a buffer. We will pass a `wchar_t*` as the state parameter and update it as we go. We'll also pass the `std::ctype<>` facet as the data parameter. It looks like this:
+
+ // Write concatenated strings into a buffer, widening
+ // them as we go.
+ struct StringCopy
+ : proto::or_<
+ proto::when<
+ proto::terminal<char[proto::N]>
+ , WidenCopy(proto::_value, proto::_state, proto::_data)
+ >
+ , proto::when<
+ proto::plus<StringCopy, StringCopy>
+ , StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+ >
+ >
+ {};
+
+Let's look more closely at the transform associated with non-terminals:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+
+This bears a resemblance to the transform in the previous section that folded an expression tree into a list. First we recurse on the left child, writing its strings into the `wchar_t*` passed in as the state parameter. That returns the new value of the `wchar_t*`, which is passed as state while transforming the right child. Both invocations receive the same `std::ctype<>`, which is passed in as the data parameter.
+
+With these pieces in our pocket, we can implement our concatenate-and-widen function as follows:
+
+ template<typename Expr>
+ void widen( Expr const &expr )
+ {
+ // Make sure the expression conforms to our grammar
+ BOOST_MPL_ASSERT(( proto::matches<Expr, StringLength> ));
+
+ // Calculate the length of the string and allocate a buffer statically
+ static std::size_t const length =
+ boost::result_of<StringLength(Expr)>::type::value;
+ wchar_t buffer[ length + 1 ] = {L'\0'};
+
+ // Get the current ctype facet
+ std::locale loc;
+ std::ctype<char> const &ct(std::use_facet<std::ctype<char> >(loc));
+
+ // Concatenate and widen the string expression
+ StringCopy()(expr, &buffer[0], ct);
+
+ // Write out the buffer.
+ std::wcout << buffer << std::endl;
+ }
+
+ int main()
+ {
+ widen( proto::lit("hello") + " " + "world" );
+ }
+
+The above code displays:
+
+[pre
+hello world
+]
+
+This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and (unlike the state parameter) Proto will never mess with it.
+
+[heading Implicit Parameters to Primitive Transforms]
+
+Let's use the above example to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals above:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+ )
+
+Here we specify all three parameters to both invocations of the `StringCopy` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been writen more simply as:
+
+ StringCopy(
+ proto::_right
+ , StringCopy(proto::_left)
+ )
+
+The same is true for any primitive transform. The following are all equivalent:
+
+[table Implicit Parameters to Primitive Transforms
+ [[Equivalent Transforms]]
+ [[`proto::when<_, StringCopy>`]]
+ [[`proto::when<_, StringCopy(_)>`]]
+ [[`proto::when<_, StringCopy(_, proto::_state)>`]]
+ [[`proto::when<_, StringCopy(_, proto::_state, proto::_data)>`]]
+]
+
+[note *Grammars Are Primitive Transforms Are Function Objects*
+
+So far, we've said that all Proto grammars are function objects. But it's more accurate to say that Proto grammars are primitive transforms -- a special kind of function object that takes between 1 and 3 arguments, and that Proto knows to treat specially when used in a callable transform, as in the table above.]
+
+[note *Not All Function Objects Are Primitive Transforms*
+
+You might be tempted now to drop the `_state` and `_data` parameters to `WidenCopy(proto::_value, proto::_state, proto::_data)`. That would be an error. `WidenCopy` is just a plain function object, not a primitive transform, so you must specify all its arguments. We'll see later how to write your own primitive transforms.]
+
+Once you know that primitive transforms will always receive all three parameters -- expression, state, and data -- it makes things possible that wouldn't be otherwise. For instance, consider that for binary expressions, these two transforms are equivalent. Can you see why?
+
+[table Two Equivalent Transforms
+ [[Without [^proto::fold<>]][With [^proto::fold<>]]]
+ [[``StringCopy(
+ proto::_right
+ , StringCopy(proto::_left, proto::_state, proto::_data)
+ , proto::_data
+)``
+][``proto::fold<_, proto::_state, StringCopy>``]]
+]
+
+[endsect]
+
+[/===========================================]
+[section:built_in Proto's Built-In Transforms]
+[/===========================================]
+
+[def _N_ [~N]]
+[def _G_ [~G]]
+[def _G0_ [~G0]]
+[def _G1_ [~G1]]
+[def _CT_ [~CT]]
+[def _OT_ [~OT]]
+[def _ET_ [~ET]]
+[def _ST_ [~ST]]
+[def _FT_ [~FT]]
+
+Primitive transforms are the building blocks for more interesting composite transforms. Proto defines a bunch of generally useful primitive transforms. They are summarized below.
+
+[variablelist
+ [[_value_pt_]
+ [Given a terminal expression, return the value of the terminal.]]
+ [[_child_c_pt_]
+ [Given a non-terminal expression, `proto::_child_c<_N_>` returns the _N_-th
+ child.]]
+ [[_child_pt_]
+ [A synonym for `proto::_child_c<0>`.]]
+ [[_left_pt_]
+ [A synonym for `proto::_child_c<0>`.]]
+ [[_right_pt_]
+ [A synonym for `proto::_child_c<1>`.]]
+ [[_expr_pt_]
+ [Returns the current expression unmodified.]]
+ [[_state_pt_]
+ [Returns the current state unmodified.]]
+ [[_data_pt_]
+ [Returns the current data unmodified.]]
+ [[_call_pt_]
+ [For a given callable transform `_CT_`, `proto::call<_CT_>` turns the
+ callable transform into a primitive transform. This is useful for
+ disambiguating callable transforms from object transforms, and also for
+ working around compiler bugs with nested function types.]]
+ [[_make_pt_]
+ [For a given object transform `_OT_`, `proto::make<_OT_>` turns the
+ object transform into a primitive transform. This is useful for
+ disambiguating object transforms from callable transforms, and also for
+ working around compiler bugs with nested function types.]]
+ [[_default_pt_]
+ [Given a grammar _G_, `proto::_default<_G_>` evaluates the current node
+ according to the standard C++ meaning of the operation the node represents.
+ For instance, if the current node is a binary plus node, the two children
+ will both be evaluated according to `_G_` and the results will be added and
+ returned. The return type is deduced with the help of the Boost.Typeof
+ library.]]
+ [[_fold_pt_]
+ [Given three transforms `_ET_`, `_ST_`, and `_FT_`,
+ `proto::fold<_ET_, _ST_, _FT_>` first evaluates `_ET_` to obtain a Fusion
+ sequence and `_ST_` to obtain an initial state for the fold, and then
+ evaluates `_FT_` for each element in the sequnce to generate the next
+ state from the previous.]]
+ [[_reverse_fold_pt_]
+ [Like _fold_pt_, except the elements in the Fusion sequence are iterated in
+ reverse order.]]
+ [[_fold_tree_pt_]
+ [Like `proto::fold<_ET_, _ST_, _FT_>`, except that the result of the `_ET_`
+ transform is treated as an expression tree that is /flattened/ to generate
+ the sequence to be folded. Flattening an expression tree causes child nodes
+ with the same tag type as the parent to be put into sequence. For instance,
+ `a >> b >> c` would be flattened to the sequence \[`a`, `b`, `c`\], and this
+ is the sequence that would be folded.]]
+ [[_reverse_fold_tree_pt_]
+ [Like _fold_tree_pt_, except that the flattened sequence is iterated in
+ reverse order.]]
+ [[_lazy_pt_]
+ [A combination of _make_pt_ and _call_pt_ that is useful when the nature of
+ the transform depends on the expression, state and/or data parameters.
+ `proto::lazy<R(A0,A1...An)>` first evaluates `proto::make<R()>` to compute a
+ callable type `R2`. Then, it evaluates `proto::call<R2(A0,A1...An)>`.]]
+]
+
+[/============================================]
+[heading All Grammars Are Primitive Transforms]
+[/============================================]
+
+In addition to the above primitive transforms, all of Proto's grammar elements are also primitive transforms. Their behaviors are described below.
+
+[variablelist
+ [[_wild_]
+ [Returns the current expression unmodified.]]
+ [[_or_]
+ [For the specified set of alternate sub-grammars, find the one that matches
+ the given expression and apply its associated transform.]]
+ [[_and_]
+ [For the given set of sub-grammars, take the /last/ sub-grammar and apply its
+ associated transform.]]
+ [[_not_]
+ [Returns the current expression unmodified.]]
+ [[_if_]
+ [Given three transforms, evaluate the first and treat the result as a
+ compile-time Boolean value. If it is true, evaluate the second transform.
+ Otherwise, evaluate the third.]]
+ [[_terminal_]
+ [Returns the current terminal expression unmodified.]]
+ [[_plus_, _nary_expr_, et. al.]
+ [A Proto grammar that matches a non-terminal such as
+ `proto::plus<_G0_, _G1_>`, when used as a primitive transform, creates a new
+ plus node where the left child is transformed according to `_G0_` and the
+ right child with `_G1_`.]]
+]
+
+[/=================================]
+[heading The Pass-Through Transform]
+[/=================================]
+
+Note the primitive transform associated with grammar elements such as _plus_ described above. They possess a so-called /pass-through/ transform. The pass-through transform accepts an expression of a certain tag type (say, `proto::tag::plus`) and creates a new expression of the same tag type, where each child expression is transformed according to the corresponding child grammar of the pass-through transform. So for instance this grammar ...
+
+ proto::function< X, proto::vararg<Y> >
+
+... matches function expressions where the first child matches the `X` grammar and the rest match the `Y` grammar. When used as a transform, the above grammar will create a new function expression where the first child is transformed according to `X` and the rest are transformed according to `Y`.
+
+The following class templates in Proto can be used as grammars with pass-through transforms:
+
+[table Class Templates With Pass-Through Transforms
+ [[Templates with Pass-Through Transforms]]
+ [[`proto::unary_plus<>`]]
+ [[`proto::negate<>`]]
+ [[`proto::dereference<>`]]
+ [[`proto::complement<>`]]
+ [[`proto::address_of<>`]]
+ [[`proto::logical_not<>`]]
+ [[`proto::pre_inc<>`]]
+ [[`proto::pre_dec<>`]]
+ [[`proto::post_inc<>`]]
+ [[`proto::post_dec<>`]]
+ [[`proto::shift_left<>`]]
+ [[`proto::shift_right<>`]]
+ [[`proto::multiplies<>`]]
+ [[`proto::divides<>`]]
+ [[`proto::modulus<>`]]
+ [[`proto::plus<>`]]
+ [[`proto::minus<>`]]
+ [[`proto::less<>`]]
+ [[`proto::greater<>`]]
+ [[`proto::less_equal<>`]]
+ [[`proto::greater_equal<>`]]
+ [[`proto::equal_to<>`]]
+ [[`proto::not_equal_to<>`]]
+ [[`proto::logical_or<>`]]
+ [[`proto::logical_and<>`]]
+ [[`proto::bitwise_and<>`]]
+ [[`proto::bitwise_or<>`]]
+ [[`proto::bitwise_xor<>`]]
+ [[`proto::comma<>`]]
+ [[`proto::mem_ptr<>`]]
+ [[`proto::assign<>`]]
+ [[`proto::shift_left_assign<>`]]
+ [[`proto::shift_right_assign<>`]]
+ [[`proto::multiplies_assign<>`]]
+ [[`proto::divides_assign<>`]]
+ [[`proto::modulus_assign<>`]]
+ [[`proto::plus_assign<>`]]
+ [[`proto::minus_assign<>`]]
+ [[`proto::bitwise_and_assign<>`]]
+ [[`proto::bitwise_or_assign<>`]]
+ [[`proto::bitwise_xor_assign<>`]]
+ [[`proto::subscript<>`]]
+ [[`proto::if_else_<>`]]
+ [[`proto::function<>`]]
+ [[`proto::unary_expr<>`]]
+ [[`proto::binary_expr<>`]]
+ [[`proto::nary_expr<>`]]
+]
+
+[/=====================================================]
+[heading The Many Roles of Proto Operator Metafunctions]
+[/=====================================================]
+
+We've seen templates such as _terminal_, _plus_ and _nary_expr_ fill many roles. They are metafunction that generate expression types. They are grammars that match expression types. And they are primitive transforms. The following code samples show examples of each.
+
+[*As Metafunctions ...]
+
+ // proto::terminal<> and proto::plus<> are metafunctions
+ // that generate expression types:
+ typedef proto::terminal<int>::type int_;
+ typedef proto::plus<int_, int_>::type plus_;
+
+ int_ i = {42}, j = {24};
+ plus_ p = {i, j};
+
+[*As Grammars ...]
+
+ // proto::terminal<> and proto::plus<> are grammars that
+ // match expression types
+ struct Int : proto::terminal<int> {};
+ struct Plus : proto::plus<Int, Int> {};
+
+ BOOST_MPL_ASSERT(( proto::matches< int_, Int > ));
+ BOOST_MPL_ASSERT(( proto::matches< plus_, Plus > ));
+
+[*As Primitive Transforms ...]
+
+ // A transform that removes all unary_plus nodes in an expression
+ struct RemoveUnaryPlus
+ : proto::or_<
+ proto::when<
+ proto::unary_plus<RemoveUnaryPlus>
+ , RemoveUnaryPlus(proto::_child)
+ >
+ // Use proto::terminal<> and proto::nary_expr<>
+ // both as grammars and as primitive transforms.
+ , proto::terminal<_>
+ , proto::nary_expr<_, proto::vararg<RemoveUnaryPlus> >
+ >
+ {};
+
+ int main()
+ {
+ proto::literal<int> i(0);
+
+ proto::display_expr(
+ +i - +(i - +i)
+ );
+
+ proto::display_expr(
+ RemoveUnaryPlus()( +i - +(i - +i) )
+ );
+ }
+
+The above code displays the following, which shows that unary plus nodes have been stripped from the expression:
+
+[pre
+minus(
+ unary_plus(
+ terminal(0)
+ )
+ , unary_plus(
+ minus(
+ terminal(0)
+ , unary_plus(
+ terminal(0)
+ )
+ )
+ )
+)
+minus(
+ terminal(0)
+ , minus(
+ terminal(0)
+ , terminal(0)
+ )
+)
+]
+
+[endsect]
+
+[/======================================================]
+[section:primitives Building Custom Primitive Transforms]
+[/======================================================]
+
+In previous sections, we've seen how to compose larger transforms out of smaller transforms using function types. The smaller transforms from which larger transforms are composed are /primitive transforms/, and Proto provides a bunch of common ones such as `_child0` and `_value`. In this section we'll see how to author your own primitive transforms.
+
+[note There are a few reasons why you might want to write your own primitive transforms. For instance, your transform may be complicated, and composing it out of primitives becomes unwieldy. You might also need to work around compiler bugs on legacy compilers that makes composing transforms using function types problematic. Finally, you might also decide to define your own primitive transforms to improve compile times. Since Proto can simply invoke a primitive transform directly without having to process arguments or differentiate callable transforms from object transforms, primitive transforms are more efficient.]
+
+Primitive transforms inherit from `proto::transform<>` and have a nested `impl<>` template that inherits from `proto::transform_impl<>`. For example, this is how Proto defines the `_child_c<_N_>` transform, which returns the _N_-th child of the current expression:
+
+ namespace boost { namespace proto
+ {
+ // A primitive transform that returns N-th child
+ // of the current expression.
+ template<int N>
+ struct _child_c : transform<_child_c<N> >
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename result_of::child_c<Expr, N>::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ return proto::child_c<N>(expr);
+ }
+ };
+ };
+
+ // Note that _child_c<N> is callable, so that
+ // it can be used in callable transforms, as:
+ // _child_c<0>(_child_c<1>)
+ template<int N>
+ struct is_callable<_child_c<N> >
+ : mpl::true_
+ {};
+ }}
+
+The `proto::transform<>` base class provides the `operator()` overloads and the nested `result<>` template that make your transform a valid function object. These are implemented in terms of the nested `impl<>` template you define.
+
+The `proto::transform_impl<>` base class is a convenience. It provides some nested typedefs that are generally useful. The are specified in the table below:
+
+[table proto::transform_impl<Expr, State, Data> typedefs
+[[typedef][Equivalent To]]
+[[`expr`][`typename remove_reference<Expr>::type`]]
+[[`state`][`typename remove_reference<State>::type`]]
+[[`data`][`typename remove_reference<Data>::type`]]
+[[`expr_param`][`typename add_reference<typename add_const<Expr>::type>::type`]]
+[[`state_param`][`typename add_reference<typename add_const<State>::type>::type`]]
+[[`data_param`][`typename add_reference<typename add_const<Data>::type>::type`]]
+]
+
+You'll notice that `_child_c::impl::operator()` takes arguments of types `expr_param`, `state_param`, and `data_param`. The typedefs make it easy to accept arguments by reference or const reference accordingly.
+
+The only other interesting bit is the `is_callable<>` specialization, which will be described in the [link boost_proto.users_guide.expression_transformation.is_callable next section].
+
+[endsect]
+
+[/=================================================]
+[section:is_callable Making Your Transform Callable]
+[/=================================================]
+
+Transforms are typically of the form `proto::when< Something, R(A0,A1,...) >`. The question is whether `R` represents a function to call or an object to construct, and the answer determines how _when_ evaluates the transform. _when_ uses the `proto::is_callable<>` trait to disambiguate between the two. Proto does its best to guess whether a type is callable or not, but it doesn't always get it right. It's best to know the rules Proto uses, so that you know when you need to be more explicit.
+
+For most types `R`, `proto::is_callable<R>` checks for inheritence from `proto::callable`. However, if the type `R` is a template specialization, Proto assumes that it is /not/ callable ['even if the template inherits from `proto::callable`]. We'll see why in a minute. Consider the following erroneous callable object:
+
+ // Proto can't tell this defines something callable!
+ template<typename T>
+ struct times2 : proto::callable
+ {
+ typedef T result_type;
+
+ T operator()(T i) const
+ {
+ return i * 2;
+ }
+ };
+
+ // ERROR! This is not going to multiply the int by 2:
+ struct IntTimes2
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
+ {};
+
+The problem is that Proto doesn't know that `times2<int>` is callable, so rather that invoking the `times2<int>` function object, Proto will try to construct a `times2<int>` object and initialize it will an `int`. That will not compile.
+
+[note Why can't Proto tell that `times2<int>` is callable? After all, it inherits from `proto::callable`, and that is detectable, right? The problem is that merely asking whether some type `X<Y>` inherits from `callable` will cause the template `X<Y>` to be instantiated. That's a problem for a type like `std::vector<_value(_child1)>`. `std::vector<>` will not suffer to be instantiated with `_value(_child1)` as a template parameter. Since merely asking the question will sometimes result in a hard error, Proto can't ask; it has to assume that `X<Y>` represents an object to construct and not a function to call.]
+
+There are a couple of solutions to the `times2<int>` problem. One solution is to wrap the transform in `proto::call<>`. This forces Proto to treat `times2<int>` as callable:
+
+ // OK, calls times2<int>
+ struct IntTimes2
+ : proto::when<
+ proto::terminal<int>
+ , proto::call<times2<int>(proto::_value)>
+ >
+ {};
+
+This can be a bit of a pain, because we need to wrap every use of `times2<int>`, which can be tedious and error prone, and makes our grammar cluttered and harder to read.
+
+Another solution is to specialize `proto::is_callable<>` on our `times2<>` template:
+
+ namespace boost { namespace proto
+ {
+ // Tell Proto that times2<> is callable
+ template<typename T>
+ struct is_callable<times2<T> >
+ : mpl::true_
+ {};
+ }}
+
+ // OK, times2<> is callable
+ struct IntTimes2
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
+ {};
+
+This is better, but still a pain because of the need to open Proto's namespace.
+
+You could simply make sure that the callable type is not a template specialization. Consider the following:
+
+ // No longer a template specialization!
+ struct times2int : times2<int> {};
+
+ // OK, times2int is callable
+ struct IntTimes2
+ : proto::when<
+ proto::terminal<int>
+ , times2int(proto::_value)
+ >
+ {};
+
+This works because now Proto can tell that `times2int` inherits (indirectly) from `proto::callable`. Any non-template types can be safely checked for inheritance because, as they are not templates, there is no worry about instantiation errors.
+
+There is one last way to tell Proto that `times2<>` is callable. You could add an extra dummy template parameter that defaults to `proto::callable`:
+
+ // Proto will recognize this as callable
+ template<typename T, typename Callable = proto::callable>
+ struct times2 : proto::callable
+ {
+ typedef T result_type;
+
+ T operator()(T i) const
+ {
+ return i * 2;
+ }
+ };
+
+ // OK, this works!
+ struct IntTimes2
+ : proto::when<
+ proto::terminal<int>
+ , times2<int>(proto::_value)
+ >
+ {};
+
+Note that in addition to the extra template parameter, `times2<>` still inherits from `proto::callable`. That's not necessary in this example but it's good style because any types derived from `times2<>` (as `times2int` defined above) will still be considered callable.
+
+[endsect]
+
+[endsect]
+
+[endsect]
Modified: trunk/libs/proto/doc/calculator.qbk
==============================================================================
--- trunk/libs/proto/doc/calculator.qbk (original)
+++ trunk/libs/proto/doc/calculator.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -112,9 +112,9 @@
expression transforms that give you total control over how your expressions
are evaluated.
-[/=================================]
-[heading Customing Expression Trees]
-[/=================================]
+[/===================================]
+[heading Customizing Expression Trees]
+[/===================================]
Our calculator DSEL is already pretty useful, and for many DSEL scenarios, no more
would be needed. But let's keep going. Imagine how much nicer it would be if all
@@ -158,36 +158,31 @@
// Overload operator() to invoke proto::eval() with
// our calculator_context.
- double operator()(double a1 = 0, double a2 = 0, double a3 = 0) const
+ double operator()(double a1 = 0, double a2 = 0) const
{
calculator_context ctx;
ctx.args.push_back(a1);
ctx.args.push_back(a2);
- ctx.args.push_back(a3);
return proto::eval(*this, ctx);
}
};
-The `calculator<>` struct is an expression /extension/. It uses `proto::extends<>`
-to effectively add additional members to an expression type. When composing larger
-expressions from smaller ones, Proto notes what domain the smaller expressions are
-in. The larger expression is in the same domain and is automatically wrapped in the
-domain's extension wrapper.
+The `calculator<>` struct is an expression /extension/. It uses `proto::extends<>` to effectively add additional members to an expression type. When composing larger expressions from smaller ones, Proto notes what domain the smaller expressions are in. The larger expression is in the same domain and is automatically wrapped in the domain's extension wrapper.
-All that remains to be done is to put our placeholders in the calculator domain. We
-do that by wrapping them in our `calculator<>` wrapper, as below:
+All that remains to be done is to put our placeholders in the calculator domain. We do that by wrapping them in our `calculator<>` wrapper, as below:
// Define the Protofied placeholder terminals, in the
// calculator domain.
calculator<proto::terminal<placeholder<0> >::type> const _1;
calculator<proto::terminal<placeholder<1> >::type> const _2;
-Any larger expression that contain these placeholders will automatically be wrapped
-in the `calculator<>` wrapper and have our `operator()` overload.
+Any larger expression that contain these placeholders will automatically be wrapped in the `calculator<>` wrapper and have our `operator()` overload. That means we can use them as function objects as follows.
-Now that we've extended calculator expressions to make them function objects, we
-can use them with standard algorithms, as shown below:
+ double result = ((_2 - _1) / _2 * 100)(45.0, 50.0);
+ assert(result == (50.0 - 45.0) / 50.0 * 100));
+
+Since calculator expressions are now valid function objects, we can use them with standard algorithms, as shown below:
double a1[4] = { 56, 84, 37, 69 };
double a2[4] = { 65, 120, 60, 70 };
@@ -226,27 +221,18 @@
>
{};
-You can read the above grammar as follows: an expression tree conforms to the
-calculator grammar if it is a binary plus, minus, multiplies or divides node, where
-both child nodes also conform to the calculator grammar; or if it is a terminal. In
-a Proto grammar, `proto::_` is a wildcard that matches any type, so
-`proto::terminal< proto::_ >` matches any terminal, whether it is a placeholder or
-a literal.
-
-[note This grammar is actually a little looser than we would like. Only
-placeholders and literals that are convertible to doubles are valid terminals.
-Later on we'll see how to express things like that in Proto grammars.]
-
-Once you have defined the grammar of your DSEL, you can use the `proto::matches<>`
-metafunction to check whether a given expression type conforms to the grammar. For
-instance, we might add the following to our `calculator::operator()` overload:
+You can read the above grammar as follows: an expression tree conforms to the calculator grammar if it is a binary plus, minus, multiplies or divides node, where both child nodes also conform to the calculator grammar; or if it is a terminal. In a Proto grammar, _wild_ is a wildcard that matches any type, so `proto::terminal< proto::_ >` matches any terminal, whether it is a placeholder or a literal.
+
+[note This grammar is actually a little looser than we would like. Only placeholders and literals that are convertible to doubles are valid terminals. Later on we'll see how to express things like that in Proto grammars.]
+
+Once you have defined the grammar of your DSEL, you can use the _matches_ metafunction to check whether a given expression type conforms to the grammar. For instance, we might add the following to our `calculator::operator()` overload:
template<typename Expr>
struct calculator
: proto::extends< /* ... as before ... */ >
{
/* ... */
- double operator()(double a1 = 0, double a2 = 0, double a3 = 0) const
+ double operator()(double a1 = 0, double a2 = 0) const
{
// Check here that the expression we are about to
// evaluate actually conforms to the calcuator grammar.
Deleted: trunk/libs/proto/doc/construction.qbk
==============================================================================
--- trunk/libs/proto/doc/construction.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
+++ (empty file)
@@ -1,1180 +0,0 @@
-[/
- / Copyright (c) 2007 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)
- /]
-
-[def __unspecified__ [~unspecified]]
-
-[/=======================================================================================]
-[section:expression_construction Expression Construction: Building Proto Expression Trees]
-[/=======================================================================================]
-
-We've seen some simple examples of how to use Proto, but we haven't really said
-much about what is going on under the hood. How exactly does Proto build and
-process expression trees? Now is the time to find out.
-
-In the calculator example, we defined a placeholder terminal like this:
-
- // Define a placeholder type
- template<int I>
- struct placeholder
- {};
-
- // Define the Protofied placeholder terminal
- proto::terminal< placeholder<0> >::type const _1 = {{}};
-
-The actual type of `_1` looks like this:
-
- proto::expr< proto::tag::terminal, proto::term< placeholder<0> >, 0 >
-
-The _expr_ template is the most important type in Proto. Although you will
-rarely need to deal with it directly, it's always there behind the scenes
-holding your expression trees together. In fact, _expr_ /is/ the expression
-tree -- branches, leaves and all.
-
-The _expr_ template makes up the nodes in expression trees. The first template
-parameter is the node type; in this case, `proto::tag::terminal`. That means
-that `_1` is a leaf-node in the expression tree. The second template parameter
-is a list of child types, or in the case of terminals, the terminal's value
-type. Terminals will always have only one type in the type list. The last
-parameter is the arity of the expression. Terminals have arity 0, unary
-expressions have arity 1, etc.
-
-The _expr_ struct is defined as follows:
-
- template< typename Tag, typename Args, long Arity = Args::arity >
- struct expr;
-
- template< typename Tag, typename Args >
- struct expr< Tag, Args, 1 >
- {
- typedef typename Args::child0 proto_child0;
- proto_child0 child0;
- // ...
- };
-
-The _expr_ struct does not define a constructor, or anything else that would
-prevent static initialization. All _expr_ objects are initialized using
-['aggregate initialization], with curly braces. In our example, `_1` is
-initialized with the initializer `{{}}`. The outer braces is the initializer
-for the _expr_ struct, and the inner braces are for the member `_1.child0` which
-is of type `placeholder<0>`. Note that we use braces to initialize `_1.child0`
-because `placeholder<0>` is also an aggregate.
-
-[/=================================]
-[heading Proto's Operator Overloads]
-[/=================================]
-
-Once we have some Proto terminals, expressions involving those terminals build
-expression trees for us. Proto defines overloads for each of C++'s overloadable
-operators in the `boost::proto` namespace. As long as one operand is a Proto
-expression, the result of the operation is a tree node representing that operation.
-
-[note The _expr_ struct lives in the `boost::proto` namespace, as do all of
-Proto's operator overloads. The overloads are found via ADL (argument-dependent
-lookup). That is why expressions must be "tainted" with Proto-ness for Proto to
-be able to build trees out of expressions.]
-
-As a result of Proto's operator overloads, we can say:
-
- -_1; // OK, build a unary-negate tree node
- _1 + 42; // OK, build a binary-plus tree node
-
-[/=========================================================]
-[heading Assignment, Subscript, and Function Call Operators]
-[/=========================================================]
-
-The _expr_ type defines overloads of `operator=`, `operator[]`, and `operator()`
-as member functions. That's because these operators cannot be overloaded at
-namespace scope. Because _expr_ defines them as member functions, the following
-are valid Proto expressions:
-
- _1 = 5; // OK, builds a binary assign tree node
- _1[6]; // OK, builds a binary subscript tree node
- _1(); // OK, builds a unary function tree node
- _1(7); // OK, builds a binary function tree node
- _1(8,9); // OK, builds a ternary function tree node
- // ... etc.
-
-For the first two lines, assigment and subscript, it should be fairly unsurprising
-that the resulting expression node should be binary. After all, there are
-two operands in each expression. It may be surprising at first that what appears
-to be a function call with no arguments, `_1()`, actually creates an expression
-node with one child. The child is `_1` itself. Likewise, the expression `_1(7)`
-has two children: `_1` and `7`.
-
-Because these operators can only be defined as member functions of _expr_, the
-following expressions are invalid:
-
- int i;
- i = _1; // ERROR: cannot assign _1 to an int
-
- int *p;
- p[_1]; // ERROR: cannot use _1 as an index
-
- std::sin(_1); // ERROR: cannot call std::sin() with _1
-
-Also, C++ has special rules for overloads of `operator->` that make it useless
-for building expression templates, so Proto does not overload it.
-
-[/==============================]
-[heading The Address-Of Operator]
-[/==============================]
-
-Proto overloads the address-of operator for expression types, so that the
-following code creates a new unary address-of tree node:
-
- &_1; // OK, creates a unary address-of tree node
-
-It does /not/ return the address of the `_1` object. However, there is
-special code in Proto such that a unary address-of node is implicitly
-convertible to a pointer to its child. In other words, the following
-code works and does what you might expect, but not in the obvious way:
-
- typedef
- proto::terminal< placeholder<0> >::type
- _1_type;
-
- _1_type const _1 = {{}};
- _1_type const * p = &_1; // OK, &_1 implicitly converted
-
-[/=======================]
-[heading Making Terminals]
-[/=======================]
-
-Proto's expression-building operator overloads are only considered when at least one operand is itself a Proto expression. We've seen how to define Protofied terminals with _terminal_, but that method can be a little awkward at times. Proto provides an easier-to-use wrapper for literals that can be used to construct Protofied terminal expressions. It's called _literal_.
-
- // Define a literal integer Proto expression.
- proto::literal<int> i = 0;
-
- // Proto literals are really just Proto terminal expressions.
- // For example, this build a proto expression template:
- i + 1;
-
-There is also a _lit_ function for constructing a _literal_ in-place. The above expression can simply be written as:
-
- // proto::lit(0) creates an integer terminal expression
- proto::lit(0) + 1;
-
-Sometimes you might want to Protofy an object, but only if it has not already been Protofied. This is especially common when writing lazy functions for your DSEL. For these situations there is _as_expr_ and _as_child_. Imagine that for the calculator DSEL described in the Getting Started guide that you wanted to define a `pow()` function that lazily raises its argument to an integral exponent. You would want expressions like `pow<2>(_1)` to work (where `_1` is an argument placeholder), and you also want to allow `pow<2>(42)`. In the first case, `_1` is already a Proto expression type, but in the second, `42` is not. Here's how you would do it.
-
- // Define a pow_fun function object
- template<int Exp>
- struct pow_fun
- {
- typedef double result_type;
- double operator()(double d) const
- {
- return std::pow(d, Exp);
- }
- };
-
- // Define a lazy pow() function for the calculator DSEL. Use
- // proto::as_child() to Protofying the argument, but only if it
- // is not a Proto expression type to begin with!
- template<int Exp, typename Arg>
- typename proto::function<
- typename proto::terminal<pow_fun<Exp> >::type
- , typename proto::result_of::as_child<Arg const>::type
- >::type
- pow(Arg const &arg)
- {
- typedef
- typename proto::function<
- typename proto::terminal<pow_fun<Exp> >::type
- , typename proto::result_of::as_child<Arg const>::type
- >::type
- result_type;
-
- result_type result = {{{}}, proto::as_child(arg)};
- return result;
- }
-
-In the above, `pow()` uses _as_child_ to Protofy its argument, but only if the argument is not already a Proto expression. When passed a Proto expression, _as_child_ returns it unmolested. When passed a non-Proto object, it is turned into a Proto expression by wrapping it in a Proto terminal /by reference/. So for instance, the expression created by `pow<2>(42)` holds `42` by const reference.
-
-If you don't want the resulting terminal expression to hold its value by reference, you can use _as_expr_ instead. _as_expr_ behaves exactly as _as_child_ except that, when passed a non-Proto object, _as_expr_ wraps it in a Proto terminal expression /by value/.
-
-[/================================]
-[heading Building Expression Trees]
-[/================================]
-
-The `_1` node is an instantiation of _expr_, and expressions containing
-`_1` are also instantiations of _expr_. To use Proto effectively, you
-won't have to bother yourself with the actual types that Proto generates.
-These are details, but you're likely to encounter these types in compiler
-error messages, so it's helpful to be familiar with them. The types look
-like this:
-
- // The type of the expression -_1
- typedef
- proto::expr<
- proto::tag::negate
- , proto::list1<
- proto::expr<
- proto::tag::terminal
- , proto::term< placeholder<0> >
- , 0
- > const &
- >
- , 1
- >
- negate_placeholder_type;
-
- negate_placeholder_type x = -_1;
-
- // The type of the expression _1 + 42
- typedef
- proto::expr<
- proto::tag::plus
- , proto::list2<
- proto::expr<
- proto::tag::terminal
- , proto::term< placeholder<0> >
- , 0
- > const &
- , proto::expr<
- proto::tag::terminal
- , proto::term< int const & >
- , 0
- >
- >
- , 2
- >
- placeholder_plus_int_type;
-
- placeholder_plus_int_type y = _1 + 42;
-
-There are a few things to note about these types:
-
-# Terminals have arity 0, unary expressions have arity 1 and binary expressions
- have arity 2.
-# When one Proto expression is made a child node of another Proto expression,
- it is held by reference, ['even if it is a temporary object]. This last
- point becomes important later.
-# Non-Proto expressions, such as the integer literal, are turned into Proto
- expressions by wrapping them in new `expr<>` terminal objects. These new
- wrappers are not themselves held by reference, but the object wrapped /is/.
- Notice that the type of the Protofied `42` literal is `int const &` -- held
- by reference.
-
-The types make it clear: everything in a Proto expression tree is held by
-reference. That means that building an expression tree is exceptionally cheap.
-It involves no copying at all.
-
-[note An astute reader will notice that the object `y` defined above will be
-left holding a dangling reference to a temporary int. In the sorts of
-high-performance applications Proto addresses, it is typical to build and
-evaluate an expression tree before any temporary objects go out of scope, so
-this dangling reference situation often doesn't arise, but it is certainly
-something to be aware of. Proto provides utilities for deep-copying expression
-trees so they can be passed around as value types without concern for dangling
-references.]
-
-[/=============================================]
-[section:left_right_child Accessing Child Nodes]
-[/=============================================]
-
-After assembling an expression into a tree, you'll naturally want to be
-able to do the reverse, and access a node's children. You may even want
-to be able to iterate over the children with algorithms from the
-Boost.Fusion library. This section shows how.
-
-[heading [^tag_of<>]]
-
-A node in an expression tree is nothing more than a collection of child
-nodes and a tag type. You can access the tag type of any Proto expression type
-`Expr` directly as `typename Expr::proto_tag`, or you can use the _tag_of_
-metafunction, as shown below:
-
- template<typename Expr>
- typename proto::result_of::tag_of<Expr>::type
- get_tag_of(Expr const &)
- {
- // Tag types are required to be default-constructible
- return typename proto::result_of::tag_of<Expr>::type();
- }
-
- proto::terminal<int>::type const i = {42};
-
- // Addition nodes have the "plus" tag type:
- proto::tag::plus plus_tag = get_tag_of( i + 2 );
-
-[/===================]
-[heading [^child_c()]]
-[/===================]
-
-Each node in an expression tree corresponds to an operator in an expression,
-and the children correspond to the operands, or arguments of the operator.
-To access them, you can use the _child_c_ function template, as demonstrated
-below:
-
- proto::terminal<int>::type i = {42};
-
- // Get the 0-th operand of an addition operation:
- proto::terminal<int>::type &ri = proto::child_c<0>( i + 2 );
-
- // Assert that we got back what we put in:
- assert( &i == &ri );
-
-You can use the `result_of::child_c<>` metafunction to get the type of the Nth
-child of an expression node. Usually you don't care to know whether a child
-is stored by value or by reference, so when you ask for the type of the Nth
-child of an expression `Expr`, you get the child's type after references and
-cv-qualifiers have been stripped from it.
-
- template<typename Expr>
- void test_result_of_child_c(Expr const &expr)
- {
- typedef typename proto::result_of::child_c<Expr, 0>::type type;
-
- // ::type is a non-cv qualified, non-reference
- BOOST_MPL_ASSERT((is_same< type, terminal<int>::type>));
- }
-
- // ...
- terminal<int>::type i = {42};
- test_result_of_child_c( i + 2 );
-
-However, if you ask for the type of the Nth child of `Expr &` or `Expr const &`
-(note the reference), the result type will be a reference, regardless of whether
-the child is actually stored by reference or not. If you need to know exactly
-how the child is stored in the node, whether by reference or by value, you can
-use `fusion::result_of::value_at<Expr, N>::type`. The following table summarizes
-the behavior of the `child_c<>` metafunction.
-
-[table Accessing Child Types
- [[Metafunction Invocation][When the Child Is ...][The Result Is ...]]
- [[`proto::result_of::child_c<Expr, N>::type`][T][T]]
- [[][T &][T]]
- [[][T const &][T]]
- [[`proto::result_of::child_c<Expr &, N>::type`][T][T &]]
- [[][T &][T &]]
- [[][T const &][T const &]]
- [[`proto::result_of::child_c<Expr const &, N>::type`][T][T const &]]
- [[][T &][T &]]
- [[][T const &][T const &]]
- [[`fusion::result_of::value_at<Expr, N>::type`][T][T]]
- [[][T &][T &]]
- [[][T const &][T const &]]
-]
-
-[/========================================================]
-[heading [^value()], [^child()], [^left()], and [^right()]]
-[/========================================================]
-
-Most operators in C++ are unary or binary. For that reason, accessing the
-only operand, or the left and right operands, are very common operations. For
-this reason, Proto provides the _child_, _left_, and _right_ functions. _child_
-and _left_ are synonomous with `child_c<0>()`, and _right_ is synonomous with
-`child_c<1>()`.
-
-Another very common operation is accessing the value stored within a Proto
-terminal. You can use the _value_ function for that.
-
-There are also `result_of::child<>`, `result_of::left<>`, and `result_of::right<>`
-metafunctions that merely forward to their `result_of::child_c<>` counterparts.
-Likewise, there is a `result_of::value<>` metafunction that returns the type of the
-value stored in a terminal node.
-
-[/===========================================]
-[heading Expression Nodes as Fusion Sequences]
-[/===========================================]
-
-Proto expression nodes are valid Fusion random-access sequences of their
-child nodes. That means you can apply Fusion algorithms to them,
-transform them, apply Fusion filters and views to them, and access their
-elements using `fusion::at()`. The things Fusion can do to heterogeneous
-sequences is beyond the scope of this users' guide, but below is a simple
-example. It takes a lazy function invocation like `fun(1,2,3,4)` and uses
-Fusion to print the function arguments in order.
-
- struct display
- {
- template<typename T>
- void operator()(T const &t) const
- {
- std::cout << t << std::endl;
- }
- };
-
- struct fun_t {};
- proto::terminal<fun_t>::type const fun = {{}};
-
- // ...
- fusion::for_each(
- fusion::transform(
- // pop_front() removes the "fun" child
- fusion::pop_front(fun(1,2,3,4))
- // Extract the ints from the terminal nodes
- , proto::functional::value()
- )
- , display()
- );
-
-Recall from the Introduction that types in the `proto::functional` namespace
-define function objects that correspond to Proto's free functions. So
-`proto::functional::value()` creates a function object that is equavalent to
-the `proto::value()` function. The above invocation of `fusion::for_each()`
-displays the following:
-
-[pre
-1
-2
-3
-4
-]
-
-[/========================================]
-[heading Flattening Proto Expression Tress]
-[/========================================]
-
-Imagine a slight variation of the above example where, instead of iterating
-over the arguments of a lazy function invocation, we would like to iterate
-over the terminals in an addition expression:
-
- proto::terminal<int>::type const _1 = {1};
-
- // ERROR: this doesn't work! Why?
- fusion::for_each(
- fusion::transform(
- _1 + 2 + 3 + 4
- , proto::functional::value()
- )
- , display()
- );
-
-The reason this doesn't work is because the expression `_1 + 2 + 3 + 4` does
-not describe a flat sequence of terminals --- it describes a binary tree. We
-can treat it as a flat sequence of terminals, however, using Proto's _flatten_
-function. _flatten_ returns a view which makes a tree appear as a flat Fusion
-sequence. If the top-most node has a tag type `T`, then the elements of the
-flattened sequence are the child nodes that do /not/ have tag type `T`. This
-process is evaluated recursively. So the above can correctly be written as:
-
- proto::terminal<int>::type const _1 = {1};
-
- // OK, iterate over a flattened view
- fusion::for_each(
- fusion::transform(
- proto::flatten(_1 + 2 + 3 + 4)
- , proto::functional::value()
- )
- , display()
- );
-
-The above invocation of `fusion::for_each()` displays the following:
-
-[pre
-1
-2
-3
-4
-]
-
-[endsect]
-
-[/=============================================================]
-[section:tags_and_metafunctions Operator Tags and Metafunctions]
-[/=============================================================]
-
-The following table lists the overloadable C++ operators, the Proto tag types for
-each, and the name of the metafunctions for generating the corresponding Proto
-expression types. And as we'll see later, the metafunctions are also usable as
-grammars for matching such nodes, as well as pass-through transforms.
-
-[table Operators, Tags and Metafunctions
- [[Operator]
- [Proto Tag]
- [Proto Metafunction]]
-
- [[unary `+`]
- [`proto::tag::unary_plus`]
- [`proto::unary_plus<>`]]
-
- [[unary `-`]
- [`proto::tag::negate`]
- [`proto::negate<>`]]
-
- [[unary `*`]
- [`proto::tag::dereference`]
- [`proto::dereference<>`]]
-
- [[unary `~`]
- [`proto::tag::complement`]
- [`proto::complement<>`]]
-
- [[unary `&`]
- [`proto::tag::address_of`]
- [`proto::address_of<>`]]
-
- [[unary `!`]
- [`proto::tag::logical_not`]
- [`proto::logical_not<>`]]
-
- [[unary prefix `++`]
- [`proto::tag::pre_inc`]
- [`proto::pre_inc<>`]]
-
- [[unary prefix `--`]
- [`proto::tag::pre_dec`]
- [`proto::pre_dec<>`]]
-
- [[unary postfix `++`]
- [`proto::tag::post_inc`]
- [`proto::post_inc<>`]]
-
- [[unary postfix `--`]
- [`proto::tag::post_dec`]
- [`proto::post_dec<>`]]
-
- [[binary `<<`]
- [`proto::tag::shift_left`]
- [`proto::shift_left<>`]]
-
- [[binary `>>`]
- [`proto::tag::shift_right`]
- [`proto::shift_right<>`]]
-
- [[binary `*`]
- [`proto::tag::multiplies`]
- [`proto::multiplies<>`]]
-
- [[binary `/`]
- [`proto::tag::divides`]
- [`proto::divides<>`]]
-
- [[binary `%`]
- [`proto::tag::modulus`]
- [`proto::modulus<>`]]
-
- [[binary `+`]
- [`proto::tag::plus`]
- [`proto::plus<>`]]
-
- [[binary `-`]
- [`proto::tag::minus`]
- [`proto::minus<>`]]
-
- [[binary `<`]
- [`proto::tag::less`]
- [`proto::less<>`]]
-
- [[binary `>`]
- [`proto::tag::greater`]
- [`proto::greater<>`]]
-
- [[binary `<=`]
- [`proto::tag::less_equal`]
- [`proto::less_equal<>`]]
-
- [[binary `>=`]
- [`proto::tag::greater_equal`]
- [`proto::greater_equal<>`]]
-
- [[binary `==`]
- [`proto::tag::equal_to`]
- [`proto::equal_to<>`]]
-
- [[binary `!=`]
- [`proto::tag::not_equal_to`]
- [`proto::not_equal_to<>`]]
-
- [[binary `||`]
- [`proto::tag::logical_or`]
- [`proto::logical_or<>`]]
-
- [[binary `&&`]
- [`proto::tag::logical_and`]
- [`proto::logical_and<>`]]
-
- [[binary `&`]
- [`proto::tag::bitwise_and`]
- [`proto::bitwise_and<>`]]
-
- [[binary `|`]
- [`proto::tag::bitwise_or`]
- [`proto::bitwise_or<>`]]
-
- [[binary `^`]
- [`proto::tag::bitwise_xor`]
- [`proto::bitwise_xor<>`]]
-
- [[binary `,`]
- [`proto::tag::comma`]
- [`proto::comma<>`]]
-
- [[binary `->*`]
- [`proto::tag::mem_ptr`]
- [`proto::mem_ptr<>`]]
-
- [[binary `=`]
- [`proto::tag::assign`]
- [`proto::assign<>`]]
-
- [[binary `<<=`]
- [`proto::tag::shift_left_assign`]
- [`proto::shift_left_assign<>`]]
-
- [[binary `>>=`]
- [`proto::tag::shift_right_assign`]
- [`proto::shift_right_assign<>`]]
-
- [[binary `*=`]
- [`proto::tag::multiplies_assign`]
- [`proto::multiplies_assign<>`]]
-
- [[binary `/=`]
- [`proto::tag::divides_assign`]
- [`proto::divides_assign<>`]]
-
- [[binary `%=`]
- [`proto::tag::modulus_assign`]
- [`proto::modulus_assign<>`]]
-
- [[binary `+=`]
- [`proto::tag::plus_assign`]
- [`proto::plus_assign<>`]]
-
- [[binary `-=`]
- [`proto::tag::minus_assign`]
- [`proto::minus_assign<>`]]
-
- [[binary `&=`]
- [`proto::tag::bitwise_and_assign`]
- [`proto::bitwise_and_assign<>`]]
-
- [[binary `|=`]
- [`proto::tag::bitwise_or_assign`]
- [`proto::bitwise_or_assign<>`]]
-
- [[binary `^=`]
- [`proto::tag::bitwise_xor_assign`]
- [`proto::bitwise_xor_assign<>`]]
-
- [[binary subscript]
- [`proto::tag::subscript`]
- [`proto::subscript<>`]]
-
- [[ternary `?:`]
- [`proto::tag::if_else_`]
- [`proto::if_else_<>`]]
-
- [[n-ary function call]
- [`proto::tag::function`]
- [`proto::function<>`]]
-]
-
-[endsect]
-
-[/===========================================================]
-[section:construction_utils Expression Construction Utilities]
-[/===========================================================]
-
-Proto gives you many other ways of creating expression trees besides the operator
-overloads. These are useful for building nodes with custom tag types that don't
-correspond to any C++ operator. They're also useful when writing tree transforms
-that manipulate the structure of the expression tree, as we'll see.
-
-Below are the tools and a brief description of each.
-
-[variablelist
-[ [_make_expr_]
- [A function that takes a tag type and child nodes and
- builds a parent node of the requested type.]]
-[ [_unpack_expr_]
- [A function that does the same as _make_expr_ except
- the child nodes are specified as a Fusion sequence.]]
-[ [`BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()`]
- [A macro that generates a number of overloads of a
- user-specified function template that behaves like
- _make_expr_.]]
-]
-
-[/====================================================]
-[heading Building Expression Trees With [^make_expr()]]
-[/====================================================]
-
-[:[*Synopsys:]]
-
- namespace proto
- {
- namespace result_of
- {
- // Metafunction for calculating the return type
- // of the make_expr() function
- template<
- typename Tag
- , typename DomainOrArg
- , typename... A
- >
- struct make_expr
- {
- typedef __implelemtation_defined__ type;
- };
- }
-
- namespace functional
- {
- // A callable function object equivalent of the
- // make_expr() function.
- template<typename Tag, typename Domain = default_domain>
- struct make_expr : callable
- {
- template<typename Sig> struct result;
-
- template<typename This, typename... A>
- struct result<This(A...)>
- : result_of::make_expr<Tag, Domain, A...>
- {};
-
- template<typename... A>
- typename result_of::make_expr<Tag, Domain, const A...>::type
- operator ()(A const &... a) const;
- };
- }
-
- // The make_expr() function
- template<typename Tag, typename Domain, typename... A>
- typename result_of::make_expr<Tag, Domain, A...>::type
- make_expr(A const &... a);
- }
-
-You can use the _make_expr_ function to build an expression tree node with
-a specified tag type, as follows.
-
- // Some user-defined tag type
- struct MyTag {};
-
- // Construct a node with MyTag tag type, and
- // two terminals as children.
- int i = 0;
- proto::make_expr<MyTag, default_domain>(i, 'a');
-
-You are not required to specify a domain. If you choose not to, `default_domain`
-is assumed. So the above is equivalent to:
-
- // Construct a node with MyTag tag type, and
- // two terminals as children.
- int i = 0;
- proto::make_expr<MyTag>(i, 'a');
-
-The return type of the above function invocation can be calculated with the
-`result_of::make_expr<>` metafunction.
-
- // Use result_of::make_expr<> to compute the return type:
- int i = 0;
- typedef
- proto::result_of::make_expr<
- MyTag
- , int
- , char
- >::type
- expr_type;
-
- expr_type expr = proto::make_expr<MyTag>(i, 'a');
-
- // expr_type is the same as this type:
- typedef
- proto::binary_expr<
- MyTag
- , proto::terminal<int>::type
- , proto::terminal<char>::type
- >::type
- expr_type2;
-
- BOOST_MPL_ASSERT((is_same<expr_type2, expr_type>));
-
-Notice that the children, an int and a char, are wrapped in terminal
-nodes and held by value. If you would like an argument to be beld by
-reference in the resulting tree node, you can use `boost::ref()`:
-
- // One terminal held by reference:
- int i = 0;
-
- typedef
- proto::result_of::make_expr<
- MyTag
- , int & // <-- Note reference here
- , char
- >::type
- expr_type;
-
- expr_type expr = proto::make_expr<MyTag>(boost::ref(i), 'a');
-
-In the return type calculation, we can specify by-ref with
-`int &`, but we need `boost::ref()` in the actual function invocation.
-That's because the _make_expr_ function can't tell from the function
-arguments whether you want to store the arguments by value or by
-reference.
-
-Non-terminals are handled similarly. Given the non-terminal `expr` as
-defined above, we could wrap it in a unary plus node by value or by
-reference as follows:
-
- // Make "expr" a child node of a new unary plus node, where
- // "expr" is held by-value:
- typedef
- proto::result_of::make_expr<
- proto::tag::unary_plus
- , expr_type
- >::type
- posit_val_type;
-
- posit_val_type p1 = proto::make_expr<proto::tag::unary_plus>(expr);
-
- // Same as above, except "expr" is held by-reference:
- typedef
- proto::result_of::make_expr<
- proto::tag::unary_plus
- , expr_type & // <-- Note reference here
- >::type
- posit_ref_type;
-
- posit_ref_type p2 = proto::make_expr<proto::tag::unary_plus>(boost::ref(expr));
-
- // Equivalent to "by-ref" line directly above:
- posit_ref_type p3 = +expr;
-
-The application of unary `operator+` on the last line is equivalent to
-the by-ref invocation of _make_expr_ because Proto's operator overloads
-always build trees by holding nodes by reference.
-
-If you specify a domain when invoking _make_expr_, then _make_expr_
-will use that domain's generator to wrap the resulting node in a
-domain-specific wrapper. In the example below, expressions within the
-`MyDomain` domain are wrapped in a `MyExpr<>` wrapper.
-
- template<typename Expr>
- struct MyExpr;
-
- struct MyDomain
- : proto::domain<proto::generator<MyExpr> >
- {};
-
- // ...
-
- // Use result_of::make_expr<> to compute the return type:
- int i = 0;
- typedef
- proto::result_of::make_expr<
- MyTag
- , MyDomain // <-- Note second template
- , int // param can be a domain.
- , char
- >::type
- expr_type;
-
- // Construct an expression within MyDomain:
- expr_type expr = proto::make_expr<MyTag, MyDomain>(i, 'a');
-
- // expr_type is the same as this type:
- typedef
- // New node is wrapped in MyExpr<>
- MyExpr<proto::binary_expr<
- MyTag
- // Terminals are also wrapped.
- , MyExpr<proto::terminal<int>::type>
- , MyExpr<proto::terminal<char>::type>
- >::type>
- expr_type2;
-
- BOOST_MPL_ASSERT((is_same<expr_type2, expr_type>));
-
-[/======================================================]
-[heading Building Expression Trees With [^unpack_expr()]]
-[/======================================================]
-
-[:[*Synopsys:]]
-
- namespace proto
- {
- namespace result_of
- {
- // Metafunction for calculating the return type
- // of the unpack_expr() function
- template<
- typename Tag
- , typename DomainOrSequence
- , typename SequenceOrVoid = void
- >
- struct unpack_expr
- {
- typedef __implelemtation_defined__ type;
- };
- }
-
- namespace functional
- {
- // A callable function object equivalent of the
- // unpack_expr() function.
- template<typename Tag, typename Domain = default_domain>
- struct unpack_expr : callable
- {
- template<typename Sig> struct result;
-
- template<typename This, typename Sequence>
- struct result<This(Sequence)>
- : result_of::unpack_expr<Tag, Domain, Sequence>
- {};
-
- template<typename Sequence>
- typename result_of::unpack_expr<Tag, Domain, Sequence>::type
- operator ()(Sequence const &sequence) const;
- };
- }
-
- // The unpack_expr() function
- template<typename Tag, typename Domain, typename Sequence>
- typename result_of::unpack_expr<Tag, Domain, Sequence>::type
- unpack_expr(Sequence const &sequence);
- }
-
-Once you understand _make_expr_, understanding _unpack_expr_ is
-simple. It behaves exactly the same way, except that rather than
-passing children individually, you pass the children as a Fusion
-sequence. So for instance, the following are equivalent:
-
- // Build an expression with make_expr():
- int i = 0;
- proto::make_expr<Tag>(i, 'a');
-
- // Build the same expression with unpack_expr():
- proto::unpack_expr<Tag>(fusion::make_tuple(i, 'a'));
-
- // Also the same as the above:
- fusion::tuple<int, char> args(i, 'a');
- proto::unpack_expr<Tag>(args);
-
-If you would like the arguments to be stored by reference, you can
-use `boost::ref()`, just as with _make_expr_.
-
- // Hold one argument by reference:
- int i = 0;
- proto::unpack_expr<Tag>(fusion::make_tuple(boost::ref(i), 'a'));
-
- // Also the same as the above:
- fusion::tuple<int &, char> args(i, 'a');
- proto::unpack_expr<Tag>(args);
-
-As with _make_expr_, _unpack_expr_ has a corresponding metafunction
-in the `proto::result_of` namespace for calculating its return type, as
-well as a callable function object form in the `proto::functional`
-namespace.
-
-One last interesting point about _unpack_expr_: Proto expression
-nodes are themselves valid Fusion sequences. Here, for instance, is
-a clever way to use _unpack_expr_ to turn a binary plus node into
-a binary minus node:
-
- // Use unpack_expr() to turn an addition into a subtraction
- proto::literal<int> i(8), j(42);
- proto::unpack_expr<proto::tag::minus>( i + j );
-
-The expression `i + j` creates an expression tree which _unpack_expr_
-interprets as a sequence of its children `i` and `j`. The result is a
-new node with the `tag::minus` tag and `i` and `j` as children.
-
-[/=====================================================]
-[heading Generating Custom Expression Factory Functions]
-[/=====================================================]
-
-[:[*Synopsys:]]
-
- // Generate BOOST_PROTO_MAX_ARITY overloads of a
- // function template named NAME within a particular
- // DOMAIN that generates expressions with a given
- // TAG and optionally has some arguments bound.
- #define BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( \
- NAME \
- , DOMAIN \
- , TAG \
- , BOUNDARGS \
- )
-
-The `proto::functional::make_expr<>` function object makes it very simple
-to create something that behaves like an expression factory function. For
-instance, the following defines a factory named `invert()` that
-"complements" its argument; that is, it builds a new node with type
-`tag::complement` as if Proto's `operator~` had been applied:
-
- // invert(x) is now a synonym for ~proto::as_expr(x)
- proto::functional::make_expr<proto::tag::complement> const invert = {};
-
-Such named "operators" are very important for domain-specific embedded
-languages. What's more, when defined as above, the `invert()` factory can
-accept up to `BOOST_PROTO_MAX_ARITY` arguments, although in this case
-that wouldn't be particularly meaningful.
-
-But imagine if you have a custom tag type `foo_tag<>` that is a template.
-You would like to define a `foo()` factory function that itself was a template,
-like this:
-
- template<typename T, typename A0>
- typename proto::result_of::make_expr<
- foo_tag<T>
- , A0 const &
- >::type foo(A0 const &a0)
- {
- return proto::make_expr<foo_tag<T> >(boost::ref(a0));
- }
-
-Now, users of your function can invoke it like this: `foo<int>("foo!")`. If
-you want to seamlessly handle up to /N/ argument, you have to write all /N/
-overloads yourself --- `functional::make_expr<>` can't help you. For this
-situation, Proto provides the `BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()`
-macro. You can invoke it as follows:
-
- // Generate overloads of the foo() function template
- // like the one above
- BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( \
- foo \
- , proto::default_domain \
- , (foo_tag)(typename) \
- , BOOST_PP_SEQ_NIL \
- )
-
-The first macro parameter specified the name of the function template, `foo`.
-The second parameter is the domain of the resulting expression. The third
-parameter is the tag type, specified as a Boost.Preprocessor sequence. A
-tag template like `foo_tag<typename>` is represented as a PP sequence like
-`(foo_tag)(typename)`. Had `foo_tag<>` been defined instead as
-`template<typename, int> struct foo_tag`, that would be a PP sequence like
-`(foo_tag)(typename)(int)`.
-
-The last macro parammeter, `BOOST_PP_SEQ_NIL`, is used for specifying any
-additional implicit arguments. There are none in this case, so
-`BOOST_PP_SEQ_NIL` is used to represent an empty sequence.
-
-As another example, consider a DSEL like the Boost Lambda Library, for
-which you might want a function named `construct()` for doing deferred
-construction of objects. You might want users to be able to use it like
-this:
-
- std::vector<S> buffer;
-
- // Use a lambda to construct S objects using two
- // sequences as constructor arguments:
- std::transform(
- sequence1.begin()
- , sequence1.end()
- , sequence2.begin()
- , std::back_inserter(buffer)
- , construct<S>(_1, _2) // From a hypothetical lambda DSEL
- );
-
-How might the `construct()` function be defined? We would like it to return
-a lazy function invocation that, when evaluated with two arguments, causes
-`S` objects to be constructed. Lazy functions in Proto look like this:
-
- // The type of a Proto lazy function
- proto::function<
- TheFunctionToCall
- , Argument1
- , Argument2
- , ...
- >::type
-
-In the above, `TheFunctionToCall` might be an ordinary function object, so
-let's define a `construct_helper<>` function object that constructs an object.
-
- template<typename T>
- struct construct_helper
- {
- typedef T result_type; // for TR1 result_of
-
- T operator()() const { return T(); }
-
- template<typename A0>
- T operator()(A0 const &a0) const { return T(a0); }
-
- // ... other overloads ...
- };
-
-With such a function object, we can say `construct_helper<S>()(1, 'a')` to
-immediately construct an `S` object using `1` and `'a'` as constructor
-arguments. We want this to be lazy, so we can wrap `construct_helper<S>` in
-a Proto terminal.
-
- // A lazy S constructor
- terminal<construct_helper<S> >::type const construct_S = {{}};
-
- // OK, make a lazy function invocation but don't call it.
- construct_S(1, 'a');
-
- // Calls the lazy function and constructs an S
- proto::default_context ctx;
- S s = proto::eval( construct_S(1, 'a'), ctx );
-
-We're closer, but this is not the syntax we want. Recall that we want
-users to create objects lazily with `construct<S>(_1, _2)`. We can
-get that syntax with the following:
-
- // Define the construct() function template that
- // constructs an object lazily.
- template<typename T, typename A0, typename A1>
- typename proto::result_of::make_expr<
- proto::tag::function
- , construct_helper<T> const
- , A0 const &
- , A1 const &
- >::type const
- construct(A0 const &a0, A1 const &a1)
- {
- return proto::make_expr<proto::tag::function>(
- construct_helper<T>()
- , boost::ref(a0)
- , boost::ref(a1)
- );
- }
-
-Now users can say `construct<S>(_1, _2)` and get the lazy object
-construction they want. (Making it work with `std::transform()`
-takes a little more effort, but that's covered in the
-[link boost_proto.users_guide.examples.lambda Lambda] example.)
-Now we need /N/ overloads to handle up to /N/ arguments. That's a lot
-of boiler plate, so we can use the `BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()`
-macro to simplify our job.
-
- // Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
- // construct function template like the one defined above.
- BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( \
- construct \
- , MyLambdaDomain \
- , (proto::tag::function) \
- , ((construct_helper)(typename)) \
- )
-
-What is new in this case is the fourth macro argument, which specifies
-that there is an implicit first argument to `construct()` of type
-`construct_helper<X>`, where `X` is a template parameter of the function.
-The fourth argument to the macro is actually a PP sequence of PP
-sequences. Each sequence describes one implicit argument.
-
-To see `BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()` and `construct()` in
-action, please check out the
-[link boost_proto.users_guide.examples.lambda Lambda] example.
-
-[blurb [*Ugly Macros]
-
-You may find this use of the preprocessor distasteful and decide to
-write out the overloads yourself. That's fine, but there are some good
-reasons to consider the macro.
-
-1) You may not be able to anticipate the maximum number of arguments
- your users will require. If users decide to increase
- `BOOST_PROTO_MAX_ARITY`, the macro will automatically generate
- the additional overloads for you.
-
-2) On compilers that support variadic templates, you'd rather this
- generated just one variadic function instead of /N/ overloads,
- but you'd like your code to be portable to compilers that don't
- support variadic templates. This is possible if you use the macro,
- but not otherwise. (Proto doesn't yet support variadic templates
- but it will in the future.)
-]
-
-[endsect]
-
-[endsect]
Deleted: trunk/libs/proto/doc/evaluation.qbk
==============================================================================
--- trunk/libs/proto/doc/evaluation.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
+++ (empty file)
@@ -1,547 +0,0 @@
-[/
- / Copyright (c) 2007 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)
- /]
-
-[section:expression_evaluation Expression Evaluation: Imparting Behaviors With A Context]
-
-Once you have constructed a Proto expression tree, either by using Proto's
-operator overloads or with _make_expr_ and friends, you probably want to
-actually /do/ something with it. The simplest option is to use `proto::eval()`,
-a generic expression evaluator. To use _eval_, you'll need to define a
-/context/ that tells _eval_ how each node should be evaluated. This section
-goes through the nuts and bolts of using _eval_, defining evaluation contexts,
-and using the contexts that Proto provides.
-
-[note `proto::eval()` is a less powerful but easier-to-use evaluation technique
-than Proto transforms, which are covered later. Although very powerful,
-transforms have a steep learning curve and can be more difficult to debug.
-`proto::eval()` is a rather weak tree traversal algorithm. Dan Marsden has
-been working on a more general and powerful tree traversal library. When it is
-ready, I anticipate that it will eliminate the need for `proto::eval()`.]
-
-[/================================================================]
-[section:proto_eval Evaluating An Expression with [^proto::eval()]]
-[/================================================================]
-
-[:[*Synopsis:]]
-
- namespace proto
- {
- namespace result_of
- {
- // A metafunction for calculating the return
- // type of proto::eval() given certain Expr
- // and Context types.
- template<typename Expr, typename Context>
- struct eval
- {
- typedef
- typename Context::template eval<Expr>::result_type
- type;
- };
- }
-
- namespace functional
- {
- // A callable function object type for evaluating
- // a Proto expression with a certain context.
- struct eval : callable
- {
- template<typename Sig>
- struct result;
-
- template<typename Expr, typename Context>
- typename proto::result_of::eval<Expr, Context>::type
- operator ()(Expr &expr, Context &context) const;
-
- template<typename Expr, typename Context>
- typename proto::result_of::eval<Expr, Context>::type
- operator ()(Expr &expr, Context const &context) const;
- };
- }
-
- template<typename Expr, typename Context>
- typename proto::result_of::eval<Expr, Context>::type
- eval(Expr &expr, Context &context);
-
- template<typename Expr, typename Context>
- typename proto::result_of::eval<Expr, Context>::type
- eval(Expr &expr, Context const &context);
- }
-
-Given an expression and an evaluation context, using _eval_ is quite simple.
-Simply pass the expression and the context to _eval_ and it does the rest and
-returns the result. You can use the `eval<>` metafunction in the
-`proto::result_of` namespace to compute the return type of _eval_. The
-following demonstrates a use of _eval_:
-
- template<typename Expr>
- typename proto::result_of::eval<Expr const, MyContext>::type
- MyEvaluate(Expr const &expr)
- {
- // Some user-defined context type
- MyContext ctx;
-
- // Evaluate an expression with the context
- return proto::eval(expr, ctx);
- }
-
-What _eval_ does is also very simple. It defers most of the work to the
-context itself. Here essentially is the implementation of _eval_:
-
- // eval() dispatches to a nested "eval<>" function
- // object within the Context:
- template<typename Expr, typename Context>
- typename Context::template eval<Expr>::result_type
- eval(Expr &expr, Context &ctx)
- {
- typename Context::template eval<Expr> eval_fun;
- return eval_fun(expr, ctx);
- }
-
-Really, _eval_ is nothing more than a thin wrapper that dispatches to the
-appropriate handler within the context class. In the next section, we'll see
-how to implement a context class from scratch.
-
-[endsect]
-
-[/==============================================]
-[section:contexts Defining an Evaluation Context]
-[/==============================================]
-
-As we saw in the previous section, there is really not much to the _eval_
-function. Rather, all the interesting expression evaluation goes on within
-a context class. This sections shows how to implement one from scratch.
-
-All context classes have roughly the following form:
-
- // A prototypical user-defined context.
- struct MyContext
- {
- // A nested eval<> class template
- template<
- typename Expr
- , typename Tag = typename proto::tag_of<Expr>::type
- >
- struct eval;
-
- // Handle terminal nodes here...
- template<typename Expr>
- struct eval<Expr, proto::tag::terminal>
- {
- // Must have a nested result_type typedef.
- typedef ... result_type;
-
- // Must have a function call operator that takes
- // an expression and the context.
- result_type operator()(Expr &expr, MyContext &ctx) const
- {
- return ...;
- }
- };
-
- // ... other specializations of struct eval<> ...
- };
-
-Context classes are nothing more than a collection of specializations of a
-nested `eval<>` class template. Each specialization handles a different
-expression type.
-
-In the [link boost_proto.users_guide.hello_calculator Hello Calculator]
-section, we saw an example of a user-defined context class for evaluating
-calculator expressions. That context class was implemented with the help
-of Proto's _callable_context_. If we were to implement it from scratch, it
-would look something like this:
-
- // The calculator_contest from the "Hello Calculator" section,
- // implemented from scratch.
- struct calculator_context
- {
- // The values with which we'll replace the placeholders
- std::vector<double> args;
-
- template<
- typename Expr
- // defaulted template parameters, so we can
- // specialize on the expressions that need
- // special handling.
- , typename Tag = typename proto::tag_of<Expr>::type
- , typename Arg0 = typename proto::child_c<Expr, 0>::type
- >
- struct eval;
-
- // Handle placeholder terminals here...
- template<typename Expr, int I>
- struct eval<Expr, proto::tag::terminal, placeholder<I> >
- {
- typedef double result_type;
-
- result_type operator()(Expr &, MyContext &ctx) const
- {
- return ctx.args[I];
- }
- };
-
- // Handle other terminals here...
- template<typename Expr, typename Arg0>
- struct eval<Expr, proto::tag::terminal, Arg0>
- {
- typedef double result_type;
-
- result_type operator()(Expr &expr, MyContext &) const
- {
- return proto::child(expr);
- }
- };
-
- // Handle addition here...
- template<typename Expr, typename Arg0>
- struct eval<Expr, proto::tag::plus, Arg0>
- {
- typedef double result_type;
-
- result_type operator()(Expr &expr, MyContext &ctx) const
- {
- return proto::eval(proto::left(expr), ctx)
- + proto::eval(proto::right(expr), ctx);
- }
- };
-
- // ... other eval<> specializations for other node types ...
- };
-
-Now we can use _eval_ with the context class above to evaluate calculator
-expressions as follows:
-
- // Evaluate an expression with a calculator_context
- calculator_context ctx;
- ctx.args.push_back(5);
- ctx.args.push_back(6);
- double d = proto::eval(_1 + _2, ctx);
- assert(11 == d);
-
-Defining a context from scratch this way is tedious and verbose, but it gives
-you complete control over how the expression is evaluated. The context class in
-the [link boost_proto.users_guide.hello_calculator Hello Calculator] example
-was much simpler. In the next section we'll see the helper class Proto provides
-to ease the job of implementing context classes.
-
-[endsect]
-
-[/======================================]
-[section:canned_contexts Canned Contexts]
-[/======================================]
-
-Proto provides some ready-made context classes that you can use as-is, or that
-you can use to help while implementing your own contexts. They are:
-
-[variablelist
- [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.default_context [^default_context]]]
- [An evaluation context that assigns the usual C++ meanings to all the
- operators. For example, addition nodes are handled by evaluating the
- left and right children and then adding the results. The _default_context_
- uses Boost.Typeof to deduce the types of the expressions it evaluates.] ]
- [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.null_context [^null_context]]]
- [A simple context that recursively evaluates children but does not combine
- the results in any way and returns void.] ]
- [ [[link boost_proto.users_guide.expression_evaluation.canned_contexts.callable_context [^callable_context<>]]]
- [A helper that simplifies the job of writing context classes. Rather than
- writing template specializations, with _callable_context_ you write a
- function object with an overloaded function call operator. Any expressions
- not handled by an overload are automatically dispatched to a default
- evaluation context that you can specify.] ]
-]
-
-[/=========================================]
-[section:default_context [^default_context]]
-[/=========================================]
-
-The _default_context_ is an evaluation context that assigns the usual C++
-meanings to all the operators. For example, addition nodes are handled by
-evaluating the left and right children and then adding the results. The
-_default_context_ uses Boost.Typeof to deduce the types of the expressions it
-evaluates.
-
-For example, consider the following "Hello World" example:
-
- #include <iostream>
- #include <boost/proto/proto.hpp>
- #include <boost/proto/context.hpp>
- #include <boost/typeof/std/ostream.hpp>
- using namespace boost;
-
- proto::terminal< std::ostream & >::type cout_ = { std::cout };
-
- template< typename Expr >
- void evaluate( Expr const & expr )
- {
- // Evaluate the expression with default_context,
- // to give the operators their C++ meanings:
- proto::default_context ctx;
- proto::eval(expr, ctx);
- }
-
- int main()
- {
- evaluate( cout_ << "hello" << ',' << " world" );
- return 0;
- }
-
-This program outputs the following:
-
-[pre
-hello, world
-]
-
-_default_context_ is trivially defined in terms of a `default_eval<>`
-template, as follows:
-
- // Definition of default_context
- struct default_context
- {
- template<typename Expr>
- struct eval
- : default_eval<
- Expr
- , default_context const
- , typename tag_of<Expr>::type
- >
- {};
- };
-
-There are a bunch of `default_eval<>` specializations, each of which handles
-a different C++ operator. Here, for instance, is the specialization for binary
-addition:
-
- // A default expression evaluator for binary addition
- template<typename Expr, typename Context>
- struct default_eval<Expr, Context, proto::tag::plus>
- {
- private:
- static Expr & s_expr;
- static Context & s_ctx;
-
- public:
- typedef
- decltype(
- proto::eval(proto::child_c<0>(s_expr), s_ctx)
- + proto::eval(proto::child_c<1>(s_expr), s_ctx)
- )
- result_type;
-
- result_type operator ()(Expr &expr, Context &ctx) const
- {
- return proto::eval(proto::child_c<0>(expr), ctx)
- + proto::eval(proto::child_c<1>(expr), ctx);
- }
- };
-
-The above code uses `decltype` to calculate the return type of the function
-call operator. `decltype` is a new keyword in the next version of C++ that gets
-the type of any expression. Most compilers do not yet support `decltype`
-directly, so `default_eval<>` uses the Boost.Typeof library to emulate it. On
-some compilers, that may mean that `default_context` either doesn't work or
-that it requires you to register your types with the Boost.Typeof library.
-Check the documentation for Boost.Typeof to see.
-
-[endsect]
-
-[/===================================]
-[section:null_context [^null_context]]
-[/===================================]
-
-The _null_context_ is a simple context that recursively evaluates children
-but does not combine the results in any way and returns void. It is useful
-in conjunction with `callable_context<>`, or when defining your own contexts
-which mutate an expression tree in-place rather than accumulate a result, as
-we'll see below.
-
-_null_context_ is trivially implemented in terms of `null_eval<>` as follows:
-
- // Definition of null_context
- struct null_context
- {
- template<typename Expr>
- struct eval
- : null_eval<Expr, null_context const, Expr::proto_arity::value>
- {};
- };
-
-And `null_eval<>` is also trivially implemented. Here, for instance is
-a binary `null_eval<>`:
-
- // Binary null_eval<>
- template<typename Expr, typename Context>
- struct null_eval<Expr, Context, 2>
- {
- typedef void result_type;
-
- void operator()(Expr &expr, Context &ctx) const
- {
- proto::eval(proto::child_c<0>(expr), ctx);
- proto::eval(proto::child_c<1>(expr), ctx);
- }
- };
-
-When would such classes be useful? Imagine you have an expression tree with
-integer terminals, and you would like to increment each integer in-place. You
-might define an evaluation context as follows:
-
- struct increment_ints
- {
- // By default, just evaluate all children by defering
- // to the null_eval<>
- template<typename Expr, typename Arg = proto::result_of::child<Expr>::type>
- struct eval
- : null_eval<Expr, increment_ints const>
- {};
-
- // Increment integer terminals
- template<typename Expr>
- struct eval<Expr, int>
- {
- typedef void result_type;
-
- void operator()(Expr &expr, increment_ints const &) const
- {
- ++proto::child(expr);
- }
- };
- };
-
-In the next section on _callable_context_, we'll see an even simpler way to
-achieve the same thing.
-
-[endsect]
-
-[/=============================================]
-[section:callable_context [^callable_context<>]]
-[/=============================================]
-
-The _callable_context_ is a helper that simplifies the job of writing context
-classes. Rather than writing template specializations, with _callable_context_
-you write a function object with an overloaded function call operator. Any
-expressions not handled by an overload are automatically dispatched to a
-default evaluation context that you can specify.
-
-Rather than an evaluation context in its own right, _callable_context_ is more
-properly thought of as a context adaptor. To use it, you must define your own
-context that inherits from _callable_context_.
-
-In the [link boost_proto.users_guide.expression_evaluation.canned_contexts.null_context [^null_context]]
-section, we saw how to implement an evaluation context that increments all the
-integers within an expression tree. Here is how to do the same thing with the
-_callable_context_:
-
- // An evaluation context that increments all
- // integer terminals in-place.
- struct increment_ints
- : callable_context<
- increment_ints const // derived context
- , null_context const // fall-back context
- >
- {
- typedef void result_type;
-
- // Handle int terminals here:
- void operator()(proto::tag::terminal, int &i) const
- {
- ++i;
- }
- };
-
-With such a context, we can do the following:
-
- literal<int> i = 0, j = 10;
- proto::eval( i - j * 3.14, increment_ints() );
-
- std::cout << "i = " << i.get() << std::endl;
- std::cout << "j = " << j.get() << std::endl;
-
-This program outputs the following, which shows that the integers `i` and `j`
-have been incremented by `1`:
-
-[pre
-i = 1
-j = 11
-]
-
-In the `increment_ints` context, we didn't have to define any nested `eval<>`
-templates. That's because _callable_context_ implements them for us.
-_callable_context_ takes two template parameters: the derived context and a
-fall-back context. For each node in the expression tree being evaluated,
-_callable_context_ checks to see if there is an overloaded `operator()` in the
-derived context that accepts it. Given some expression `expr` of type `Expr`,
-and a context `ctx`, it attempts to call:
-
- ctx(
- typename Expr::proto_tag()
- , proto::child_c<0>(expr)
- , proto::child_c<1>(expr)
- ...
- );
-
-Using function overloading and metaprogramming tricks, _callable_context_ can
-detect at compile-time whether such a function exists or not. If so, that
-function is called. If not, the current expression is passed to the fall-back
-evaluation context to be processed.
-
-We saw another example of the _callable_context_ when we looked at the simple
-calculator expression evaluator. There, we wanted to customize the evaluation
-of placeholder terminals, and delegate the handling of all other nodes to the
-_default_context_. We did that as follows:
-
- // An evaluation context for calculator expressions that
- // explicitly handles placeholder terminals, but defers the
- // processing of all other nodes to the default_context.
- struct calculator_context
- : proto::callable_context< calculator_context const >
- {
- std::vector<double> args;
-
- // Define the result type of the calculator.
- typedef double result_type;
-
- // Handle the placeholders:
- template<int I>
- double operator()(proto::tag::terminal, placeholder<I>) const
- {
- return this->args[I];
- }
- };
-
-In this case, we didn't specify a fall-back context. In that case,
-_callable_context_ uses the _default_context_. With the above
-`calculator_context` and a couple of appropriately defined placeholder
-terminals, we can evaluate calculator expressions, as demonstrated
-below:
-
- template<int I>
- struct placeholder
- {};
-
- terminal<placeholder<0> >::type const _1 = {{}};
- terminal<placeholder<1> >::type const _2 = {{}};
- // ...
-
- calculator_context ctx;
- ctx.args.push_back(4);
- ctx.args.push_back(5);
-
- double j = proto::eval( (_2 - _1) / _2 * 100, ctx );
- std::cout << "j = " << j << std::endl;
-
-The above code displays the following:
-
-[pre
-j = 20
-]
-
-[endsect]
-
-[endsect]
-
-[endsect]
Deleted: trunk/libs/proto/doc/extensibility.qbk
==============================================================================
--- trunk/libs/proto/doc/extensibility.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
+++ (empty file)
@@ -1,451 +0,0 @@
-[/
- / Copyright (c) 2008 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)
- /]
-
-[section:expression_extension Expression Extension: Giving Expressions Extra Smarts]
-
-In this section, we'll see how to associate Proto expressions with a /domain/,
-how to add members to expressions within a domain, how to control which
-operators are overloaded in a domain, and how to define your own "operators".
-
-[/==============]
-[section Domains]
-[/==============]
-
-In most of the examples we've seen so far, Proto has been used to construct an
-expression tree that either is evaluated with the help of a /context/ or else is
-transformed into some other object. What if you need something else? Take our old
-friend the calculator example. Perhaps we would like to build a calculator
-expression and immediately use it as a function object to a standard algorithm,
-like this:
-
- double data[] = {1., 2., 3., 4.};
-
- // Use the calculator DSEL to square each element ... HOW?
- std::transform( data, data + 4, data, _1 * _1 );
-
-By default, Proto expressions don't have interesting behaviors of their own.
-They're just trees. In particular, the expression `_1 * _1` won't have an
-`operator()` that takes a double and returns a double, like `std::transform()`
-expects. In the [link boost_proto.users_guide.getting_started.hello_calculator
-Hello Calculator] section, we learned that to make this work, we need to define an
-expression wrapper type that defines the `operator()` member function, and we
-needed to associate the wrapper with the calculator /domain/.
-
-In Proto, the term /domain/ refers to a type that associates expressions in that
-domain to an expression /generator/. The generator is just a function object that
-accepts an expression and does something to it, like wrapping it in an expression
-wrapper.
-
-You can also use a domain to associate expressions with a grammar. When you
-specify a domain's grammar, Proto ensures that all the expressions it generates in
-that domain conform to the domain's grammar. It does that by disabling any operator
-overloads that would create invalid expressions.
-
-[endsect]
-
-[/==================================================]
-[section:extends The [^extends<>] Expression Wrapper]
-[/==================================================]
-
-The first step to giving your calculator expressions extra behaviors is to
-define a calculator domain. All expressions within the calculator domain will
-be imbued with calculator-ness, as we'll see.
-
- // A type to be used as a domain tag (to be defined below)
- struct calculator_domain;
-
-We use this domain type when extending the _expr_ type, which we do with the
-_extends_ class template. Here is our expression wrapper, which imbues an
-expression with calculator-ness. It is described below.
-
- // The calculator<> expression wrapper makes expressions
- // function objects.
- template< typename Expr >
- struct calculator
- : proto::extends< Expr, calculator< Expr >, calculator_domain >
- {
- typedef
- proto::extends< Expr, calculator< Expr >, calculator_domain >
- base_type;
-
- calculator( Expr const &expr = Expr() )
- : base_type( expr )
- {}
-
- // This is usually needed because by default, the compiler-generated
- // assignment operator hides the extends<>::operator=
- using base_type::operator =;
-
- typedef double result_type;
-
- // Hide base_type::operator() by defining our own which
- // evaluates the calculator expression with a calculator context.
- result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
- {
- // As defined in the Hello Calculator section.
- calculator_context ctx;
-
- // ctx.args is a vector<double> that holds the values
- // with which we replace the placeholders (e.g., _1 and _2)
- // in the expression.
- ctx.args.push_back( d1 ); // _1 gets the value of d1
- ctx.args.push_back( d2 ); // _2 gets the value of d2
-
- return proto::eval(*this, ctx ); // evaluate the expression
- }
- };
-
-We want calculator expressions to be function objects, so we have to define an
-`operator()` that takes and returns doubles. The `calculator<>` wrapper above
-does that with the help of the _extends_ template. The first template to
-_extends_ parameter is the expression type we are extending. The second is the
-type of the wrapped expression. The third parameter is the domain that this
-wrapper is associated with. A wrapper type like `calculator<>` that inherits
-from _extends_ behaves just like the expression type it has extended, with any
-additional behaviors you choose to give it.
-
-Although not strictly necessary in this case, we bring `extends<>::operator=` into
-scope with a `using` declaration. This is really only necessary if you want
-expressions like `_1 = 3` to create a lazily evaluated assignment. _extends_
-defines the appropriate `operator=` for you, but the compiler-generated
-`calculator<>::operator=` will hide it unless you make it available with the
-`using` declaration.
-
-Note that in the implementation of `calculator<>::operator()`, we evaluate the
-expression with the `calculator_context` we defined earlier. As we saw before, the
-context is what gives the operators their meaning. In the case of the calculator,
-the context is also what defines the meaning of the placeholder terminals.
-
-Now that we have defined the `calculator<>` expression wrapper, we need to wrap the
-placeholders to imbue them with calculator-ness:
-
- calculator< proto::terminal< placeholder<0> >::type > const _1;
- calculator< proto::terminal< placeholder<1> >::type > const _2;
-
-[heading Retaining POD-ness with [^BOOST_PROTO_EXTENDS()]]
-
-To use _extends_, your extension type must derive from _extends_. Unfortunately, that means that your extension type is no longer POD and its instances cannot be /statically initialized/. (See the [link boost_proto.appendices.rationale.static_initialization Static
-Initialization] section in the [link boost_proto.appendices.rationale Rationale]
-appendix for why this matters.) In particular, as defined above, the global placeholder objects `_1` and `_2` will need to be initialized at runtime, which could lead to subtle order of initialization bugs.
-
-There is another way to make an expression extension that doesn't sacrifice POD-ness : the `BOOST_PROTO_EXTENDS()` macro. You can use it much like you use _extends_. We can use `BOOST_PROTO_EXTENDS()` to keep `calculator<>` a POD and our placeholders statically initialized.
-
- // The calculator<> expression wrapper makes expressions
- // function objects.
- template< typename Expr >
- struct calculator
- {
- // Use BOOST_PROTO_EXTENDS() instead of proto::extends<> to
- // make this type a Proto expression extension.
- BOOST_PROTO_EXTENDS(Expr, calculator<Expr>, calculator_domain)
-
- typedef double result_type;
-
- result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
- {
- /* ... as before ... */
- }
- };
-
-With the new `calculator<>` type, we can redefine our placeholders to be statically initialized:
-
- calculator< proto::terminal< placeholder<0> >::type > const _1 = {{{}}};
- calculator< proto::terminal< placeholder<1> >::type > const _2 = {{{}}};
-
-We need to make one additional small change to accomodate the POD-ness of our expression extension, which we'll describe below in the section on expression generators.
-
-What does `BOOST_PROTO_EXTENDS()` do? It defines a data member of expression type being extended; some nested typedefs that Proto requires; `operator=`, `operator[]` and `operator()` overloads for building expression templates; and a nested `result<>` template for calculating the return type of `operator()`. In this case, however, the `operator()` overloads and the `result<>` template are not needed because we are defining our own `operator()` in the `calculator<>` type. Proto provides additional macros for finer control over which member functions are defined. We could improve our `calculator<>` type as follows:
-
- // The calculator<> expression wrapper makes expressions
- // function objects.
- template< typename Expr >
- struct calculator
- {
- // Use BOOST_PROTO_BASIC_EXTENDS() instead of proto::extends<> to
- // make this type a Proto expression extension:
- BOOST_PROTO_BASIC_EXTENDS(Expr, calculator<Expr>, calculator_domain)
-
- // Define operator[] to build expression templates:
- BOOST_PROTO_EXTENDS_SUBSCRIPT()
-
- // Define operator= to build expression templates:
- BOOST_PROTO_EXTENDS_ASSIGN()
-
- typedef double result_type;
-
- result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
- {
- /* ... as before ... */
- }
- };
-
-Notice that we are now using `BOOST_PROTO_BASIC_EXTENDS()` instead of `BOOST_PROTO_EXTENDS()`. This just adds the data member and the nested typedefs but not any of the overloaded operators. Those are added separately with `BOOST_PROTO_EXTENDS_ASSIGN()` and `BOOST_PROTO_EXTENDS_SUBSCRIPT()`. We are leaving out the function call operator and the nested `result<>` tempate that could have been defined with Proto's `BOOST_PROTO_EXTENDS_FUNCTION()` macro.
-
-In summary, here are the macros you can use to define expression extensions, and a brief description of each.
-
-[def __expression__ [~expression]]
-[def __extension__ [~extension]]
-[def __domain__ [~domain]]
-
-[table Expression Extension Macros
- [[Macro]
- [Purpose]]
- [[``BOOST_PROTO_BASIC_EXTENDS(
- __expression__
- , __extension__
- , __domain__
-)``]
- [Defines a data member of type `__expression__` and some nested typedefs that Proto requires.]]
- [[`BOOST_PROTO_EXTENDS_ASSIGN()`]
- [Defines `operator=`. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
- [[`BOOST_PROTO_EXTENDS_SUBSCRIPT()`]
- [Defines `operator[]`. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
- [[`BOOST_PROTO_EXTENDS_FUNCTION()`]
- [Defines `operator()` and a nested `result<>` template for return type calculation. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
- [[``BOOST_PROTO_EXTENDS(
- __expression__
- , __extension__
- , __domain__
-)``]
- [Equivalent to:``
- BOOST_PROTO_BASIC_EXTENDS(__expression__, __extension__, __domain__)
- BOOST_PROTO_EXTENDS_ASSIGN()
- BOOST_PROTO_EXTENDS_SUBSCRIPT()
- BOOST_PROTO_EXTENDS_FUNCTION()``]]
-]
-
-[endsect]
-
-[/============================]
-[section Expression Generators]
-[/============================]
-
-The last thing that remains to be done is to tell Proto that it needs to wrap all
-of our calculator expressions in our `calculator<>` wrapper. We have already
-wrapped the placeholders, but we want /all/ expressions that involve the calculator
-placeholders to be calculators. We can do that by specifying an expression
-generator when we define our `calculator_domain`, as follows:
-
- // Define the calculator_domain we forward-declared above.
- // Specify that all expression in this domain should be wrapped
- // in the calculator<> expression wrapper.
- struct calculator_domain
- : proto::domain< proto::generator< calculator > >
- {};
-
-The first template parameter to `proto::domain<>` is the generator. "Generator" is just a fancy name for a function object that accepts an expression and does something to it. `proto::generator<>` is a very simple one --- it wraps an expression in the wrapper you specify. `proto::domain<>` inherits from its generator parameter, so all domains are themselves function objects.
-
-If we used `BOOST_PROTO_EXTENDS()` to keep our expression extension type POD, then we need to use `proto::pod_generatro<>` instead of `proto::generator<>`, as follows:
-
- // If calculator<> uses BOOST_PROTO_EXTENDS() instead of
- // use proto::extends<>, use proto::pod_generator<> instead
- // of proto::generator<>.
- struct calculator_domain
- : proto::domain< proto::pod_generator< calculator > >
- {};
-
-[def __Domain__ [~Domain]]
-
-After Proto has calculated a new expression type, it checks the domains of the child expressions. They must match. Assuming they do, Proto creates the new expression and passes it to `__Domain__::operator()` for any additional processing. If we don't specify a generator, the new expression gets passed through unchanged. But since we've specified a generator above, `calculator_domain::operator()` returns `calculator<>` objects.
-
-Now we can use calculator expressions as function objects to STL algorithms, as
-follows:
-
- double data[] = {1., 2., 3., 4.};
-
- // Use the calculator DSEL to square each element ... WORKS! :-)
- std::transform( data, data + 4, data, _1 * _1 );
-
-[endsect]
-
-[/==========================================================]
-[section:inhibiting_overloads Controlling Operator Overloads]
-[/==========================================================]
-
-By default, Proto defines every possible operator overload for Protofied
-expressions. This makes it simple to bang together a DSEL, and Proto's grammar
-building and checking facilities make it simple to detect and report invalid
-expressions. In some cases, however, the presence of Proto's promiscuous
-overloads can lead to confusion or worse. When that happens, you'll have to
-disable some of Proto's overloaded operators.
-
-As an example, consider a simple linear algebra DSEL that lets you efficiently
-add vectors without creating temporaries. With such a DSEL, we could initialize
-vectors and add them as follows:
-
- // lazy_vectors with 4 elements each.
- lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
-
- // Add two vectors lazily and get the 2nd element.
- double d1 = ( v2 + v3 )[ 2 ]; // Look ma, no temporaries!
-
- // Subtract two vectors and add the result to a third vector.
- v1 += v2 - v3; // Still no temporaries!
-
-Consider the uses of the `operator[]` and `operator+=` in the examples above.
-We want them to do real work instead of creating expression templates. We need
-to imbue our expression templates with linear algebra-ness and then give
-`operator[]` and `operator+=` new domain-specific semantics. As above, we do
-that by defining an appropriate domain-specific expression wrapper.
-
-Here is the code. It is described below.
-
- struct lazy_vector_domain;
-
- // Here is an evaluation context that indexes into an algebraic
- // expression, and combines the result.
- template<typename Size = std::size_t>
- struct lazy_subscript_context
- {
- lazy_subscript_context(Size subscript)
- : subscript_(subscript)
- {}
-
- // Use default_eval for all the operations ...
- template<typename Expr, typename Tag = typename Expr::proto_tag>
- struct eval
- : proto::default_eval<Expr, lazy_subscript_context>
- {};
-
- // ... except for terminals, which we index with our subscript
- template<typename Expr>
- struct eval<Expr, proto::tag::terminal>
- {
- typedef
- typename proto::result_of::child<Expr>::type::value_type
- result_type;
-
- result_type
- operator()( Expr const & expr, lazy_subscript_context & ctx ) const
- {
- return proto::child( expr )[ ctx.subscript_ ];
- }
- };
-
- Size subscript_;
- };
-
- // Here is the domain-specific expression wrapper, which overrides
- // operator[] to evaluate the expression using the lazy_subscript_context.
- template<typename Expr>
- struct lazy_vector_expr
- : proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
- {
- typedef
- proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
- base_type;
-
- lazy_vector_expr( Expr const & expr = Expr() )
- : base_type( expr )
- {}
-
- template< typename Size >
- typename proto::result_of::eval< Expr, lazy_subscript_context<Size> >::type
- operator []( Size subscript ) const
- {
- lazy_subscript_context<Size> ctx(subscript);
- return proto::eval(*this, ctx);
- }
- };
-
- // Here is our lazy_vector terminal, implemented in terms of lazy_vector_expr
- template< typename T >
- struct lazy_vector
- : lazy_vector_expr< typename proto::terminal< std::vector<T> >::type >
- {
- typedef typename proto::terminal< std::vector<T> >::type expr_type;
-
- lazy_vector( std::size_t size = 0, T const & value = T() )
- : lazy_vector_expr<expr_type>(
- expr_type::make( std::vector<T>( size, value ) )
- )
- {}
-
- template< typename Expr >
- lazy_vector &operator += (Expr const & expr)
- {
- std::size_t size = proto::child(*this).size();
- for(std::size_t i = 0; i < size; ++i)
- {
- proto::child(*this)[i] += expr[i];
- }
- return *this;
- }
- };
-
- struct lazy_vector_domain
- : proto::domain< proto::generator< lazy_vector_expr > >
- {};
-
-The `lazy_subscript_context<>` struct is used to evaluate expressions like
-`(v1 + v2)[2]` as if they were written `v1[2] + v2[2]`. The `lazy_vector_expr<>`
-struct is a wrapper for expressions. It defines an `operator[]` which evaluates
-the expression using `lazy_subscript_context<>`. The `lazy_vector<>` struct is
-used for the vector terminals in our expression trees. It is essentially a
-`proto::terminal< std::vector<T> >::type`, with `operator[]` and `operator+=`
-defined to evaluate the expressions. With the above code, we can do the
-following:
-
- // lazy_vectors with 4 elements each.
- lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
-
- // Add two vectors lazily and get the 2nd element.
- double d1 = ( v2 + v3 )[ 2 ]; // Look ma, no temporaries!
-
- // Subtract two vectors and add the result to a third vector.
- v1 += v2 - v3; // Hmm, trouble here.
-
- // What does this do?
- (v2 + v3) += v1;
-
-The line `v1 += v2 - v3` is somewhat ambiguous. Clearly we want it to use the
-`lazy_vector<>::operator+=` we defined above, but it could also mean to
-construct an even larger expression template using Proto's `operator+=`. At
-least one compiler actually believes the call to be ambiguous! We have to tell
-the compiler which.
-
-And the last line is clearly a bug. It is nonsensical to add two vectors and
-then assign /to/ the result. But strangely, this line of code compiles! And even
-more strangely, it has no effect! It is building an expression template and then
-discarding it. We would like this to be a compile error, instead. We can make
-it an error, and solve the ambiguity problem, by disabling Proto's `operator+=`
-overload, and all the other overloaded operators that don't make sense in our
-domain. To do that, we define the grammar for our domain. Let's say we want to
-allow addition and subtraction of our vector terminals. Our grammar looks like
-this:
-
- using proto::_;
-
- struct LazyVectorGrammar
- : proto::or_<
- proto::terminal< std::vector<_> >
- , proto::plus< LazyVectorGrammar, LazyVectorGrammar>
- , proto::minus< LazyVectorGrammar, LazyVectorGrammar>
- >
- {};
-
-Notice that even though the terminals of our DSEL are `lazy_vector<>`'s, they
-will match `terminal< std::vector<_> >` because `lazy_vector<T>` extends
-`terminal< std::vector<T> >::type`. Once we have defined the grammar of our
-DSEL, using it to control the operator overloads in our domain is as simple
-as:
-
- // Expressions in the lazy_vector_domain must conform to the
- // LazyVectorGrammar
- struct lazy_vector_domain
- : proto::domain<
- proto::generator< lazy_vector_expr >
- , LazyVectorGrammar
- >
- {};
-
-And that's it! Now, all operators that do not produce valid lazy vector
-expressions are automatically disabled.
-
-[endsect]
-
-[endsect]
Added: trunk/libs/proto/doc/front_end.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/proto/doc/front_end.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,553 @@
+[/
+ / Copyright (c) 2007 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)
+ /]
+
+[/================================================================================]
+[section:front_end Fronts Ends:
+ Defining Terminals and Non-Terminals of Your DSEL]
+[/================================================================================]
+
+Here is the fun part: designing your own mini-programming language. In this section we'll talk about the nuts and bolts of designing a DSEL interface using Proto. We'll cover the definition of terminals and lazy functions that the users of your DSEL will get to program with. We'll also talk about Proto's expression template-building operator overloads, and about ways to add additional members to expressions within your domain.
+
+[/=======================]
+[section Making Terminals]
+[/=======================]
+
+As we saw with the Calculator example from the Introduction, the simplest way to get a DSEL up and running is simply to define some terminals, as follows.
+
+ // Define a literal integer Proto expression.
+ proto::terminal<int>::type i = {0};
+
+ // This creates an expression template.
+ i + 1;
+
+With some terminals and Proto's operator overloads, you can immediately start creating expression templates.
+
+Defining terminals -- with aggregate initialization -- can be a little awkward at times. Proto provides an easier-to-use wrapper for literals that can be used to construct Protofied terminal expressions. It's called _literal_.
+
+ // Define a literal integer Proto expression.
+ proto::literal<int> i = 0;
+
+ // Proto literals are really just Proto terminal expressions.
+ // For example, this build a Proto expression template:
+ i + 1;
+
+There is also a _lit_ function for constructing a _literal_ in-place. The above expression can simply be written as:
+
+ // proto::lit(0) creates an integer terminal expression
+ proto::lit(0) + 1;
+
+[endsect]
+
+[/=================================]
+[section Proto's Operator Overloads]
+[/=================================]
+
+Once we have some Proto terminals, expressions involving those terminals build expression trees for us. Proto defines overloads for each of C++'s overloadable operators in the `boost::proto` namespace. As long as one operand is a Proto expression, the result of the operation is a tree node representing that operation.
+
+[note Proto's operator overloads live in the `boost::proto` namespace and are found via ADL (argument-dependent lookup). That is why expressions must be "tainted" with Proto-ness for Proto to be able to build trees out of expressions.]
+
+As a result of Proto's operator overloads, we can say:
+
+ -_1; // OK, build a unary-negate tree node
+ _1 + 42; // OK, build a binary-plus tree node
+
+For the most part, this Just Works and you don't need to think about it, but a few operators are special and it can be helpful to know how Proto handles them.
+
+[/=========================================================]
+[heading Assignment, Subscript, and Function Call Operators]
+[/=========================================================]
+
+Proto also overloads `operator=`, `operator[]`, and `operator()`, but these operators are member functions of the expression template rather than free functions in Proto's namespace. The following are valid Proto expressions:
+
+ _1 = 5; // OK, builds a binary assign tree node
+ _1[6]; // OK, builds a binary subscript tree node
+ _1(); // OK, builds a unary function tree node
+ _1(7); // OK, builds a binary function tree node
+ _1(8,9); // OK, builds a ternary function tree node
+ // ... etc.
+
+For the first two lines, assigment and subscript, it should be fairly unsurprising
+that the resulting expression node should be binary. After all, there are
+two operands in each expression. It may be surprising at first that what appears
+to be a function call with no arguments, `_1()`, actually creates an expression
+node with one child. The child is `_1` itself. Likewise, the expression `_1(7)`
+has two children: `_1` and `7`.
+
+Because these operators can only be defined as member functions, the following expressions are invalid:
+
+ int i;
+ i = _1; // ERROR: cannot assign _1 to an int
+
+ int *p;
+ p[_1]; // ERROR: cannot use _1 as an index
+
+ std::sin(_1); // ERROR: cannot call std::sin() with _1
+
+Also, C++ has special rules for overloads of `operator->` that make it useless
+for building expression templates, so Proto does not overload it.
+
+[/==============================]
+[heading The Address-Of Operator]
+[/==============================]
+
+Proto overloads the address-of operator for expression types, so that the
+following code creates a new unary address-of tree node:
+
+ &_1; // OK, creates a unary address-of tree node
+
+It does /not/ return the address of the `_1` object. However, there is
+special code in Proto such that a unary address-of node is implicitly
+convertible to a pointer to its child. In other words, the following
+code works and does what you might expect, but not in the obvious way:
+
+ typedef
+ proto::terminal< placeholder<0> >::type
+ _1_type;
+
+ _1_type const _1 = {{}};
+ _1_type const * p = &_1; // OK, &_1 implicitly converted
+
+[endsect]
+
+[/============================]
+[section Making Lazy Functions]
+[/============================]
+
+If we limitted ourselves to nothing but terminals and operator overloads, our domain-specific embedded languages wouldn't be very expressive. Imagine that we wanted to extend our calculator DSEL with a full suite of math functions like `sin()` and `pow()` that we could invoke lazily as follows.
+
+ // A calculator expression that takes one argument
+ // and takes the sine of it.
+ sin(_1);
+
+We would like the above to create an expression template representing a function invocation. When that expression is evaluated, it should cause the function to be invoked. (At least, that's the meaning of function invocation we'd like the calculator DSEL to have.) You can define `sin` quite simply as follows.
+
+ // "sin" is a Proto terminal containing a function pointer
+ proto::terminal< double(*)(double) >::type const sin = {&std::sin};
+
+In the above, we define `sin` as a Proto terminal containing a pointer to the `std::sin()` function. Now we can use `sin` as a lazy function. The `default_context` that we saw in the Introduction knows how to evaluate lazy functions. Consider the following:
+
+ double pi = 3.1415926535;
+ proto::default_context ctx;
+ // Create a lazy "sin" invocation and immediately evaluate it
+ std::cout << proto::eval( sin(pi/2), ctx ) << std::endl;
+
+The above code prints out:
+
+[pre 1]
+
+It is important to note that there is nothing special about terminals that contain function pointers. /Any/ Proto expression has an overloaded function call operator. Consider:
+
+ // This compiles!
+ proto::lit(1)(2)(3,4)(5,6,7,8);
+
+That may look strange at first. It creates an integer terminal with _lit_, and then invokes it like a function again and again. What does it mean? To be sure, the `default_context` wouldn't know what to do with it. The `default_context` only knows how to evaluate expressions that are sufficiently C++-like. In the case of function call expressions, the left hand side must evaluate to something that can be invoked: a pointer to a function, a reference to a function, or a TR1-style function object. That doesn't stop you from defining your own evaluation context that gives that expression a meaning. But more on that later.
+
+[/=======================================]
+[heading Making Lazy Functions, Continued]
+[/=======================================]
+
+Now, what if we wanted to add a `pow()` function to our calculator DSEL that users could invoke as follow.
+
+ // A calculator expression that takes one argument
+ // and raises it to the 2nd power
+ pow< 2 >(_1);
+
+The simple technique described above of making `pow` a terminal containing a function pointer doesn't work here. If `pow` is an object, then the expression `pow< 2 >(_1)` is not valid C++. `pow` needs to be a real function template. But it must be an unusual function; it must return an expression template.
+
+Before we can write the `pow()` function, we need a function object that wraps an invocation of `std::pow()`.
+
+ // Define a pow_fun function object
+ template<int Exp>
+ struct pow_fun
+ {
+ typedef double result_type;
+ double operator()(double d) const
+ {
+ return std::pow(d, Exp);
+ }
+ };
+
+Now, let's try to define a function template that returns an expression template. We'll use the `proto::function<>` metafunction to calculate the type of a Proto expression that represents a function call. It is analogous to _terminal_. (We'll see a couple of different ways to solve this problem, and each will demonstrate another utility for defining Proto front-ends.)
+
+ // Define a lazy pow() function for the calculator DSEL.
+ // Can be used as: pow< 2 >(_1)
+ template<int Exp, typename Arg>
+ typename proto::function<
+ typename proto::terminal<pow_fun<Exp> >::type
+ , Arg const &
+ >::type
+ pow(Arg const &arg)
+ {
+ typedef
+ typename proto::function<
+ typename proto::terminal<pow_fun<Exp> >::type
+ , Arg const &
+ >::type
+ result_type;
+
+ result_type result = {{{}}, arg};
+ return result;
+ }
+
+In the code above, notice how the `proto::function<>` and _terminal_ metafunctions are used to calculate the return type: `pow()` returns an expression template representing a function call where the first child is the function to call and the second is the argument to the function. (Unfortunately, the same type calculation is repeated in the body of the function so that we can initialize a local variable of the correct type. We'll see in a moment how to avoid that.)
+
+[note As with `proto::function<>`, there are metafunctions corresponding to all of the overloadable C++ operators for calculation expression types.]
+
+With the above definition of the `pow()` function, we can create calculator expressions like the one below and evaluate them using the `calcuator_context` we implemented in the Introduction.
+
+ // Initialize a calculator context
+ calculator_context ctx;
+ ctx.args.push_back(3); // let _1 be 3
+
+ // Create a calculator expression that takes one argument,
+ // adds one to it, and raises it to the 2nd power; and then
+ // immediately evaluate it using the calculator_context.
+ assert( 16 == proto::eval( pow<2>( _1 + 1 ), ctx ) );
+
+[/=========================================]
+[heading Protofying Lazy Function Arguments]
+[/=========================================]
+
+Above, we defined a `pow()` function template that returns an expression template representing a lazy function invocation. But if we tried to call it as below, we'll run into a problem.
+
+ // ERROR: pow() as defined above doesn't work when
+ // called with a non-Proto argument.
+ pow< 2 >( 4 );
+
+Proto expressions can only have other Proto expressions as children. But if we look at `pow()`'s function signature, we can see that if we pass it a non-Proto object, it will try to make it a child.
+
+ template<int Exp, typename Arg>
+ typename proto::function<
+ typename proto::terminal<pow_fun<Exp> >::type
+ , Arg const & // <=== ERROR! This may not be a Proto type!
+ >::type
+ pow(Arg const &arg)
+
+What we want is a way to make `Arg` into a Proto terminal if it is not a Proto expression already, and leave it alone if it is. For that, we can use _as_child_. The following implementation of the `pow()` function handles all argument types, expression templates or otherwise.
+
+ // Define a lazy pow() function for the calculator DSEL. Use
+ // proto::as_child() to Protofy the argument, but only if it
+ // is not a Proto expression type to begin with!
+ template<int Exp, typename Arg>
+ typename proto::function<
+ typename proto::terminal<pow_fun<Exp> >::type
+ , typename proto::result_of::as_child<Arg const>::type
+ >::type
+ pow(Arg const &arg)
+ {
+ typedef
+ typename proto::function<
+ typename proto::terminal<pow_fun<Exp> >::type
+ , typename proto::result_of::as_child<Arg const>::type
+ >::type
+ result_type;
+
+ result_type result = {{{}}, proto::as_child(arg)};
+ return result;
+ }
+
+Notice how we use the `proto::result_of::as_child<>` metafunction to calculate the return type, and the `proto::as_child()` function to actually normalize the argument.
+
+[/=====================================================]
+[heading Lazy Functions Made Simple With [^make_expr()]]
+[/=====================================================]
+
+The versions of the `pow()` function we've seen above are rather verbose. In the return type calculation, you have to be very explicit about wrapping non-Proto types. Worse, you have to restate the return type calculation in the body of `pow()` itself. Proto provides a helper for building expression templates directly that handle these mundane details for you. It's called _make_expr_. We can redefine `pow()` with it as below.
+
+ // Define a lazy pow() function for the calculator DSEL.
+ // Can be used as: pow< 2 >(_1)
+ template<int Exp, typename Arg>
+ typename proto::result_of::make_expr<
+ proto::tag::function // Tag type
+ , pow_fun<Exp> // First child (by value)
+ , Arg const & // Second child (by reference)
+ >::type
+ pow(Arg const &arg)
+ {
+ return proto::make_expr<proto::tag::function>(
+ pow_fun<Exp>() // First child (by value)
+ , boost::ref(arg) // Second child (by reference)
+ );
+ }
+
+There are some things to notice about the above code. We use `proto::result_of::make_expr<>` to calculate the return type. The first template parameter is the tag type for the expression node we're building -- in this case, `proto::tag::function`, which is the tag type Proto uses for function call expressions.
+
+Subsequent template parameters to `proto::result_of::make_expr<>` represent children nodes. If a child type is not already a Proto expression, it is made into a terminal with _as_child_. A type such as `pow_fun<Exp>` results in terminal that is held by value, whereas a type like `Arg const &` (note the reference) indicates that the result should be held by reference.
+
+In the function body is the runtime invocation of _make_expr_. It closely mirrors the return type calculation. _make_expr_ requires you to specify the node's tag type as a template parameter. The arguments to the function become the node's children. When a child should be stored by value, nothing special needs to be done. When a child should be stored by reference, you must use the `boost::ref()` function to wrap the argument. Without this extra information, the _make_expr_ function couldn't know whether to store a child by value or by reference.
+
+[endsect]
+
+[/==============================================]
+[section Adding Members By Extending Expressions]
+[/==============================================]
+
+In this section, we'll see how to associate Proto expressions with a /domain/, how to add members to expressions within a domain, and how to control which operators are overloaded in a domain.
+
+[/==============]
+[section Domains]
+[/==============]
+
+In the [link boost_proto.users_guide.getting_started.hello_calculator Hello Calculator] section, we looked into making calculator expressions directly usable as lambda expressions in calls to STL algorithms, as below:
+
+ double data[] = {1., 2., 3., 4.};
+
+ // Use the calculator DSEL to square each element ... HOW?
+ std::transform( data, data + 4, data, _1 * _1 );
+
+The difficulty, if you recall, was that by default Proto expressions don't have interesting behaviors of their own. They're just trees. In particular, the expression `_1 * _1` won't have an `operator()` that takes a double and returns a double like `std::transform()` expects -- unless we give it one. To make this work, we needed to define an expression wrapper type that defined the `operator()` member function, and we needed to associate the wrapper with the calculator /domain/.
+
+In Proto, the term /domain/ refers to a type that associates expressions in that domain to an expression /generator/. The generator is just a function object that accepts an expression and does something to it, like wrapping it in an expression wrapper.
+
+You can also use a domain to associate expressions with a grammar. When you specify a domain's grammar, Proto ensures that all the expressions it generates in that domain conform to the domain's grammar. It does that by disabling any operator overloads that would create invalid expressions.
+
+[endsect]
+
+[/==================================================]
+[section:extends The [^extends<>] Expression Wrapper]
+[/==================================================]
+
+The first step to giving your calculator expressions extra behaviors is to define a calculator domain. All expressions within the calculator domain will be imbued with calculator-ness, as we'll see.
+
+ // A type to be used as a domain tag (to be defined below)
+ struct calculator_domain;
+
+We use this domain type when extending the _expr_ type, which we do with the _extends_ class template. Here is our expression wrapper, which imbues an expression with calculator-ness. It is described below.
+
+ // The calculator<> expression wrapper makes expressions
+ // function objects.
+ template< typename Expr >
+ struct calculator
+ : proto::extends< Expr, calculator< Expr >, calculator_domain >
+ {
+ typedef
+ proto::extends< Expr, calculator< Expr >, calculator_domain >
+ base_type;
+
+ calculator( Expr const &expr = Expr() )
+ : base_type( expr )
+ {}
+
+ // This is usually needed because by default, the compiler-
+ // generated assignment operator hides extends<>::operator=
+ using base_type::operator =;
+
+ typedef double result_type;
+
+ // Hide base_type::operator() by defining our own which
+ // evaluates the calculator expression with a calculator context.
+ result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
+ {
+ // As defined in the Hello Calculator section.
+ calculator_context ctx;
+
+ // ctx.args is a vector<double> that holds the values
+ // with which we replace the placeholders (e.g., _1 and _2)
+ // in the expression.
+ ctx.args.push_back( d1 ); // _1 gets the value of d1
+ ctx.args.push_back( d2 ); // _2 gets the value of d2
+
+ return proto::eval(*this, ctx ); // evaluate the expression
+ }
+ };
+
+We want calculator expressions to be function objects, so we have to define an `operator()` that takes and returns doubles. The `calculator<>` wrapper above does that with the help of the _extends_ template. The first template to _extends_ parameter is the expression type we are extending. The second is the type of the wrapped expression. The third parameter is the domain that this wrapper is associated with. A wrapper type like `calculator<>` that inherits from _extends_ behaves just like the expression type it has extended, with any additional behaviors you choose to give it.
+
+Although not strictly necessary in this case, we bring `extends<>::operator=` into scope with a `using` declaration. This is really only necessary if you want expressions like `_1 = 3` to create a lazily evaluated assignment. _extends_ defines the appropriate `operator=` for you, but the compiler-generated `calculator<>::operator=` will hide it unless you make it available with the `using` declaration.
+
+Note that in the implementation of `calculator<>::operator()`, we evaluate the expression with the `calculator_context` we defined earlier. As we saw before, the context is what gives the operators their meaning. In the case of the calculator, the context is also what defines the meaning of the placeholder terminals.
+
+Now that we have defined the `calculator<>` expression wrapper, we need to wrap the placeholders to imbue them with calculator-ness:
+
+ calculator< proto::terminal< placeholder<0> >::type > const _1;
+ calculator< proto::terminal< placeholder<1> >::type > const _2;
+
+[/=======================================================]
+[heading Retaining POD-ness with [^BOOST_PROTO_EXTENDS()]]
+[/=======================================================]
+
+To use _extends_, your extension type must derive from _extends_. Unfortunately, that means that your extension type is no longer POD and its instances cannot be /statically initialized/. (See the [link boost_proto.appendices.rationale.static_initialization Static
+Initialization] section in the [link boost_proto.appendices.rationale Rationale] appendix for why this matters.) In particular, as defined above, the global placeholder objects `_1` and `_2` will need to be initialized at runtime, which could lead to subtle order of initialization bugs.
+
+There is another way to make an expression extension that doesn't sacrifice POD-ness : the `BOOST_PROTO_EXTENDS()` macro. You can use it much like you use _extends_. We can use `BOOST_PROTO_EXTENDS()` to keep `calculator<>` a POD and our placeholders statically initialized.
+
+ // The calculator<> expression wrapper makes expressions
+ // function objects.
+ template< typename Expr >
+ struct calculator
+ {
+ // Use BOOST_PROTO_EXTENDS() instead of proto::extends<> to
+ // make this type a Proto expression extension.
+ BOOST_PROTO_EXTENDS(Expr, calculator<Expr>, calculator_domain)
+
+ typedef double result_type;
+
+ result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
+ {
+ /* ... as before ... */
+ }
+ };
+
+With the new `calculator<>` type, we can redefine our placeholders to be statically initialized:
+
+ calculator< proto::terminal< placeholder<0> >::type > const _1 = {{{}}};
+ calculator< proto::terminal< placeholder<1> >::type > const _2 = {{{}}};
+
+We need to make one additional small change to accomodate the POD-ness of our expression extension, which we'll describe below in the section on expression generators.
+
+What does `BOOST_PROTO_EXTENDS()` do? It defines a data member of expression type being extended; some nested typedefs that Proto requires; `operator=`, `operator[]` and `operator()` overloads for building expression templates; and a nested `result<>` template for calculating the return type of `operator()`. In this case, however, the `operator()` overloads and the `result<>` template are not needed because we are defining our own `operator()` in the `calculator<>` type. Proto provides additional macros for finer control over which member functions are defined. We could improve our `calculator<>` type as follows:
+
+ // The calculator<> expression wrapper makes expressions
+ // function objects.
+ template< typename Expr >
+ struct calculator
+ {
+ // Use BOOST_PROTO_BASIC_EXTENDS() instead of proto::extends<> to
+ // make this type a Proto expression extension:
+ BOOST_PROTO_BASIC_EXTENDS(Expr, calculator<Expr>, calculator_domain)
+
+ // Define operator[] to build expression templates:
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ // Define operator= to build expression templates:
+ BOOST_PROTO_EXTENDS_ASSIGN()
+
+ typedef double result_type;
+
+ result_type operator()( double d1 = 0.0, double d2 = 0.0 ) const
+ {
+ /* ... as before ... */
+ }
+ };
+
+Notice that we are now using `BOOST_PROTO_BASIC_EXTENDS()` instead of `BOOST_PROTO_EXTENDS()`. This just adds the data member and the nested typedefs but not any of the overloaded operators. Those are added separately with `BOOST_PROTO_EXTENDS_ASSIGN()` and `BOOST_PROTO_EXTENDS_SUBSCRIPT()`. We are leaving out the function call operator and the nested `result<>` tempate that could have been defined with Proto's `BOOST_PROTO_EXTENDS_FUNCTION()` macro.
+
+In summary, here are the macros you can use to define expression extensions, and a brief description of each.
+
+[def __expression__ [~expression]]
+[def __extension__ [~extension]]
+[def __domain__ [~domain]]
+
+[table Expression Extension Macros
+ [[Macro]
+ [Purpose]]
+ [[``BOOST_PROTO_BASIC_EXTENDS(
+ __expression__
+ , __extension__
+ , __domain__
+)``]
+ [Defines a data member of type `__expression__` and some nested typedefs that Proto requires.]]
+ [[`BOOST_PROTO_EXTENDS_ASSIGN()`]
+ [Defines `operator=`. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
+ [[`BOOST_PROTO_EXTENDS_SUBSCRIPT()`]
+ [Defines `operator[]`. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
+ [[`BOOST_PROTO_EXTENDS_FUNCTION()`]
+ [Defines `operator()` and a nested `result<>` template for return type calculation. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]]
+ [[``BOOST_PROTO_EXTENDS(
+ __expression__
+ , __extension__
+ , __domain__
+)``]
+ [Equivalent to:``
+ BOOST_PROTO_BASIC_EXTENDS(__expression__, __extension__, __domain__)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+ BOOST_PROTO_EXTENDS_FUNCTION()``]]
+]
+
+[endsect]
+
+[/============================]
+[section Expression Generators]
+[/============================]
+
+The last thing that remains to be done is to tell Proto that it needs to wrap all of our calculator expressions in our `calculator<>` wrapper. We have already wrapped the placeholders, but we want /all/ expressions that involve the calculator placeholders to be calculators. We can do that by specifying an expression generator when we define our `calculator_domain`, as follows:
+
+ // Define the calculator_domain we forward-declared above.
+ // Specify that all expression in this domain should be wrapped
+ // in the calculator<> expression wrapper.
+ struct calculator_domain
+ : proto::domain< proto::generator< calculator > >
+ {};
+
+The first template parameter to `proto::domain<>` is the generator. "Generator" is just a fancy name for a function object that accepts an expression and does something to it. `proto::generator<>` is a very simple one --- it wraps an expression in the wrapper you specify. `proto::domain<>` inherits from its generator parameter, so all domains are themselves function objects.
+
+If we used `BOOST_PROTO_EXTENDS()` to keep our expression extension type POD, then we need to use `proto::pod_generatro<>` instead of `proto::generator<>`, as follows:
+
+ // If calculator<> uses BOOST_PROTO_EXTENDS() instead of
+ // use proto::extends<>, use proto::pod_generator<> instead
+ // of proto::generator<>.
+ struct calculator_domain
+ : proto::domain< proto::pod_generator< calculator > >
+ {};
+
+[def __Domain__ [~Domain]]
+
+After Proto has calculated a new expression type, it checks the domains of the child expressions. They must match. Assuming they do, Proto creates the new expression and passes it to `__Domain__::operator()` for any additional processing. If we don't specify a generator, the new expression gets passed through unchanged. But since we've specified a generator above, `calculator_domain::operator()` returns `calculator<>` objects.
+
+Now we can use calculator expressions as function objects to STL algorithms, as follows:
+
+ double data[] = {1., 2., 3., 4.};
+
+ // Use the calculator DSEL to square each element ... WORKS! :-)
+ std::transform( data, data + 4, data, _1 * _1 );
+
+[endsect]
+
+[/==========================================================]
+[section:inhibiting_overloads Controlling Operator Overloads]
+[/==========================================================]
+
+By default, Proto defines every possible operator overload for Protofied
+expressions. This makes it simple to bang together a DSEL. In some cases, however, the presence of Proto's promiscuous overloads can lead to confusion or worse. When that happens, you'll have to disable some of Proto's overloaded operators. That is done by defining the grammar for your domain and specifying it as the second parameter of the _domain_ template.
+
+In the [link boost_proto.users_guide.getting_started.hello_calculator Hello Calculator] section, we saw an example of a Proto grammar, which is repeated here:
+
+ // Define the grammar of calculator expressions
+ struct calculator_grammar
+ : proto::or_<
+ proto::plus< calculator_grammar, calculator_grammar >
+ , proto::minus< calculator_grammar, calculator_grammar >
+ , proto::multiplies< calculator_grammar, calculator_grammar >
+ , proto::divides< calculator_grammar, calculator_grammar >
+ , proto::terminal< proto::_ >
+ >
+ {};
+
+We'll have much more to say about grammars in subsequent sections, but for now, we'll just say that the `calculator_grammar` struct describes a subset of all expression types -- the subset that comprise valid calculator expressions. We would like to prohibit Proto from creating a calculator expression that does not conform to this grammar. We do that by changing the definition of the `calculator_domain` struct.
+
+[def __calculator_grammar__ [*calculator_grammar]]
+
+ // Define the calculator_domain. Expressions in the calculator
+ // domain are wrapped in the calculator<> wrapper, and they must
+ // conform to the calculator_grammar:
+ struct calculator_domain
+ : proto::domain< proto::generator< calculator >, __calculator_grammar__ >
+ {};
+
+The only new addition is `calculator_grammar` as the second template parameter to the _domain_ template. That has the effect of disabling any of Proto's operator overloads that would create an invalid calculator expression.
+
+Another common use for this feature would be to disable Proto's unary `operator&` overload. It may be surprising for users of your DSEL that they cannot take the address of their expressions! You can very easily disable Proto's unary `operator&` overload for your domain with a very simple grammar, as below:
+
+ // For expressions in my_domain, disable Proto's
+ // unary address-of operator.
+ struct my_domain
+ : proto::domain<
+ proto::generator< my_wrapper >
+ // A simple grammar that matches any expression that
+ // is not a unary address-of expression.
+ , proto::not_< proto::address_of< _ > >
+ >
+ {};
+
+The type `proto::not_< proto::address_of< _ > >` is a very simple grammar that matches all expressions except unary address-of expressions. In the section describing Proto's intermediate form, we'll have much more to say about grammars.
+
+[endsect]
+
+[endsect]
+
+[endsect]
Deleted: trunk/libs/proto/doc/grammars.qbk
==============================================================================
--- trunk/libs/proto/doc/grammars.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
+++ (empty file)
@@ -1,624 +0,0 @@
-[/
- / Copyright (c) 2008 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)
- /]
-
-[/============================================================================]
-[section:expression_introspection Expression Introspection: Defining a Grammar]
-[/============================================================================]
-
-Expression trees can have a very rich and complicated structure. Often, you
-need to know some things about an expression's structure before you can process
-it. This section describes the tools Proto provides for peering inside an
-expression tree and discovering its structure. And as you'll see in later
-sections, all the really interesting things you can do with Proto begin right
-here.
-
-[/===============================================]
-[section:patterns Finding Patterns In Expressions]
-[/===============================================]
-
-Imagine your DSEL is a miniature I/O facility, with iostream operations
-that execute lazily. You might want expressions representing input operations
-to be processed by one function, and output operations to be processed by a
-different function. How would you do that?
-
-The answer is to write patterns (a.k.a, /grammars/) that match the structure
-of input and output expressions. Proto provides utilities for defining the
-grammars, and the _matches_ template for checking whether a given expression
-type matches the grammar.
-
-First, let's define some terminals we can use in our lazy I/O expressions:
-
- proto::terminal< std::istream & >::type cin_ = { std::cin };
- proto::terminal< std::ostream & >::type cout_ = { std::cout };
-
-Now, we can use `cout_` instead of `std::cout`, and get I/O expression trees
-that we can execute later. To define grammars that match intput and output
-expressions of the form `cin_ >> i` and `cout_ << 1` we do this:
-
- struct Input
- : proto::shift_right< proto::terminal< std::istream & >, proto::_ >
- {};
-
- struct Output
- : proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
- {};
-
-We've seen the template `proto::terminal<>` before, but here we're using it
-without accessing the nested `::type`. When used like this, it is a very simple
-grammar, as are `proto::shift_right<>` and `proto::shift_left<>`. The newcomer
-here is `_` in the `proto` namespace. It is a wildcard that matches anything.
-The `Input` struct is a grammar that matches any right-shift expression that
-has a `std::istream` terminal as its left operand.
-
-We can use these grammars together with the _matches_ template to query at
-compile time whether a given I/O expression type is an input or output
-operation. Consider the following:
-
- template< typename Expr >
- void input_output( Expr const & expr )
- {
- if( proto::matches< Expr, Input >::value )
- {
- std::cout << "Input!\n";
- }
-
- if( proto::matches< Expr, Output >::value )
- {
- std::cout << "Output!\n";
- }
- }
-
- int main()
- {
- int i = 0;
- input_output( cout_ << 1 );
- input_output( cin_ >> i );
-
- return 0;
- }
-
-This program prints the following:
-
-[pre
-Output!
-Input!
-]
-
-If we wanted to break the `input_output()` function into two functions, one
-that handles input expressions and one for output expressions, we can use
-`boost::enable_if<>`, as follows:
-
- template< typename Expr >
- typename boost::enable_if< proto::matches< Expr, Input > >::type
- input_output( Expr const & expr )
- {
- std::cout << "Input!\n";
- }
-
- template< typename Expr >
- typename boost::enable_if< proto::matches< Expr, Output > >::type
- input_output( Expr const & expr )
- {
- std::cout << "Output!\n";
- }
-
-This works as the previous version did. However, the following does not compile
-at all:
-
- input_output( cout_ << 1 << 2 ); // oops!
-
-What's wrong? The problem is that this expression does not match our grammar.
-The expression groups as if it were written like `(cout_ << 1) << 2`. It will
-not match the `Output` grammar, which expects the left operand to be a
-terminal, not another left-shift operation. We need to fix the grammar.
-
-We notice that in order to verify an expression as input or output, we'll need
-to recurse down to the bottom-left-most leaf and check that it is a
-`std::istream` or `std::ostream`. When we get to the terminal, we must stop
-recursing. We can express this in our grammar using _or_. Here are the correct
-`Input` and `Output` grammars:
-
- struct Input
- : proto::or_<
- proto::shift_right< proto::terminal< std::istream & >, proto::_ >
- , proto::shift_right< Input, proto::_ >
- >
- {};
-
- struct Output
- : proto::or_<
- proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
- , proto::shift_left< Output, proto::_ >
- >
- {};
-
-This may look a little odd at first. We seem to be defining the `Input` and
-`Output` types in terms of themselves. This is perfectly OK, actually. At
-the point in the grammar that the `Input` and `Output` types are being used,
-they are /incomplete/, but by the time we actually evaluate the grammar with
-_matches_, the types will be complete. These are recursive grammars, and
-rightly so because they must match a recursive data structure!
-
-When the `Output` grammar is evaluated against an expression like
-`cout_ << 1 << 2`, the first alternate of the _or_ is tried first. It will fail,
-because the expression `cout_ << 1 << 2` does not match the grammar
-`proto::shift_left< proto::terminal< std::ostream & >, proto::_ >`. Then the second
-alternate is tried. We match the expression against
-`proto::shift_left< Output, proto::_ >`. The expression is a left-shift, so we try
-the operands. The right operand `2` matches `proto::_` trivially. To see if the
-left operand `cout_ << 1` matches `Output`, we must recursively evaluate the
-`Output` grammar. This time we succeed, because `cout_ << 1` will match the first
-alternate of the _or_. We're done -- the grammar matches successfully.
-
-[endsect]
-
-[/===========================================]
-[section Fuzzy and Exact Matches of Terminals]
-[/===========================================]
-
-The terminals in an expression tree could be const or non-const references, or
-they might not be references at all. When writing grammars, you usually don't
-have to worry about it because _matches_ gives you a little wiggle room when
-matching terminals. A grammar such as `proto::terminal<int>` will match a
-terminal of type `int`, `int &`, or `int const &`.
-
-You can explicitly specify that you want to match a reference type. If you do,
-the type must match exactly. For instance, a grammar such as
-`proto::terminal<int &>` will only match an `int &`. It will not match an `int`
-or a `int const &`.
-
-The table below shows how Proto matches terminals. The simple rule is: if you
-want to match only reference types, you must specify the reference in your
-grammar. Otherwise, leave it off and Proto will ignore const and references.
-
-[table proto::matches<> and Reference / CV-Qualification of Terminals
- [[Terminal] [Grammar] [Matches?]]
- [[T] [T] [yes]]
- [[T &] [T] [yes]]
- [[T const &] [T] [yes]]
- [[T] [T &] [no]]
- [[T &] [T &] [yes]]
- [[T const &] [T &] [no]]
- [[T] [T const &] [no]]
- [[T &] [T const &] [no]]
- [[T const &] [T const &] [yes]]
-]
-
-This begs the question: What if you want to match an `int`, but not an `int &`
-or an `int const &`? For forcing exact matches, Proto provides the _exact_
-template. For instance, `proto::terminal< proto::exact<int> >` would only match an
-`int` held by value.
-
-Proto gives you extra wiggle room when matching array types. Array types match
-themselves or the pointer types they decay to. This is especially useful with
-character arrays. The type returned by `proto::as_expr("hello")` is
-`proto::terminal<char const[6]>::type`. That's a terminal containing a
-a 6-element character array. Naturally, you can match this terminal
-with the grammar `proto::terminal<char const[6]>`, but the grammar
-`proto::terminal<char const *>` will match it as well, as the following
-code fragment illustrates.
-
- struct CharString
- : proto::terminal< char const * >
- {};
-
- typedef proto::terminal< char const[6] >::type char_array;
-
- BOOST_MPL_ASSERT(( proto::matches< char_array, CharString > ));
-
-What if we only wanted `CharString` to match terminals of exactly the type
-`char const *`? You can use _exact_ here to turn off the fuzzy matching of
-terminals, as follows:
-
- struct CharString
- : proto::terminal< proto::exact< char const * > >
- {};
-
- typedef proto::terminal<char const[6]>::type char_array;
- typedef proto::terminal<char const *>::type char_string;
-
- BOOST_MPL_ASSERT(( proto::matches< char_string, CharString > ));
- BOOST_MPL_ASSERT_NOT(( proto::matches< char_array, CharString > ));
-
-Now, `CharString` does not match array types, only character string pointers.
-
-The inverse problem is a little trickier: what if you wanted to match all
-character arrays, but not character pointers? As mentioned above, the
-expression `as_expr("hello")` has the type
-`proto::terminal< char const[ 6 ] >::type`. If you wanted to match character
-arrays of arbitrary size, you could use `proto::N`, which is an array-size
-wildcard. The following grammar would match any string literal:
-`proto::terminal< char const[ proto::N ] >`.
-
-Sometimes you need even more wiggle room when matching terminals. For
-example, maybe you're building a calculator DSEL and you want to allow any
-terminals that are convertible to `double`. For that, Proto provides the
-_convertible_to_ template. You can use it as:
-`proto::terminal< proto::convertible_to< double > >`.
-
-There is one more way you can perform a fuzzy match on terminals. Consider the
-problem of trying to match a `std::complex<>` terminal. You can easily match
-a `std::complex<float>` or a `std::complex<double>`, but how would you match
-any instantiation of `std::complex<>`? You can use `proto::_` here to solve
-this problem. Here is the grammar to match any `std::complex<>` instantiation:
-
- struct StdComplex
- : proto::terminal< std::complex< proto::_ > >
- {};
-
-When given a grammar like this, Proto will deconstruct the grammar and the
-terminal it is being matched against and see if it can match all the
-constituents.
-
-[endsect]
-
-[/====================================================]
-[section:if_and_not [^if_<>], [^and_<>], and [^not_<>]]
-[/====================================================]
-
-We've already seen how to use expression generators like `proto::terminal<>` and
-`proto::shift_right<>` as grammars. We've also seen _or_, which we can use to
-express a set of alternate grammars. There are a few others of interest; in
-particular, _if_, _and_ and _not_.
-
-The _not_ template is the simplest. It takes a grammar as a template parameter
-and logically negates it; `not_<Grammar>` will match any expression that
-`Grammar` does /not/ match.
-
-The _if_ template is used together with a Proto transform that is evaluated
-against expression types to find matches. (Proto transforms will be described
-later.)
-
-The _and_ template is like _or_, except that each argument of the _and_ must
-match in order for the _and_ to match. As an example, consider the definition
-of `CharString` above that uses _exact_. It could have been written without
-_exact_ as follows:
-
- struct CharString
- : proto::and_<
- proto::terminal< proto::_ >
- , proto::if_< boost::is_same< proto::_value, char const * >() >
- >
- {};
-
-This says that a `CharString` must be a terminal, /and/ its value type must be
-the same as `char const *`. Notice the template argument of _if_:
-`boost::is_same< proto::_value, char const * >()`. This is Proto transform that
-compares the value type of a terminal to `char const *`.
-
-The _if_ template has a couple of variants. In additon to `if_<Condition>` you
-can also say `if_<Condition, ThenGrammar>` and
-`if_<Condition, ThenGrammar, ElseGrammar>`. These let you select one sub-grammar
-or another based on the `Condition`.
-
-[endsect]
-
-[/=======================================================]
-[section:switch Improving Compile Times With [^switch_<>]]
-[/=======================================================]
-
-When your Proto grammar gets large, you'll start to run into some scalability problems with _or_, the construct you use to specify alternate sub-grammars. First, due to limitations in C++, _or_ can only accept up to a certain number of sub-grammars, controlled by the `BOOST_PROTO_MAX_LOGICAL_ARITY` macro. This macro defaults to eight, and you can set it higher, but doing so will aggravate another scalability problem: long compile times. With _or_, alternate sub-grammars are tried in order -- like a series of cascading `if`'s -- leading to lots of unnecessary template instantiations. What you would prefer instead is something like `switch` that avoids the expense of cascading `if`'s. That's the purpose of _switch_; although less convenient than _or_, it improves compile times for larger grammars and does not have an arbitrary fixed limit on the number of sub-grammars.
-
-Let's illustrate how to use _switch_ by first writing a big grammar with _or_ and then translating it to an equivalent grammar using _switch_:
-
- // Here is a big, inneficient grammar
- struct ABigGrammar
- : proto::or_<
- proto::terminal<int>
- , proto::terminal<double>
- , proto::unary_plus<ABigGrammar>
- , proto::negate<ABigGrammar>
- , proto::complement<ABigGrammar>
- , proto::plus<ABigGrammar, ABigGrammar>
- , proto::minus<ABigGrammar, ABigGrammar>
- , proto::or_<
- proto::multiplies<ABigGrammar, ABigGrammar>
- , proto::divides<ABigGrammar, ABigGrammar>
- , proto::modulus<ABigGrammar, ABigGrammar>
- >
- >
- {};
-
-The above might be the grammar to a more ellaborate calculator DSEL. Notice that since there are more than eight sub-grammars, we had to chain the sub-grammars with a nested _or_ -- not nice.
-
-The idea behind _switch_ is to dispatch based on an expression's tag type to a sub-grammar that handles expressions of that type. To use _switch_, you define a struct with a nested `case_<>` template, specialized on tag types. The above grammar can be expressed using _switch_ as follows. It is described below.
-
- // Redefine ABigGrammar more efficiently using proto::switch_<>
- struct ABigGrammar;
-
- struct ABigGrammarCases
- {
- // The primary template matches nothing:
- template<typename Tag>
- struct case_
- : proto::not_<_>
- {};
- };
-
- // Terminal expressions are handled here
- template<>
- struct ABigGrammarCases::case_<proto::tag::terminal>
- : proto::or_<
- proto::terminal<int>
- , proto::terminal<double>
- >
- {};
-
- // Non-terminals are handled similarly
- template<>
- struct ABigGrammarCases::case_<proto::tag::unary_plus>
- : proto::unary_plus<ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::negate>
- : proto::negate<ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::complement>
- : proto::complement<ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::plus>
- : proto::plus<ABigGrammar, ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::minus>
- : proto::minus<ABigGrammar, ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::multiplies>
- : proto::multiplies<ABigGrammar, ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::divides>
- : proto::divides<ABigGrammar, ABigGrammar>
- {};
-
- template<>
- struct ABigGrammarCases::case_<proto::tag::modulus>
- : proto::modulus<ABigGrammar, ABigGrammar>
- {};
-
- // Define ABigGrammar in terms of ABigGrammarCases
- // using proto::switch_<>
- struct ABigGrammar
- : proto::switch_<ABigGrammarCases>
- {};
-
-Matching an expression type `E` against `proto::switch_<C>` is equivalent to matching it against `C::case_<E::proto_tag>`. By dispatching on the expression's tag type, we can jump to the sub-grammar that handles expressions of that type, skipping over all the other sub-grammars that couldn't possibly match. If there is no specialization of `case_<>` for a particular tag type, we select the primary template. In this case, the primary template inherits from `proto::not_<_>` which matches no expressions.
-
-Notice the specialization that handles terminals:
-
- // Terminal expressions are handled here
- template<>
- struct ABigGrammarCases::case_<proto::tag::terminal>
- : proto::or_<
- proto::terminal<int>
- , proto::terminal<double>
- >
- {};
-
-The `proto::tag::terminal` type by itself isn't enough to select an appropriate sub-grammar, so we use _or_ to list the alternate sub-grammars that match terminals.
-
-[note You might be tempted to define your `case_<>` specializations /in situ/ as follows:
-
-``
- struct ABigGrammarCases
- {
- template<typename Tag>
- struct case_ : proto::not_<_> {};
-
- // ERROR: not legal C++
- template<>
- struct case_<proto::tag::terminal>
- /* ... as defined above ... */
- };
-``
-
-Unfortunately, for arcane reasons, it is not legal to define an explicit nested specialization /in situ/ like this. It is, however, perfectly legal to define /partial/ specializations /in situ/, so you can add a extra dummy template parameter that has a default, as follows:
-
-``
- struct ABigGrammarCases
- {
- // Note extra "Dummy" template parameter here:
- template<typename Tag, int Dummy = 0>
- struct case_ : proto::not_<_> {};
-
- // OK: "Dummy" makes this a partial specialization
- // instead of an explicit specialization.
- template<int Dummy>
- struct case_<proto::tag::terminal, Dummy>
- /* ... as defined above */
- };
-``
-
-You might find this cleaner that defining explicit `case_<>` specializations outside of their enclosing struct.
-]
-
-[endsect]
-
-[/==================================]
-[section Matching Vararg Expressions]
-[/==================================]
-
-Not all of C++'s overloadable operators are unary or binary. There is the
-oddball `operator()` -- the function call operator -- which can have any number
-of arguments. Likewise, with Proto you may define your own "operators" that
-could also take more that two arguments. As a result, there may be nodes in
-your Proto expression tree that have an arbitrary number of children (up to
-`BOOST_PROTO_MAX_ARITY`, which is configurable). How do you write a grammar to
-match such a node?
-
-For such cases, Proto provides the _vararg_ class template. Its template
-argument is a grammar, and the _vararg_ will match the grammar zero or more
-times. Consider a Proto lazy function called `fun()` that can take zero or
-more characters as arguments, as follows:
-
- struct fun_tag {};
- struct FunTag : proto::terminal< fun_tag > {};
- FunTag::type const fun = {{}};
-
- // example usage:
- fun();
- fun('a');
- fun('a', 'b');
- ...
-
-Below is the grammar that matches all the allowable invocations of `fun()`:
-
- struct FunCall
- : proto::function< FunTag, proto::vararg< proto::terminal< char > > >
- {};
-
-The `FunCall` grammar uses _vararg_ to match zero or more character literals
-as arguments of the `fun()` function.
-
-As another example, can you guess what the following grammar matches?
-
- struct Foo
- : proto::or_<
- proto::terminal< proto::_ >
- , proto::nary_expr< proto::_, proto::vararg< Foo > >
- >
- {};
-
-Here's a hint: the first template parameter to `proto::nary_expr<>` represents the
-node type, and any additional template parameters represent child nodes. The answer
-is that this is a degenerate grammar that matches every possible expression tree,
-from root to leaves.
-
-[endsect]
-
-[/=============================]
-[section Defining DSEL Grammars]
-[/=============================]
-
-In this section we'll see how to use Proto to define a grammar for your DSEL and
-use it to validate expression templates, giving short, readable compile-time errors
-for invalid expressions.
-
-[tip You might think that this is a backwards way of doing things. ["If Proto let
-me select which operators to overload, my users wouldn't be able to create invalid
-expressions in the first place, and I wouldn't need a grammar at all!] That may be
-true, but there are reasons for preferring to do things this way.
-
-First, it lets you develop your DSEL rapidly -- all the operators are there for you
-already! -- and worry about invalid syntax later.
-
-Second, it might be the case that some operators are only allowed in certain
-contexts within your DSEL. This is easy to express with a grammar, and hard to do
-with straight operator overloading.
-
-Third, using a DSEL grammar to flag invalid expressions can often yield better
-errors than manually selecting the overloaded operators.
-
-Fourth, the grammar can be used for more than just validation. You can use your
-grammar to define ['tree transformations] that convert expression templates into
-other more useful objects.
-
-If none of the above convinces you, you actually /can/ use Proto to control which
-operators are overloaded within your domain. And to do it, you need to define a
-grammar!]
-
-In a previous section, we used Proto to define a DSEL for a lazily evaluated
-calculator that allowed any combination of placeholders, floating-point
-literals, addition, subtraction, multiplaction, division and grouping. If
-we were to write the grammar for this DSEL in
-[@http://en.wikipedia.org/wiki/Extended_Backus_Naur_Form EBNF], it might look
-like this:
-
-[pre
-group ::= '(' expression ')'
-factor ::= double | '_1' | '_2' | group
-term ::= factor (('*' factor) | ('/' factor))*
-expression ::= term (('+' term) | ('-' term))*
-]
-
-This captures the syntax, associativity and precedence rules of a calculator.
-Writing the grammar for our calculator DSEL using Proto is /even simpler/.
-Since we are using C++ as the host language, we are bound to the associativity
-and precedence rules for the C++ operators. Our grammar can assume them. Also,
-in C++ grouping is already handled for us with the use of parenthesis, so we
-don't have to code that into our grammar.
-
-Let's begin our grammar for forward-declaring it:
-
- struct CalculatorGrammar;
-
-It's an incomplete type at this point, but we'll still be able to use it to
-define the rules of our grammar. Let's define grammar rules for the terminals:
-
- struct Double
- : proto::terminal< proto::convertible_to< double > >
- {};
-
- struct Placeholder1
- : proto::terminal< placeholder<0> >
- {};
-
- struct Placeholder2
- : proto::terminal< placeholder<1> >
- {};
-
- struct Terminal
- : proto::or_< Double, Placeholder1, Placeholder2 >
- {};
-
-Now let's define the rules for addition, subtraction, multiplication and division.
-Here, we can ignore issues of associativity and precedence -- the C++ compiler will
-enforce that for us. We only must enforce that the arguments to the operators must
-themselves conform to the `CalculatorGrammar` that we forward-declared above.
-
- struct Plus
- : proto::plus< CalculatorGrammar, CalculatorGrammar >
- {};
-
- struct Minus
- : proto::minus< CalculatorGrammar, CalculatorGrammar >
- {};
-
- struct Multiplies
- : proto::multiplies< CalculatorGrammar, CalculatorGrammar >
- {};
-
- struct Divides
- : proto::divides< CalculatorGrammar, CalculatorGrammar >
- {};
-
-Now that we've defined all the parts of the grammar, we can define
-`CalculatorGrammar`:
-
- struct CalculatorGrammar
- : proto::or_<
- Terminal
- , Plus
- , Minus
- , Multiplies
- , Divides
- >
- {};
-
-That's it! Now we can use `CalculatorGrammar` to enforce that an expression
-template conforms to our grammar. We can use _matches_ and `BOOST_MPL_ASSERT()`
-to issue readable compile-time errors for invalid expressions, as below:
-
- template< typename Expr >
- void evaluate( Expr const & expr )
- {
- BOOST_MPL_ASSERT(( proto::matches< Expr, CalculatorGrammar > ));
- // ...
- }
-
-[endsect]
-
-[endsect]
Modified: trunk/libs/proto/doc/installation.qbk
==============================================================================
--- trunk/libs/proto/doc/installation.qbk (original)
+++ trunk/libs/proto/doc/installation.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -5,17 +5,24 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
+[/=======================]
[section Installing Proto]
+[/=======================]
+[/====================]
[heading Getting Proto]
+[/====================]
You can get Proto by downloading [^proto.zip] from
-[@http://www.boost-consulting.com/vault/index.php?directory=Template%20Metaprogramming]
+[@http://www.boost-consulting.com/vault/index.php?directory=Template%20Metaprogramming],
+by downloading Boost (Proto is in version 1.37 and later),
or by accessing Boost's SVN repository on SourceForge.net. Just go to
[@http://svn.boost.org/trac/boost/wiki/BoostSubversion]
and follow the instructions there for anonymous SVN access.
+[/==========================]
[heading Building with Proto]
+[/==========================]
Proto is a header-only template library, which means you don't need to alter
your build scripts or link to any separate lib file to use it. All you need
@@ -23,12 +30,16 @@
include the core of Proto (`#include <boost/proto/core.hpp>`) and whichever
contexts and transforms you happen to use.
+[/===================]
[heading Requirements]
+[/===================]
Proto depends on Boost. You must use either Boost version 1.34.1 or higher,
or the version in SVN trunk.
+[/==========================]
[heading Supported Compilers]
+[/==========================]
Currently, Boost.Proto is known to work on the following compilers:
@@ -37,6 +48,6 @@
* Intel on Linux 8.1 and higher
* Intel on Windows 9.1 and higher
-[note Please send any questions, comments and bug reports to eric <at> boost-consulting <dot> com.]
+[note Please send any questions, comments and bug reports to eric <at> boostpro <dot> com.]
[endsect]
Added: trunk/libs/proto/doc/intermediate_form.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/proto/doc/intermediate_form.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,1170 @@
+[/
+ / Copyright (c) 2007 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)
+ /]
+
+
+[/talk about:
+
+ tag types
+ generator metafunctions
+ accessing child nodes
+ metafunctions for tag type and arity
+ deep_copy
+ flatten
+ debug utilities
+ introspection with grammars and proto::matches
+]
+
+[/================================================================================]
+[section:intermediate_form Intermediate Form:
+ Understanding and Introspecting Expressions]
+[/================================================================================]
+
+By now, you know a bit about how to build a front-end for your DSEL "compiler" -- you can define terminals and functions that generate expression templates. But we haven't said anything about the expression templates themselves. What do they look like? What can you do with them? In this section we'll see.
+
+[/=========================]
+[heading The [^expr<>] Type]
+[/=========================]
+
+All Proto expressions are an instantiation of a template called `expr<>` (or a wrapper around such an instantiation). When we define a terminal as below, we are really initializing an instance of the _expr_ template.
+
+ // Define a placeholder type
+ template<int I>
+ struct placeholder
+ {};
+
+ // Define the Protofied placeholder terminal
+ proto::terminal< placeholder<0> >::type const _1 = {{}};
+
+The actual type of `_1` looks like this:
+
+ proto::expr< proto::tag::terminal, proto::term< placeholder<0> >, 0 >
+
+The _expr_ template is the most important type in Proto. Although you will
+rarely need to deal with it directly, it's always there behind the scenes
+holding your expression trees together. In fact, _expr_ /is/ the expression
+tree -- branches, leaves and all.
+
+The _expr_ template makes up the nodes in expression trees. The first template
+parameter is the node type; in this case, `proto::tag::terminal`. That means
+that `_1` is a leaf-node in the expression tree. The second template parameter
+is a list of child types, or in the case of terminals, the terminal's value
+type. Terminals will always have only one type in the type list. The last
+parameter is the arity of the expression. Terminals have arity 0, unary
+expressions have arity 1, etc.
+
+The _expr_ struct is defined as follows:
+
+ template< typename Tag, typename Args, long Arity = Args::arity >
+ struct expr;
+
+ template< typename Tag, typename Args >
+ struct expr< Tag, Args, 1 >
+ {
+ typedef typename Args::child0 proto_child0;
+ proto_child0 child0;
+ // ...
+ };
+
+The _expr_ struct does not define a constructor, or anything else that would
+prevent static initialization. All _expr_ objects are initialized using
+['aggregate initialization], with curly braces. In our example, `_1` is
+initialized with the initializer `{{}}`. The outer braces is the initializer
+for the _expr_ struct, and the inner braces are for the member `_1.child0` which
+is of type `placeholder<0>`. Note that we use braces to initialize `_1.child0`
+because `placeholder<0>` is also an aggregate.
+
+[/================================]
+[heading Building Expression Trees]
+[/================================]
+
+The `_1` node is an instantiation of _expr_, and expressions containing
+`_1` are also instantiations of _expr_. To use Proto effectively, you
+won't have to bother yourself with the actual types that Proto generates.
+These are details, but you're likely to encounter these types in compiler
+error messages, so it's helpful to be familiar with them. The types look
+like this:
+
+ // The type of the expression -_1
+ typedef
+ proto::expr<
+ proto::tag::negate
+ , proto::list1<
+ proto::expr<
+ proto::tag::terminal
+ , proto::term< placeholder<0> >
+ , 0
+ > const &
+ >
+ , 1
+ >
+ negate_placeholder_type;
+
+ negate_placeholder_type x = -_1;
+
+ // The type of the expression _1 + 42
+ typedef
+ proto::expr<
+ proto::tag::plus
+ , proto::list2<
+ proto::expr<
+ proto::tag::terminal
+ , proto::term< placeholder<0> >
+ , 0
+ > const &
+ , proto::expr<
+ proto::tag::terminal
+ , proto::term< int const & >
+ , 0
+ >
+ >
+ , 2
+ >
+ placeholder_plus_int_type;
+
+ placeholder_plus_int_type y = _1 + 42;
+
+There are a few things to note about these types:
+
+# Terminals have arity 0, unary expressions have arity 1 and binary expressions
+ have arity 2.
+# When one Proto expression is made a child node of another Proto expression,
+ it is held by reference, ['even if it is a temporary object]. This last
+ point becomes important later.
+# Non-Proto expressions, such as the integer literal, are turned into Proto
+ expressions by wrapping them in new `expr<>` terminal objects. These new
+ wrappers are not themselves held by reference, but the object wrapped /is/.
+ Notice that the type of the Protofied `42` literal is `int const &` -- held
+ by reference.
+
+The types make it clear: everything in a Proto expression tree is held by
+reference. That means that building an expression tree is exceptionally cheap.
+It involves no copying at all.
+
+[note An astute reader will notice that the object `y` defined above will be
+left holding a dangling reference to a temporary int. In the sorts of
+high-performance applications Proto addresses, it is typical to build and
+evaluate an expression tree before any temporary objects go out of scope, so
+this dangling reference situation often doesn't arise, but it is certainly
+something to be aware of. Proto provides utilities for deep-copying expression
+trees so they can be passed around as value types without concern for dangling
+references.]
+
+[/=============================================]
+[section:left_right_child Accessing Child Nodes]
+[/=============================================]
+
+After assembling an expression into a tree, you'll naturally want to be
+able to do the reverse, and access a node's children. You may even want
+to be able to iterate over the children with algorithms from the
+Boost.Fusion library. This section shows how.
+
+[heading [^tag_of<>]]
+
+A node in an expression tree is nothing more than a collection of child
+nodes and a tag type. You can access the tag type of any Proto expression type
+`Expr` directly as `typename Expr::proto_tag`, or you can use the _tag_of_
+metafunction, as shown below:
+
+ template<typename Expr>
+ typename proto::result_of::tag_of<Expr>::type
+ get_tag_of(Expr const &)
+ {
+ // Tag types are required to be default-constructible
+ return typename proto::result_of::tag_of<Expr>::type();
+ }
+
+ proto::terminal<int>::type const i = {42};
+
+ // Addition nodes have the "plus" tag type:
+ proto::tag::plus plus_tag = get_tag_of( i + 2 );
+
+[/===================]
+[heading [^child_c()]]
+[/===================]
+
+Each node in an expression tree corresponds to an operator in an expression,
+and the children correspond to the operands, or arguments of the operator.
+To access them, you can use the _child_c_ function template, as demonstrated
+below:
+
+ proto::terminal<int>::type i = {42};
+
+ // Get the 0-th operand of an addition operation:
+ proto::terminal<int>::type &ri = proto::child_c<0>( i + 2 );
+
+ // Assert that we got back what we put in:
+ assert( &i == &ri );
+
+You can use the `result_of::child_c<>` metafunction to get the type of the Nth
+child of an expression node. Usually you don't care to know whether a child
+is stored by value or by reference, so when you ask for the type of the Nth
+child of an expression `Expr`, you get the child's type after references and
+cv-qualifiers have been stripped from it.
+
+ template<typename Expr>
+ void test_result_of_child_c(Expr const &expr)
+ {
+ typedef typename proto::result_of::child_c<Expr, 0>::type type;
+
+ // ::type is a non-cv qualified, non-reference
+ BOOST_MPL_ASSERT((is_same< type, terminal<int>::type>));
+ }
+
+ // ...
+ terminal<int>::type i = {42};
+ test_result_of_child_c( i + 2 );
+
+However, if you ask for the type of the Nth child of `Expr &` or `Expr const &`
+(note the reference), the result type will be a reference, regardless of whether
+the child is actually stored by reference or not. If you need to know exactly
+how the child is stored in the node, whether by reference or by value, you can
+use `fusion::result_of::value_at<Expr, N>::type`. The following table summarizes
+the behavior of the `child_c<>` metafunction.
+
+[table Accessing Child Types
+ [[Metafunction Invocation][When the Child Is ...][The Result Is ...]]
+ [[`proto::result_of::child_c<Expr, N>::type`][T][T]]
+ [[][T &][T]]
+ [[][T const &][T]]
+ [[`proto::result_of::child_c<Expr &, N>::type`][T][T &]]
+ [[][T &][T &]]
+ [[][T const &][T const &]]
+ [[`proto::result_of::child_c<Expr const &, N>::type`][T][T const &]]
+ [[][T &][T &]]
+ [[][T const &][T const &]]
+ [[`fusion::result_of::value_at<Expr, N>::type`][T][T]]
+ [[][T &][T &]]
+ [[][T const &][T const &]]
+]
+
+[/========================================================]
+[heading [^value()], [^child()], [^left()], and [^right()]]
+[/========================================================]
+
+Most operators in C++ are unary or binary. For that reason, accessing the
+only operand, or the left and right operands, are very common operations. For
+this reason, Proto provides the _child_, _left_, and _right_ functions. _child_
+and _left_ are synonomous with `child_c<0>()`, and _right_ is synonomous with
+`child_c<1>()`.
+
+Another very common operation is accessing the value stored within a Proto
+terminal. You can use the _value_ function for that.
+
+There are also `result_of::child<>`, `result_of::left<>`, and `result_of::right<>`
+metafunctions that merely forward to their `result_of::child_c<>` counterparts.
+Likewise, there is a `result_of::value<>` metafunction that returns the type of the
+value stored in a terminal node.
+
+[/===========================================]
+[heading Expression Nodes as Fusion Sequences]
+[/===========================================]
+
+Proto expression nodes are valid Fusion random-access sequences of their
+child nodes. That means you can apply Fusion algorithms to them,
+transform them, apply Fusion filters and views to them, and access their
+elements using `fusion::at()`. The things Fusion can do to heterogeneous
+sequences is beyond the scope of this users' guide, but below is a simple
+example. It takes a lazy function invocation like `fun(1,2,3,4)` and uses
+Fusion to print the function arguments in order.
+
+ struct display
+ {
+ template<typename T>
+ void operator()(T const &t) const
+ {
+ std::cout << t << std::endl;
+ }
+ };
+
+ struct fun_t {};
+ proto::terminal<fun_t>::type const fun = {{}};
+
+ // ...
+ fusion::for_each(
+ fusion::transform(
+ // pop_front() removes the "fun" child
+ fusion::pop_front(fun(1,2,3,4))
+ // Extract the ints from the terminal nodes
+ , proto::functional::value()
+ )
+ , display()
+ );
+
+Recall from the Introduction that types in the `proto::functional` namespace
+define function objects that correspond to Proto's free functions. So
+`proto::functional::value()` creates a function object that is equavalent to
+the `proto::value()` function. The above invocation of `fusion::for_each()`
+displays the following:
+
+[pre
+1
+2
+3
+4
+]
+
+[/========================================]
+[heading Flattening Proto Expression Tress]
+[/========================================]
+
+Imagine a slight variation of the above example where, instead of iterating
+over the arguments of a lazy function invocation, we would like to iterate
+over the terminals in an addition expression:
+
+ proto::terminal<int>::type const _1 = {1};
+
+ // ERROR: this doesn't work! Why?
+ fusion::for_each(
+ fusion::transform(
+ _1 + 2 + 3 + 4
+ , proto::functional::value()
+ )
+ , display()
+ );
+
+The reason this doesn't work is because the expression `_1 + 2 + 3 + 4` does
+not describe a flat sequence of terminals --- it describes a binary tree. We
+can treat it as a flat sequence of terminals, however, using Proto's _flatten_
+function. _flatten_ returns a view which makes a tree appear as a flat Fusion
+sequence. If the top-most node has a tag type `T`, then the elements of the
+flattened sequence are the child nodes that do /not/ have tag type `T`. This
+process is evaluated recursively. So the above can correctly be written as:
+
+ proto::terminal<int>::type const _1 = {1};
+
+ // OK, iterate over a flattened view
+ fusion::for_each(
+ fusion::transform(
+ proto::flatten(_1 + 2 + 3 + 4)
+ , proto::functional::value()
+ )
+ , display()
+ );
+
+The above invocation of `fusion::for_each()` displays the following:
+
+[pre
+1
+2
+3
+4
+]
+
+[endsect]
+
+[/=============================================================]
+[section:tags_and_metafunctions Operator Tags and Metafunctions]
+[/=============================================================]
+
+The following table lists the overloadable C++ operators, the Proto tag types for
+each, and the name of the metafunctions for generating the corresponding Proto
+expression types. And as we'll see later, the metafunctions are also usable as
+grammars for matching such nodes, as well as pass-through transforms.
+
+[table Operators, Tags and Metafunctions
+ [[Operator]
+ [Proto Tag]
+ [Proto Metafunction]]
+
+ [[unary `+`]
+ [`proto::tag::unary_plus`]
+ [`proto::unary_plus<>`]]
+
+ [[unary `-`]
+ [`proto::tag::negate`]
+ [`proto::negate<>`]]
+
+ [[unary `*`]
+ [`proto::tag::dereference`]
+ [`proto::dereference<>`]]
+
+ [[unary `~`]
+ [`proto::tag::complement`]
+ [`proto::complement<>`]]
+
+ [[unary `&`]
+ [`proto::tag::address_of`]
+ [`proto::address_of<>`]]
+
+ [[unary `!`]
+ [`proto::tag::logical_not`]
+ [`proto::logical_not<>`]]
+
+ [[unary prefix `++`]
+ [`proto::tag::pre_inc`]
+ [`proto::pre_inc<>`]]
+
+ [[unary prefix `--`]
+ [`proto::tag::pre_dec`]
+ [`proto::pre_dec<>`]]
+
+ [[unary postfix `++`]
+ [`proto::tag::post_inc`]
+ [`proto::post_inc<>`]]
+
+ [[unary postfix `--`]
+ [`proto::tag::post_dec`]
+ [`proto::post_dec<>`]]
+
+ [[binary `<<`]
+ [`proto::tag::shift_left`]
+ [`proto::shift_left<>`]]
+
+ [[binary `>>`]
+ [`proto::tag::shift_right`]
+ [`proto::shift_right<>`]]
+
+ [[binary `*`]
+ [`proto::tag::multiplies`]
+ [`proto::multiplies<>`]]
+
+ [[binary `/`]
+ [`proto::tag::divides`]
+ [`proto::divides<>`]]
+
+ [[binary `%`]
+ [`proto::tag::modulus`]
+ [`proto::modulus<>`]]
+
+ [[binary `+`]
+ [`proto::tag::plus`]
+ [`proto::plus<>`]]
+
+ [[binary `-`]
+ [`proto::tag::minus`]
+ [`proto::minus<>`]]
+
+ [[binary `<`]
+ [`proto::tag::less`]
+ [`proto::less<>`]]
+
+ [[binary `>`]
+ [`proto::tag::greater`]
+ [`proto::greater<>`]]
+
+ [[binary `<=`]
+ [`proto::tag::less_equal`]
+ [`proto::less_equal<>`]]
+
+ [[binary `>=`]
+ [`proto::tag::greater_equal`]
+ [`proto::greater_equal<>`]]
+
+ [[binary `==`]
+ [`proto::tag::equal_to`]
+ [`proto::equal_to<>`]]
+
+ [[binary `!=`]
+ [`proto::tag::not_equal_to`]
+ [`proto::not_equal_to<>`]]
+
+ [[binary `||`]
+ [`proto::tag::logical_or`]
+ [`proto::logical_or<>`]]
+
+ [[binary `&&`]
+ [`proto::tag::logical_and`]
+ [`proto::logical_and<>`]]
+
+ [[binary `&`]
+ [`proto::tag::bitwise_and`]
+ [`proto::bitwise_and<>`]]
+
+ [[binary `|`]
+ [`proto::tag::bitwise_or`]
+ [`proto::bitwise_or<>`]]
+
+ [[binary `^`]
+ [`proto::tag::bitwise_xor`]
+ [`proto::bitwise_xor<>`]]
+
+ [[binary `,`]
+ [`proto::tag::comma`]
+ [`proto::comma<>`]]
+
+ [[binary `->*`]
+ [`proto::tag::mem_ptr`]
+ [`proto::mem_ptr<>`]]
+
+ [[binary `=`]
+ [`proto::tag::assign`]
+ [`proto::assign<>`]]
+
+ [[binary `<<=`]
+ [`proto::tag::shift_left_assign`]
+ [`proto::shift_left_assign<>`]]
+
+ [[binary `>>=`]
+ [`proto::tag::shift_right_assign`]
+ [`proto::shift_right_assign<>`]]
+
+ [[binary `*=`]
+ [`proto::tag::multiplies_assign`]
+ [`proto::multiplies_assign<>`]]
+
+ [[binary `/=`]
+ [`proto::tag::divides_assign`]
+ [`proto::divides_assign<>`]]
+
+ [[binary `%=`]
+ [`proto::tag::modulus_assign`]
+ [`proto::modulus_assign<>`]]
+
+ [[binary `+=`]
+ [`proto::tag::plus_assign`]
+ [`proto::plus_assign<>`]]
+
+ [[binary `-=`]
+ [`proto::tag::minus_assign`]
+ [`proto::minus_assign<>`]]
+
+ [[binary `&=`]
+ [`proto::tag::bitwise_and_assign`]
+ [`proto::bitwise_and_assign<>`]]
+
+ [[binary `|=`]
+ [`proto::tag::bitwise_or_assign`]
+ [`proto::bitwise_or_assign<>`]]
+
+ [[binary `^=`]
+ [`proto::tag::bitwise_xor_assign`]
+ [`proto::bitwise_xor_assign<>`]]
+
+ [[binary subscript]
+ [`proto::tag::subscript`]
+ [`proto::subscript<>`]]
+
+ [[ternary `?:`]
+ [`proto::tag::if_else_`]
+ [`proto::if_else_<>`]]
+
+ [[n-ary function call]
+ [`proto::tag::function`]
+ [`proto::function<>`]]
+]
+
+[endsect]
+
+[/============================================================================]
+[section:expression_introspection Expression Introspection: Defining a Grammar]
+[/============================================================================]
+
+Expression trees can have a very rich and complicated structure. Often, you
+need to know some things about an expression's structure before you can process
+it. This section describes the tools Proto provides for peering inside an
+expression tree and discovering its structure. And as you'll see in later
+sections, all the really interesting things you can do with Proto begin right
+here.
+
+[/===============================================]
+[section:patterns Finding Patterns In Expressions]
+[/===============================================]
+
+Imagine your DSEL is a miniature I/O facility, with iostream operations
+that execute lazily. You might want expressions representing input operations
+to be processed by one function, and output operations to be processed by a
+different function. How would you do that?
+
+The answer is to write patterns (a.k.a, /grammars/) that match the structure
+of input and output expressions. Proto provides utilities for defining the
+grammars, and the _matches_ template for checking whether a given expression
+type matches the grammar.
+
+First, let's define some terminals we can use in our lazy I/O expressions:
+
+ proto::terminal< std::istream & >::type cin_ = { std::cin };
+ proto::terminal< std::ostream & >::type cout_ = { std::cout };
+
+Now, we can use `cout_` instead of `std::cout`, and get I/O expression trees
+that we can execute later. To define grammars that match intput and output
+expressions of the form `cin_ >> i` and `cout_ << 1` we do this:
+
+ struct Input
+ : proto::shift_right< proto::terminal< std::istream & >, proto::_ >
+ {};
+
+ struct Output
+ : proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
+ {};
+
+We've seen the template `proto::terminal<>` before, but here we're using it
+without accessing the nested `::type`. When used like this, it is a very simple
+grammar, as are `proto::shift_right<>` and `proto::shift_left<>`. The newcomer
+here is `_` in the `proto` namespace. It is a wildcard that matches anything.
+The `Input` struct is a grammar that matches any right-shift expression that
+has a `std::istream` terminal as its left operand.
+
+We can use these grammars together with the _matches_ template to query at
+compile time whether a given I/O expression type is an input or output
+operation. Consider the following:
+
+ template< typename Expr >
+ void input_output( Expr const & expr )
+ {
+ if( proto::matches< Expr, Input >::value )
+ {
+ std::cout << "Input!\n";
+ }
+
+ if( proto::matches< Expr, Output >::value )
+ {
+ std::cout << "Output!\n";
+ }
+ }
+
+ int main()
+ {
+ int i = 0;
+ input_output( cout_ << 1 );
+ input_output( cin_ >> i );
+
+ return 0;
+ }
+
+This program prints the following:
+
+[pre
+Output!
+Input!
+]
+
+If we wanted to break the `input_output()` function into two functions, one
+that handles input expressions and one for output expressions, we can use
+`boost::enable_if<>`, as follows:
+
+ template< typename Expr >
+ typename boost::enable_if< proto::matches< Expr, Input > >::type
+ input_output( Expr const & expr )
+ {
+ std::cout << "Input!\n";
+ }
+
+ template< typename Expr >
+ typename boost::enable_if< proto::matches< Expr, Output > >::type
+ input_output( Expr const & expr )
+ {
+ std::cout << "Output!\n";
+ }
+
+This works as the previous version did. However, the following does not compile
+at all:
+
+ input_output( cout_ << 1 << 2 ); // oops!
+
+What's wrong? The problem is that this expression does not match our grammar.
+The expression groups as if it were written like `(cout_ << 1) << 2`. It will
+not match the `Output` grammar, which expects the left operand to be a
+terminal, not another left-shift operation. We need to fix the grammar.
+
+We notice that in order to verify an expression as input or output, we'll need
+to recurse down to the bottom-left-most leaf and check that it is a
+`std::istream` or `std::ostream`. When we get to the terminal, we must stop
+recursing. We can express this in our grammar using _or_. Here are the correct
+`Input` and `Output` grammars:
+
+ struct Input
+ : proto::or_<
+ proto::shift_right< proto::terminal< std::istream & >, proto::_ >
+ , proto::shift_right< Input, proto::_ >
+ >
+ {};
+
+ struct Output
+ : proto::or_<
+ proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
+ , proto::shift_left< Output, proto::_ >
+ >
+ {};
+
+This may look a little odd at first. We seem to be defining the `Input` and
+`Output` types in terms of themselves. This is perfectly OK, actually. At
+the point in the grammar that the `Input` and `Output` types are being used,
+they are /incomplete/, but by the time we actually evaluate the grammar with
+_matches_, the types will be complete. These are recursive grammars, and
+rightly so because they must match a recursive data structure!
+
+When the `Output` grammar is evaluated against an expression like
+`cout_ << 1 << 2`, the first alternate of the _or_ is tried first. It will fail,
+because the expression `cout_ << 1 << 2` does not match the grammar
+`proto::shift_left< proto::terminal< std::ostream & >, proto::_ >`. Then the second
+alternate is tried. We match the expression against
+`proto::shift_left< Output, proto::_ >`. The expression is a left-shift, so we try
+the operands. The right operand `2` matches `proto::_` trivially. To see if the
+left operand `cout_ << 1` matches `Output`, we must recursively evaluate the
+`Output` grammar. This time we succeed, because `cout_ << 1` will match the first
+alternate of the _or_. We're done -- the grammar matches successfully.
+
+[endsect]
+
+[/===========================================]
+[section Fuzzy and Exact Matches of Terminals]
+[/===========================================]
+
+The terminals in an expression tree could be const or non-const references, or
+they might not be references at all. When writing grammars, you usually don't
+have to worry about it because _matches_ gives you a little wiggle room when
+matching terminals. A grammar such as `proto::terminal<int>` will match a
+terminal of type `int`, `int &`, or `int const &`.
+
+You can explicitly specify that you want to match a reference type. If you do,
+the type must match exactly. For instance, a grammar such as
+`proto::terminal<int &>` will only match an `int &`. It will not match an `int`
+or a `int const &`.
+
+The table below shows how Proto matches terminals. The simple rule is: if you
+want to match only reference types, you must specify the reference in your
+grammar. Otherwise, leave it off and Proto will ignore const and references.
+
+[table proto::matches<> and Reference / CV-Qualification of Terminals
+ [[Terminal] [Grammar] [Matches?]]
+ [[T] [T] [yes]]
+ [[T &] [T] [yes]]
+ [[T const &] [T] [yes]]
+ [[T] [T &] [no]]
+ [[T &] [T &] [yes]]
+ [[T const &] [T &] [no]]
+ [[T] [T const &] [no]]
+ [[T &] [T const &] [no]]
+ [[T const &] [T const &] [yes]]
+]
+
+This begs the question: What if you want to match an `int`, but not an `int &`
+or an `int const &`? For forcing exact matches, Proto provides the _exact_
+template. For instance, `proto::terminal< proto::exact<int> >` would only match an
+`int` held by value.
+
+Proto gives you extra wiggle room when matching array types. Array types match
+themselves or the pointer types they decay to. This is especially useful with
+character arrays. The type returned by `proto::as_expr("hello")` is
+`proto::terminal<char const[6]>::type`. That's a terminal containing a
+a 6-element character array. Naturally, you can match this terminal
+with the grammar `proto::terminal<char const[6]>`, but the grammar
+`proto::terminal<char const *>` will match it as well, as the following
+code fragment illustrates.
+
+ struct CharString
+ : proto::terminal< char const * >
+ {};
+
+ typedef proto::terminal< char const[6] >::type char_array;
+
+ BOOST_MPL_ASSERT(( proto::matches< char_array, CharString > ));
+
+What if we only wanted `CharString` to match terminals of exactly the type
+`char const *`? You can use _exact_ here to turn off the fuzzy matching of
+terminals, as follows:
+
+ struct CharString
+ : proto::terminal< proto::exact< char const * > >
+ {};
+
+ typedef proto::terminal<char const[6]>::type char_array;
+ typedef proto::terminal<char const *>::type char_string;
+
+ BOOST_MPL_ASSERT(( proto::matches< char_string, CharString > ));
+ BOOST_MPL_ASSERT_NOT(( proto::matches< char_array, CharString > ));
+
+Now, `CharString` does not match array types, only character string pointers.
+
+The inverse problem is a little trickier: what if you wanted to match all
+character arrays, but not character pointers? As mentioned above, the
+expression `as_expr("hello")` has the type
+`proto::terminal< char const[ 6 ] >::type`. If you wanted to match character
+arrays of arbitrary size, you could use `proto::N`, which is an array-size
+wildcard. The following grammar would match any string literal:
+`proto::terminal< char const[ proto::N ] >`.
+
+Sometimes you need even more wiggle room when matching terminals. For
+example, maybe you're building a calculator DSEL and you want to allow any
+terminals that are convertible to `double`. For that, Proto provides the
+_convertible_to_ template. You can use it as:
+`proto::terminal< proto::convertible_to< double > >`.
+
+There is one more way you can perform a fuzzy match on terminals. Consider the
+problem of trying to match a `std::complex<>` terminal. You can easily match
+a `std::complex<float>` or a `std::complex<double>`, but how would you match
+any instantiation of `std::complex<>`? You can use `proto::_` here to solve
+this problem. Here is the grammar to match any `std::complex<>` instantiation:
+
+ struct StdComplex
+ : proto::terminal< std::complex< proto::_ > >
+ {};
+
+When given a grammar like this, Proto will deconstruct the grammar and the
+terminal it is being matched against and see if it can match all the
+constituents.
+
+[endsect]
+
+[/====================================================]
+[section:if_and_not [^if_<>], [^and_<>], and [^not_<>]]
+[/====================================================]
+
+We've already seen how to use expression generators like `proto::terminal<>` and
+`proto::shift_right<>` as grammars. We've also seen _or_, which we can use to
+express a set of alternate grammars. There are a few others of interest; in
+particular, _if_, _and_ and _not_.
+
+The _not_ template is the simplest. It takes a grammar as a template parameter
+and logically negates it; `not_<Grammar>` will match any expression that
+`Grammar` does /not/ match.
+
+The _if_ template is used together with a Proto transform that is evaluated
+against expression types to find matches. (Proto transforms will be described
+later.)
+
+The _and_ template is like _or_, except that each argument of the _and_ must
+match in order for the _and_ to match. As an example, consider the definition
+of `CharString` above that uses _exact_. It could have been written without
+_exact_ as follows:
+
+ struct CharString
+ : proto::and_<
+ proto::terminal< proto::_ >
+ , proto::if_< boost::is_same< proto::_value, char const * >() >
+ >
+ {};
+
+This says that a `CharString` must be a terminal, /and/ its value type must be
+the same as `char const *`. Notice the template argument of _if_:
+`boost::is_same< proto::_value, char const * >()`. This is Proto transform that
+compares the value type of a terminal to `char const *`.
+
+The _if_ template has a couple of variants. In additon to `if_<Condition>` you
+can also say `if_<Condition, ThenGrammar>` and
+`if_<Condition, ThenGrammar, ElseGrammar>`. These let you select one sub-grammar
+or another based on the `Condition`.
+
+[endsect]
+
+[/=======================================================]
+[section:switch Improving Compile Times With [^switch_<>]]
+[/=======================================================]
+
+When your Proto grammar gets large, you'll start to run into some scalability problems with _or_, the construct you use to specify alternate sub-grammars. First, due to limitations in C++, _or_ can only accept up to a certain number of sub-grammars, controlled by the `BOOST_PROTO_MAX_LOGICAL_ARITY` macro. This macro defaults to eight, and you can set it higher, but doing so will aggravate another scalability problem: long compile times. With _or_, alternate sub-grammars are tried in order -- like a series of cascading `if`'s -- leading to lots of unnecessary template instantiations. What you would prefer instead is something like `switch` that avoids the expense of cascading `if`'s. That's the purpose of _switch_; although less convenient than _or_, it improves compile times for larger grammars and does not have an arbitrary fixed limit on the number of sub-grammars.
+
+Let's illustrate how to use _switch_ by first writing a big grammar with _or_ and then translating it to an equivalent grammar using _switch_:
+
+ // Here is a big, innefficient grammar
+ struct ABigGrammar
+ : proto::or_<
+ proto::terminal<int>
+ , proto::terminal<double>
+ , proto::unary_plus<ABigGrammar>
+ , proto::negate<ABigGrammar>
+ , proto::complement<ABigGrammar>
+ , proto::plus<ABigGrammar, ABigGrammar>
+ , proto::minus<ABigGrammar, ABigGrammar>
+ , proto::or_<
+ proto::multiplies<ABigGrammar, ABigGrammar>
+ , proto::divides<ABigGrammar, ABigGrammar>
+ , proto::modulus<ABigGrammar, ABigGrammar>
+ >
+ >
+ {};
+
+The above might be the grammar to a more elaborate calculator DSEL. Notice that since there are more than eight sub-grammars, we had to chain the sub-grammars with a nested _or_ -- not very nice.
+
+The idea behind _switch_ is to dispatch based on an expression's tag type to a sub-grammar that handles expressions of that type. To use _switch_, you define a struct with a nested `case_<>` template, specialized on tag types. The above grammar can be expressed using _switch_ as follows. It is described below.
+
+ // Redefine ABigGrammar more efficiently using proto::switch_<>
+ struct ABigGrammar;
+
+ struct ABigGrammarCases
+ {
+ // The primary template matches nothing:
+ template<typename Tag>
+ struct case_
+ : proto::not_<_>
+ {};
+ };
+
+ // Terminal expressions are handled here
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::terminal>
+ : proto::or_<
+ proto::terminal<int>
+ , proto::terminal<double>
+ >
+ {};
+
+ // Non-terminals are handled similarly
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::unary_plus>
+ : proto::unary_plus<ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::negate>
+ : proto::negate<ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::complement>
+ : proto::complement<ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::plus>
+ : proto::plus<ABigGrammar, ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::minus>
+ : proto::minus<ABigGrammar, ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::multiplies>
+ : proto::multiplies<ABigGrammar, ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::divides>
+ : proto::divides<ABigGrammar, ABigGrammar>
+ {};
+
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::modulus>
+ : proto::modulus<ABigGrammar, ABigGrammar>
+ {};
+
+ // Define ABigGrammar in terms of ABigGrammarCases
+ // using proto::switch_<>
+ struct ABigGrammar
+ : proto::switch_<ABigGrammarCases>
+ {};
+
+Matching an expression type `E` against `proto::switch_<C>` is equivalent to matching it against `C::case_<E::proto_tag>`. By dispatching on the expression's tag type, we can jump to the sub-grammar that handles expressions of that type, skipping over all the other sub-grammars that couldn't possibly match. If there is no specialization of `case_<>` for a particular tag type, we select the primary template. In this case, the primary template inherits from `proto::not_<_>` which matches no expressions.
+
+Notice the specialization that handles terminals:
+
+ // Terminal expressions are handled here
+ template<>
+ struct ABigGrammarCases::case_<proto::tag::terminal>
+ : proto::or_<
+ proto::terminal<int>
+ , proto::terminal<double>
+ >
+ {};
+
+The `proto::tag::terminal` type by itself isn't enough to select an appropriate sub-grammar, so we use _or_ to list the alternate sub-grammars that match terminals.
+
+[note You might be tempted to define your `case_<>` specializations /in situ/ as follows:
+
+``
+ struct ABigGrammarCases
+ {
+ template<typename Tag>
+ struct case_ : proto::not_<_> {};
+
+ // ERROR: not legal C++
+ template<>
+ struct case_<proto::tag::terminal>
+ /* ... */
+ };
+``
+
+Unfortunately, for arcane reasons, it is not legal to define an explicit nested specialization /in situ/ like this. It is, however, perfectly legal to define /partial/ specializations /in situ/, so you can add a extra dummy template parameter that has a default, as follows:
+
+``
+ struct ABigGrammarCases
+ {
+ // Note extra "Dummy" template parameter here:
+ template<typename Tag, int Dummy = 0>
+ struct case_ : proto::not_<_> {};
+
+ // OK: "Dummy" makes this a partial specialization
+ // instead of an explicit specialization.
+ template<int Dummy>
+ struct case_<proto::tag::terminal, Dummy>
+ /* ... */
+ };
+``
+
+You might find this cleaner than defining explicit `case_<>` specializations outside of their enclosing struct.
+]
+
+[endsect]
+
+[/==================================]
+[section Matching Vararg Expressions]
+[/==================================]
+
+Not all of C++'s overloadable operators are unary or binary. There is the
+oddball `operator()` -- the function call operator -- which can have any number
+of arguments. Likewise, with Proto you may define your own "operators" that
+could also take more that two arguments. As a result, there may be nodes in
+your Proto expression tree that have an arbitrary number of children (up to
+`BOOST_PROTO_MAX_ARITY`, which is configurable). How do you write a grammar to
+match such a node?
+
+For such cases, Proto provides the _vararg_ class template. Its template
+argument is a grammar, and the _vararg_ will match the grammar zero or more
+times. Consider a Proto lazy function called `fun()` that can take zero or
+more characters as arguments, as follows:
+
+ struct fun_tag {};
+ struct FunTag : proto::terminal< fun_tag > {};
+ FunTag::type const fun = {{}};
+
+ // example usage:
+ fun();
+ fun('a');
+ fun('a', 'b');
+ ...
+
+Below is the grammar that matches all the allowable invocations of `fun()`:
+
+ struct FunCall
+ : proto::function< FunTag, proto::vararg< proto::terminal< char > > >
+ {};
+
+The `FunCall` grammar uses _vararg_ to match zero or more character literals
+as arguments of the `fun()` function.
+
+As another example, can you guess what the following grammar matches?
+
+ struct Foo
+ : proto::or_<
+ proto::terminal< proto::_ >
+ , proto::nary_expr< proto::_, proto::vararg< Foo > >
+ >
+ {};
+
+Here's a hint: the first template parameter to `proto::nary_expr<>` represents the
+node type, and any additional template parameters represent child nodes. The answer
+is that this is a degenerate grammar that matches every possible expression tree,
+from root to leaves.
+
+[endsect]
+
+[/=============================]
+[section Defining DSEL Grammars]
+[/=============================]
+
+In this section we'll see how to use Proto to define a grammar for your DSEL and
+use it to validate expression templates, giving short, readable compile-time errors
+for invalid expressions.
+
+[tip You might think that this is a backwards way of doing things. ["If Proto let
+me select which operators to overload, my users wouldn't be able to create invalid
+expressions in the first place, and I wouldn't need a grammar at all!] That may be
+true, but there are reasons for preferring to do things this way.
+
+First, it lets you develop your DSEL rapidly -- all the operators are there for you
+already! -- and worry about invalid syntax later.
+
+Second, it might be the case that some operators are only allowed in certain
+contexts within your DSEL. This is easy to express with a grammar, and hard to do
+with straight operator overloading.
+
+Third, using a DSEL grammar to flag invalid expressions can often yield better
+errors than manually selecting the overloaded operators.
+
+Fourth, the grammar can be used for more than just validation. You can use your
+grammar to define ['tree transformations] that convert expression templates into
+other more useful objects.
+
+If none of the above convinces you, you actually /can/ use Proto to control which
+operators are overloaded within your domain. And to do it, you need to define a
+grammar!]
+
+In a previous section, we used Proto to define a DSEL for a lazily evaluated
+calculator that allowed any combination of placeholders, floating-point
+literals, addition, subtraction, multiplaction, division and grouping. If
+we were to write the grammar for this DSEL in
+[@http://en.wikipedia.org/wiki/Extended_Backus_Naur_Form EBNF], it might look
+like this:
+
+[pre
+group ::= '(' expression ')'
+factor ::= double | '_1' | '_2' | group
+term ::= factor (('*' factor) | ('/' factor))*
+expression ::= term (('+' term) | ('-' term))*
+]
+
+This captures the syntax, associativity and precedence rules of a calculator.
+Writing the grammar for our calculator DSEL using Proto is /even simpler/.
+Since we are using C++ as the host language, we are bound to the associativity
+and precedence rules for the C++ operators. Our grammar can assume them. Also,
+in C++ grouping is already handled for us with the use of parenthesis, so we
+don't have to code that into our grammar.
+
+Let's begin our grammar for forward-declaring it:
+
+ struct CalculatorGrammar;
+
+It's an incomplete type at this point, but we'll still be able to use it to
+define the rules of our grammar. Let's define grammar rules for the terminals:
+
+ struct Double
+ : proto::terminal< proto::convertible_to< double > >
+ {};
+
+ struct Placeholder1
+ : proto::terminal< placeholder<0> >
+ {};
+
+ struct Placeholder2
+ : proto::terminal< placeholder<1> >
+ {};
+
+ struct Terminal
+ : proto::or_< Double, Placeholder1, Placeholder2 >
+ {};
+
+Now let's define the rules for addition, subtraction, multiplication and division.
+Here, we can ignore issues of associativity and precedence -- the C++ compiler will
+enforce that for us. We only must enforce that the arguments to the operators must
+themselves conform to the `CalculatorGrammar` that we forward-declared above.
+
+ struct Plus
+ : proto::plus< CalculatorGrammar, CalculatorGrammar >
+ {};
+
+ struct Minus
+ : proto::minus< CalculatorGrammar, CalculatorGrammar >
+ {};
+
+ struct Multiplies
+ : proto::multiplies< CalculatorGrammar, CalculatorGrammar >
+ {};
+
+ struct Divides
+ : proto::divides< CalculatorGrammar, CalculatorGrammar >
+ {};
+
+Now that we've defined all the parts of the grammar, we can define
+`CalculatorGrammar`:
+
+ struct CalculatorGrammar
+ : proto::or_<
+ Terminal
+ , Plus
+ , Minus
+ , Multiplies
+ , Divides
+ >
+ {};
+
+That's it! Now we can use `CalculatorGrammar` to enforce that an expression
+template conforms to our grammar. We can use _matches_ and `BOOST_MPL_ASSERT()`
+to issue readable compile-time errors for invalid expressions, as below:
+
+ template< typename Expr >
+ void evaluate( Expr const & expr )
+ {
+ BOOST_MPL_ASSERT(( proto::matches< Expr, CalculatorGrammar > ));
+ // ...
+ }
+
+[endsect]
+
+[endsect]
+
+[endsect]
Modified: trunk/libs/proto/doc/proto.qbk
==============================================================================
--- trunk/libs/proto/doc/proto.qbk (original)
+++ trunk/libs/proto/doc/proto.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
@@ -49,6 +49,8 @@
[classref boost::proto::expr<Tag,Args,1> `proto::expr<>`]]
[def _deep_copy_
[funcref boost::proto::deep_copy `proto::deep_copy()`]]
+[def _domain_
+ [classref boost::proto::domain `proto::domain<>`]]
[def _extends_
[classref boost::proto::extends `proto::extends<>`]]
[def _as_expr_
@@ -124,39 +126,39 @@
[def _flatten_
[funcref boost::proto::flatten `proto::flatten()`]]
[def _value_pt_
- [classref boost::proto::_value [^proto::_value]]]
+ [classref boost::proto::_value `proto::_value`]]
[def _child_c_pt_
- [classref boost::proto::_child_c [^proto::_child_c<>]]]
+ [classref boost::proto::_child_c `proto::_child_c<>`]]
[def _child_pt_
- [classref boost::proto::_child [^proto::_child]]]
+ [classref boost::proto::_child `proto::_child`]]
[def _left_pt_
- [classref boost::proto::_left [^proto::_left]]]
+ [classref boost::proto::_left `proto::_left`]]
[def _right_pt_
- [classref boost::proto::_right [^proto::_right]]]
-[def _wild_pt_
- [classref boost::proto::_ [^proto::_]]]
+ [classref boost::proto::_right `proto::_right`]]
+[def _wild_
+ [classref boost::proto::_ `proto::_`]]
[def _expr_pt_
- [classref boost::proto::_expr [^proto::_expr]]]
+ [classref boost::proto::_expr `proto::_expr`]]
[def _state_pt_
- [classref boost::proto::_state [^proto::_state]]]
+ [classref boost::proto::_state `proto::_state`]]
[def _data_pt_
- [classref boost::proto::_data [^proto::_data]]]
+ [classref boost::proto::_data `proto::_data`]]
[def _call_pt_
- [classref boost::proto::call [^proto::call<>]]]
+ [classref boost::proto::call `proto::call<>`]]
[def _make_pt_
- [classref boost::proto::make [^proto::make<>]]]
+ [classref boost::proto::make `proto::make<>`]]
[def _default_pt_
- [classref boost::proto::_default [^proto::_default<>]]]
+ [classref boost::proto::_default `proto::_default<>`]]
[def _fold_pt_
- [classref boost::proto::fold [^proto::fold<>]]]
+ [classref boost::proto::fold `proto::fold<>`]]
[def _fold_tree_pt_
- [classref boost::proto::fold_tree [^proto::fold_tree<>]]]
+ [classref boost::proto::fold_tree `proto::fold_tree<>`]]
[def _reverse_fold_pt_
- [classref boost::proto::reverse_fold [^proto::reverse_fold<>]]]
+ [classref boost::proto::reverse_fold `proto::reverse_fold<>`]]
[def _reverse_fold_tree_pt_
- [classref boost::proto::reverse_fold_tree [^proto::reverse_fold_tree<>]]]
+ [classref boost::proto::reverse_fold_tree `proto::reverse_fold_tree<>`]]
[def _lazy_pt_
- [classref boost::proto::lazy [^proto::lazy<>]]]
+ [classref boost::proto::lazy `proto::lazy<>`]]
[def _SYB_
[link boost_proto.users_guide.resources.SYB ["Scrap Your Boilerplate]]]
@@ -166,41 +168,36 @@
[section:users_guide Users' Guide]
[/===============================]
-This Users' Guide describes how to use Proto to build expression-template
-based Domain-Specific Embedded Langauges. It is broken up in to 5 sections,
-corresponding to the 5 major parts to Proto:
+[/===========================================================]
+[heading Compilers, Compiler Construction Toolkits, and Proto]
+[/===========================================================]
+
+Most compilers have front ends and back ends. The front end parses the text of an input program into some intermediate form like an abstract syntax tree, and the back end takes the intermediate form and generates an executable from it.
+
+A library built with Proto is essentially a compiler for a domain-specific embedded language (DSEL). It also has a front end, an intermediate form, and a back end. The front end is comprised of the symbols (a.k.a., terminals), members, operators and functions that make up the user-visible aspects of the DSEL. The back end is made of evaluation contexts and transforms that give meaning and behavior to the expression templates generated by the front end. In between is the intermediate form: the expression template itself, which is an abstract syntax tree in a very real sense.
+
+To build a library with Proto, you will first decide what your interface will be; that is, you'll design a programming language for your domain and build the front end with tools provided by Proto. Then you'll design the back end by writing evaluation contexts and/or transforms that accept expression templates and do interesting things with them.
+
+This users' guide is organized as follows. After a [link boost_proto.users_guide.getting_started Getting Started guide], we'll cover the tools Proto provides for defining and manipulating the three major parts of a compiler:
[variablelist
-[[[link boost_proto.users_guide.expression_construction Expression Construction]]
- [Describes how to use Proto to build expression trees.]]
-[[[link boost_proto.users_guide.expression_evaluation Expression Evaluation]]
- [Describes the tools Proto provides for making your expression trees do
- something useful.]]
-[[[link boost_proto.users_guide.expression_introspection Expression Introspection]]
- [Describes Proto's grammar matching facilities, which make
- it easy to discover the structure of an expression tree.]]
-[[[link boost_proto.users_guide.expression_transformation Expression Transformation]]
- [Describes how to write expression transforms that turn an expression tree
- into some other object.]]
-[[[link boost_proto.users_guide.expression_extension Expression Extension]]
- [Describes how to extend Proto expressions with additional behaviors and
- members and how to selectively disable Proto's operator overloads.]]
+ [[[link boost_proto.users_guide.front_end Front Ends]]
+ [How to define the aspects of your DSEL with which your users will interact directly.]]
+ [[[link boost_proto.users_guide.intermediate_form Intermediate Form]]
+ [What Proto expression templates look like, how to discover their structure and access their constituents.]]
+ [[[link boost_proto.users_guide.back_end Back Ends]]
+ [How to define evaluation contexts and transforms that make expression templates do interesting things.]]
]
-But before we get started, let's have a look at some very simple Proto examples
-and say a few words about Proto's philosophy.
+After that, you may be interested in seeing some [link boost_proto.users_guide.examples Examples] to get a better idea of how the pieces all fit together.
[include getting_started.qbk]
-[include construction.qbk]
-
-[include evaluation.qbk]
-
-[include grammars.qbk]
+[include front_end.qbk]
-[include transforms.qbk]
+[include intermediate_form.qbk]
-[include extensibility.qbk]
+[include back_end.qbk]
[include examples.qbk]
Deleted: trunk/libs/proto/doc/transforms.qbk
==============================================================================
--- trunk/libs/proto/doc/transforms.qbk 2008-10-16 22:48:46 EDT (Thu, 16 Oct 2008)
+++ (empty file)
@@ -1,1014 +0,0 @@
-[/
- / Copyright (c) 2006 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)
- /]
-
-[import ../test/examples.cpp]
-
-[/============================================================================]
-[section:expression_transformation Expression Transformation: Semantic Actions]
-[/============================================================================]
-
-If you have ever built a parser with the help of a tool like Antlr, yacc or Boost.Spirit, you might be familiar with /semantic actions/. In addition to allowing you to define the grammar of the language recognized by the parser, these tools let you embed code within your grammar that executes when parts of the grammar participate in a parse. Proto has the equivalent of semantic actions. They are called /transforms/. This section describes how to embed transforms within your Proto grammars, turning your grammars into function objects that can manipulate or evaluate expressions in powerful ways.
-
-Proto transforms are an advanced topic. We'll take it slow, using examples to illustrate the key concepts, starting simple.
-
-[/==================================]
-[section ["Activating] Your Grammars]
-[/==================================]
-
-The Proto grammars we've seen so far are static. You can check at compile-time to see if an expression type matches a grammar, but that's it. Things get more interesting when you give them runtime behaviors. A grammar with embedded transforms is more than just a static grammar. It is a function object that accepts expressions that match the grammar and does /something/ with them.
-
-Below is a very simple grammar. It matches terminal expressions.
-
- // A simple Proto grammar that matches all terminals
- proto::terminal< _ >
-
-Here is the same grammar with a transform that extracts the value from the terminal:
-
- // A simple Proto grammar that matches all terminals
- // *and* a function object that extracts the value from
- // the terminal
- proto::when<
- proto::terminal< _ >
- , proto::_value // <-- Look, a transform!
- >
-
-You can read this as follows: when you match a terminal expression, extract the value. The type `proto::_value` is a so-called transform. Later we'll see what makes it a transform, but for now just think of it as a kind of function object. Note the use of _when_: the first template parameter is the grammar to match and the second is the transform to execute. The result is both a grammar that matches terminal expressions and a function object that accepts terminal expressions and extracts their values.
-
-As with ordinary grammars, we can define an empty struct that inherits from a grammar+transform to give us an easy way to refer back to the thing we're defining, as follows:
-
- // A grammar and a function object, as before
- struct Value
- : proto::when<
- proto::terminal< _ >
- , proto::_value
- >
- {};
-
- // "Value" is a grammar that matches terminal expressions
- BOOST_MPL_ASSERT(( proto::matches< proto::terminal<int>::type, Value > ));
-
- // "Value" also defines a function object that accepts terminals
- // and extracts their value.
- proto::terminal<int>::type answer = {42};
- Value get_value;
- int i = get_value( answer );
-
-As already mentioned, `Value` is a grammar that matches terminal expressions and a function object that operates on terminal expressions. It would be an error to pass a non-terminal expression to the `Value` function object. This is a general property of grammars with transforms; when using them as function objects, expressions passed to them must match the grammar.
-
-Proto grammars are valid TR1-style function objects. That means you can use `boost::result_of<>` to ask a grammar what its return type will be, given a particular expression type. For instance, we can access the `Value` grammar's return type as follows:
-
- // We can use boost::result_of<> to get the return type
- // of a Proto grammar.
- typedef
- typename boost::result_of<Value(proto::terminal<int>::type)>::type
- result_type;
-
- // Check that we got the type we expected
- BOOST_MPL_ASSERT(( boost::is_same<result_type, int> ));
-
-[note A grammar with embedded transforms is both a grammar and a function object. Calling these things "grammars with transforms" would get tedious. We could call them something like "active grammars", but as we'll see /every/ grammar that you can define with Proto is "active"; that is, every grammar has some behavior when used as a function object. So we'll continue calling these things plain "grammars". The term "transform" is reserved for the thing that is used as the second parameter to the _when_ template.]
-
-[endsect]
-
-[/=========================================]
-[section Handling Alternation and Recursion]
-[/=========================================]
-
-Most grammars are a little more complicated than the one in the preceeding section. For the sake of illustration, let's define a rather nonsensical grammar that matches any expression and recurses to the leftmost terminal and returns its value. It will demonstrate how two key concepts of Proto grammars -- alternation and recursion -- interact with transforms. The grammar is described below.
-
- // A grammar that matches any expression, and a function object
- // that returns the value of the leftmost terminal.
- struct LeftmostLeaf
- : proto::or_<
- // If the expression is a terminal, return its value
- proto::when<
- proto::terminal< _ >
- , proto::_value
- >
- // Otherwise, it is a non-terminal. Return the result
- // of invoking LeftmostLeaf on the 0th (leftmost) child.
- , proto::when<
- _
- , LeftmostLeaf( proto::_child0 )
- >
- >
- {};
-
- // A Proto terminal wrapping std::cout
- proto::terminal< std::ostream & >::type cout_ = { std::cout };
-
- // Create an expression and use LeftmostLeaf to extract the
- // value of the leftmost terminal, which will be std::cout.
- std::ostream & sout = LeftmostLeaf()( cout_ << "the answer: " << 42 << '\n' );
-
-We've seen `proto::or_<>` before. Here it is serving two roles. First, it is a grammar that matches any of its alternate sub-grammars; in this case, either a terminal or a non-terminal. Second, it is also a function object that accepts an expression, finds the alternate sub-grammar that matches the expression, and applies its transform. And since `LeftmostLeaf` inherits from `proto::or_<>`, `LeftmostLeaf` is also both a grammar and a function object.
-
-[def _some_transform_ [~some-transform]]
-
-[note The second alternate uses `proto::_` as its grammar. Recall that `proto::_` is the wildcard grammar that matches any expression. Since alternates in `proto::or_<>` are tried in order, and since the first alternate handles all terminals, the second alternate handles all (and only) non-terminals. Often enough, `proto::when< _, _some_transform_ >` is the last alternate in a grammar, so for improved readability, you could use the equivalent `proto::otherwise< _some_transform_ >`.]
-
-The next section describes this grammar further.
-
-[endsect]
-
-[/==========================]
-[section Callable Transforms]
-[/==========================]
-
-[def __bold_transform__ [*LeftmostLeaf( proto::_child0 )]]
-
-In the grammar defined in the preceeding section, the transform associated with non-terminals is a little strange-looking:
-
- proto::when<
- _
- , __bold_transform__ // <-- a "callable" transform
- >
-
-It has the effect of accepting non-terminal expressions, taking the 0th (leftmost) child and recursively invoking the `LeftmostLeaf` function on it. But `LeftmostLeaf( proto::_child0 )` is actually a /function type/. Literally, it is the type of a function that accepts an object of type `proto::_child0` and returns an object of type `LeftmostLeaf`. So how do we make sense of this transform? Clearly, there is no function that actually has this signature, nor would such a function be useful. The key is in understanding how `proto::when<>` /interprets/ its second template parameter.
-
-When the second template parameter to _when_ is a function type, _when_ interprets the function type as a transform. In this case, `LeftmostLeaf` is treated as the type of a function object to invoke, and `proto::_child0` is treated as a transform. First, `proto::_child0` is applied to the current expression (the non-terminal that matched this alternate sub-grammar), and the result (the 0th child) is passed as an argument to `LeftmostLeaf`.
-
-[note *Transforms are a Domain-Specific Language*
-
-`LeftmostLeaf( proto::_child0 )` /looks/ like an invocation of the `LeftmostLeaf` function object, but it's not, but then it actually is! Why this confusing subterfuge? Function types give us a natural and concise syntax for composing more complicated transforms from simpler ones. The fact that the syntax is suggestive of a function invocation is on purpose. It is a domain-specific embedded language for defining expression transformations. If the subterfuge worked, it may have fooled you into thinking the transform is doing exactly what it actually does! And that's the point.]
-
-The type `LeftmostLeaf( proto::_child0 )` is an example of a /callable transform/. It is a function type that represents a function object to call and its arguments. The types `proto::_child0` and `proto::_value` are /primitive transforms/. They are plain structs, not unlike function objects, from which callable transforms can be composed. There is one other type of transform, /object transforms/, that we'll encounter next.
-
-[endsect]
-
-[/========================]
-[section Object Transforms]
-[/========================]
-
-The very first transform we looked at simply extracted the value of terminals. Let's do the same thing, but this time we'll promote all ints to longs first. (Please forgive the contrived-ness of the examples so far; they get more interesting later.) Here's the grammar:
-
- // A simple Proto grammar that matches all terminals,
- // and a function object that extracts the value from
- // the terminal, promoting ints to longs:
- struct ValueWithPomote
- : proto::or_<
- proto::when<
- proto::terminal< int >
- , long(proto::_value) // <-- an "object" transform
- >
- , proto::when<
- proto::terminal< _ >
- , proto::_value
- >
- >
- {};
-
-You can read the above grammar as follows: when you match an int terminal, extract the value from the terminal and use it to initialize a long; otherwise, when you match another kind of terminal, just extract the value. The type `long(proto::_value)` is a so-called /object/ transform. It looks like the creation of a temporary long, but it's really a function type. Just as a callable transform is a function type that represents a function to call and its arguments, an object transforms is a function type that represents an object to construct and the arguments to its constructor.
-
-[/================================================]
-[note *Object Transforms vs. Callable Transforms*
-
-When using function types as Proto transforms, they can either represent an object to construct or a function to call. It is similar to "normal" C++ where the syntax `foo("arg")` can either be interpreted as an object to construct or a function to call, depending on whether `foo` is a type or a function. But consider two of the transforms we've seen so far:
-
-``
- LeftmostLeaf(proto::_child0) // <-- a callable transform
- long(proto::_value) // <-- an object transform
-``
-
-Proto can't know in general which is which, so it uses a trait, `proto::is_callable<>`, to differentiate. `is_callable< long >::value` is false so `long(proto::_value)` is an object to construct, but `is_callable< LeftmostLeaf >::value` is true so `LeftmostLeaf(proto::_child0)` is a function to call. Later on, we'll see how Proto recognizes a type as "callable".]
-[/================================================]
-
-[endsect]
-
-[/================================]
-[section Example: Calculator Arity]
-[/================================]
-
-Now that we have the basics of Proto transforms down, let's consider a slightly more realistic example. We can use transforms to improve the type-safety of the [link boost_proto.users_guide.getting_started.hello_calculator calculator DSEL]. If you recall, it lets you write infix arithmetic expressions involving argument placeholders like `_1` and `_2` and pass them to STL algorithms as function objects, as follows:
-
- double a1[4] = { 56, 84, 37, 69 };
- double a2[4] = { 65, 120, 60, 70 };
- double a3[4] = { 0 };
-
- // Use std::transform() and a calculator expression
- // to calculate percentages given two input sequences:
- std::transform(a1, a1+4, a2, a3, (_2 - _1) / _2 * 100);
-
-This works because we gave calculator expressions an `operator()` that evaluates the expression, replacing the placeholders with the arguments to `operator()`. The overloaded `calculator<>::operator()` looked like this:
-
- // Overload operator() to invoke proto::eval() with
- // our calculator_context.
- template<typename Expr>
- double
- calculator<Expr>::operator()(double a1 = 0, double a2 = 0, double a3 = 0) const
- {
- calculator_context ctx;
- ctx.args.push_back(a1);
- ctx.args.push_back(a2);
- ctx.args.push_back(a3);
-
- return proto::eval(*this, ctx);
- }
-
-Although this works, it's not ideal because it doesn't warn users if they supply too many or too few arguments to a calculator expression. Consider the following mistakes:
-
- (_1 * _1)(4, 2); // Oops, too many arguments!
- (_2 * _2)(42); // Oops, too few arguments!
-
-The expression `_1 * _1` defines a unary calculator expression; it takes one argument and squares it. If we pass more than one argument, the extra arguments will be silently ignored, which might be surprising to users. The next expression, `_2 * _2` defines a binary calculator expression; it takes two arguments, ignores the first and squares the second. If we only pass one argument, the code silently fills in `0.0` for the second argument, which is also probably not what users expect. What can be done?
-
-We can say that the /arity/ of a calculator expression is the number of arguments it expects, and it is equal to the largest placeholder in the expression. So, the arity of `_1 * _1` is one, and the arity of `_2 * _2` is two. We can increase the type-safety of our calculator DSEL by making sure the artiy of an expression equals the actual number of arguments supplied. Computing the artiy of an expression is simple with the help of Proto transforms.
-
-It's straightforward to describe in words how the arity of an expression should
-be calculated. Consider that calculator expressions can be made of `_1`, `_2`, literals, unary expressions and binary expressions. The following table shows the arities for each of these 5 constituents.
-
-[table Calculator Sub-Expression Arities
- [[Sub-Expression] [Arity]]
- [[Placeholder 1] [`1`]]
- [[Placeholder 2] [`2`]]
- [[Literal] [`0`]]
- [[Unary Expression] [ /arity of the operand/ ]]
- [[Binary Expression] [ /max arity of the two operands/ ]]
-]
-
-Using this information, we can write the grammar for calculator expressions and attach transforms for computing the arity of each constituent. The code below computes the expression arity as a compile-time integer, using integral wrappers and metafunctions from the Boost MPL Library. The grammar is described below.
-
-[CalcArity]
-
-When we find a placeholder terminal or a literal, we use an /object transform/ such as `mpl::int_<1>()` to create a (default-constructed) compile-time integer representing the arity of that terminal.
-
-For unary expressions, we use `CalcArity(proto::_child)` which is a /callable transform/ that computes the arity of the expression's child.
-
-The transform for binary expressions has a few new tricks. Let's look more closely:
-
- // Compute the left and right arities and
- // take the larger of the two.
- mpl::max<CalcArity(proto::_left),
- CalcArity(proto::_right)>()
-
-This is an object transform; it default-constructs ... what exactly? The `mpl::max<>` template is an MPL metafunction that accepts two compile-time integers. It has a nested `::type` typedef (not shown) that is the maximum of the two. But here, we appear to be passing it two things that are /not/ compile-time integers; they're Proto callable transforms. Proto is smart enough to recognize that fact. It first evaluates the two nested callable transforms, computing the arities of the left and right child expressions. Then it puts the resulting integers into `mpl::max<>` and evaluates the metafunction by asking for the nested `::type`. That is the type of the object that gets default-constructed and returned.
-
-More generally, when evaluating object transforms, Proto looks at the object type and checks whether it is a template specialization, like `mpl::max<>`. If it is, Proto looks for nested transforms that it can evaluate. After any nested transforms have been evaluated and substituted back into the template, the new template specialization is the result type, unless that type has a nested `::type`, in which case that becomes the result.
-
-Now that we can calculate the arity of a calculator expression, let's redefine the `calculator<>` expression wrapper we wrote in the Getting Started guide to use the `CalcArity` grammar and some macros from Boost.MPL to issue compile-time errors when users specify too many or too few arguments.
-
- // The calculator expression wrapper, as defined in the Hello
- // Calculator example in the Getting Started guide. It behaves
- // just like the expression it wraps, but with extra operator()
- // member functions that evaluate the expression.
- // NEW: Use the CalcArity grammar to ensure that the correct
- // number of arguments are supplied.
- template<typename Expr>
- struct calculator
- : proto::extends<Expr, calculator<Expr>, calculator_domain>
- {
- typedef
- proto::extends<Expr, calculator<Expr>, calculator_domain>
- base_type;
-
- calculator(Expr const &expr = Expr())
- : base_type(expr)
- {}
-
- typedef double result_type;
-
- // Use CalcArity to compute the arity of Expr:
- static int const arity = boost::result_of<CalcArity(Expr)>::type::value;
-
- double operator()() const
- {
- BOOST_MPL_ASSERT_RELATION(0, ==, arity);
- calculator_context ctx;
- return proto::eval(*this, ctx);
- }
-
- double operator()(double a1) const
- {
- BOOST_MPL_ASSERT_RELATION(1, ==, arity);
- calculator_context ctx;
- ctx.args.push_back(a1);
- return proto::eval(*this, ctx);
- }
-
- // ... and additional operator() overloads to handle more arguments ...
- };
-
-Note the use of `boost::result_of<>` to access the return type of the `CalcArity` function object. Since we used compile-time integers in our transforms, the arity of the expression is encoded in the return type of the `CalcArity` function object. Proto grammars are valid TR1-style function objects, so you can use `boost::result_of<>` to figure out their return types.
-
-With our compile-time assertions in place, when users provide too many or too few arguments to a calculator expression, as in:
-
- (_2 * _2)(42); // Oops, too few arguments!
-
-... they will get a compile-time error message on the line with the assertion that reads something like this[footnote This error message was generated with Microsoft Visual C++ 9.0. Different compilers will emit different messages with varying degrees of readability.]:
-
-[pre
-c:\boost\org\trunk\libs\proto\scratch\main.cpp(97) : error C2664: 'boost::mpl::asse
-rtion\_failed' : cannot convert parameter 1 from 'boost::mpl::failed \*\*\*\*\*\*\*\*\*\*\*\*boo
-st::mpl::assert\_relation<x,y,\_\_formal>::\*\*\*\*\*\*\*\*\*\*\*\*' to 'boost::mpl::assert<false>
-::type'
- with
- \[
- x\=1,
- y\=2,
- \_\_formal\=bool boost::mpl::operator\=\=(boost::mpl::failed,boost::mpl::failed)
- \]
-]
-
-The point of this exercise was to show that we can write a fairly simple Proto grammar with embedded transforms that is declarative and readable and can compute interesting properties of arbitrarily complicated expressions. But transforms can do more than that. Boost.Xpressive uses transforms to turn expressions into finite state automata for matching regular expressions, and Boost.Spirit uses transforms to build recursive descent parser generators. Proto comes with a collection of built-in transforms that you can use to perform very sophisticated expression manipulations like these. In the next few sections we'll see some of them in action.
-
-[endsect]
-
-[/===============================================]
-[section:state Transforms With State Accumulation]
-[/===============================================]
-
-So far, we've only seen examples of grammars with transforms that accept one argument: the expression to transform. But consider for a moment how, in ordinary procedural code, you would turn a binary tree into a linked list. You would start with an empty list. Then, you would recursively convert the right branch to a list, and use the result as the initial state while converting the left branch to a list. That is, you would need a function that takes two parameters: the current node and the list so far. These sorts of /accumulation/ problems are quite common when processing trees. The linked list is an example of an accumulation variable or /state/. Each iteration of the algorithm takes the current element and state, applies some binary function to the two and creates a new state. In the STL, this algorithm is called `std::accumulate()`. In many other languages, it is called /fold/. Let's see how to implement a fold algorithm with Proto transforms.
-
-All Proto grammars can optionally accept a state parameter in addition to the expression to transform. If you want to fold a tree to a list, you'll need to make use of the state parameter to pass around the list you've built so far. As for the list, the Boost.Fusion library provides a `fusion::cons<>` type from which you can build heterogenous lists. The type `fusion::nil` represents an empty list.
-
-Below is a grammar that recognizes output expressions like `cout_ << 42 << '\n'` and puts the arguments into a Fusion list. It is explained below.
-
- // Fold the terminals in output statements like
- // "cout_ << 42 << '\n'" into a Fusion cons-list.
- struct FoldToList
- : proto::or_<
- // Don't add the ostream terminal to the list
- proto::when<
- proto::terminal< std::ostream & >
- , proto::_state
- >
- // Put all other terminals at the head of the
- // list that we're building in the "state" parameter
- , proto::when<
- proto::terminal<_>
- , fusion::cons<proto::_value, proto::_state>(
- proto::_value, proto::_state
- )
- >
- // For left-shift operations, first fold the right
- // child to a list using the current state. Use
- // the result as the state parameter when folding
- // the left child to a list.
- , proto::when<
- proto::shift_left<FoldToList, FoldToList>
- , FoldToList(
- proto::_left
- , FoldToList(proto::_right, proto::_state)
- )
- >
- >
- {};
-
-Before reading on, see if you can apply what you know already about object, callable and primitive transforms to figure out how this grammar works.
-
-When you use the `FoldToList` function, you'll need to pass two arguments: the expression to fold, and the initial state: an empty list. Those two arguments get passed around to each transform. We learned previously that `proto::_value` is a primitive transform that accepts a terminal expression and extracts its value. What we didn't know until now was that it also accepts the current state /and ignores it/. `proto::_state` is also a primitive transform. It accepts the current expression, which it ignores, and the current state, which it returns.
-
-When we find a terminal, we stick it at the head of the cons list, using the current state as the tail of the list. (The first alternate causes the `ostream` to be skipped. We don't want `cout` in the list.) When we find a shift-left node, we apply the following transform:
-
- // Fold the right child and use the result as
- // state while folding the right.
- FoldToList(
- proto::_left
- , FoldToList(proto::_right, proto::_state)
- )
-
-You can read this transform as follows: using the current state, fold the right child to a list. Use the new list as the state while folding the left child to a list.
-
-[tip If your compiler is Microsoft Visual C++, you'll find that the above transform does not compile. The compiler has bugs with its handling of nested function types. You can work around the bug by wrapping the inner transform in `proto::call<>` as follows:
-
-``
- FoldToList(
- proto::_left
- , proto::call<FoldToList(proto::_right, proto::_state)>
- )
-``
-
-`proto::call<>` turns a callable transform into a primitive transform, but more on that later.
-]
-
-Now that we have defined the `FoldToList` function object, we can use it to turn output expressions into lists as follows:
-
- proto::terminal<std::ostream &>::type const cout_ = {std::cout};
-
- // This is the type of the list we build below
- typedef
- fusion::cons<
- int
- , fusion::cons<
- double
- , fusion::cons<
- char
- , fusion::nil
- >
- >
- >
- result_type;
-
- // Fold an output expression into a Fusion list, using
- // fusion::nil as the initial state of the transformation.
- FoldToList to_list;
- result_type args = to_list(cout_ << 1 << 3.14 << '\n', fusion::nil());
-
- // Now "args" is the list: {1, 3.14, '\n'}
-
-When writing transforms, "fold" is such a basic operation that Proto provides a number of built-in fold transforms. We'll get to them later. For now, rest assured that you won't always have to strech your brain so far to do such basic things.
-
-[endsect]
-
-[/================================================]
-[section:data Passing Auxiliary Data To Transforms]
-[/================================================]
-
-In the last section, we saw that we can pass a second parameter to grammars with transforms: an accumulation variable or /state/ that gets updated as your transform executes. There are times when your transforms will need to access auxiliary data that does /not/ accumulate, so bundling it with the state parameter is impractical. Instead, you can pass auxiliary data as a third parameter, known as the /data/ parameter. Below we show an example involving string processing where the data parameter is essential.
-
-[note All Proto grammars are function objects that take one, two or three arguments: the expression, the state, and the data. There are no additional arguments to know about, we promise. In Haskell, there is set of a tree traversal technologies known collectively as _SYB_. In that framework, there are also three parameters: the term, the accumulator, and the context. These are Proto's expression, state and data parameters under different names.]
-
-Expression templates are often used as an optimization to eliminate temporary objects. Condsier the problem of string concatenation: a series of concatenations would result in the needless creation of temporary strings. We can use Proto to make string concatenation very efficient. To make the problem more interesting, we can apply a locale-sensitive transformation to each character during the concatenation. The locale information will be passed as the data parameter.
-
-Consider the following expression template:
-
- proto::lit("hello") + " " + "world";
-
-We would like to concatenate this string into a statically allocated wide character buffer, widening each charater in turn using the specified locale. The first step is to write a grammar that describes this expression, with transforms that calculate the total string length. Here it is:
-
- // A grammar that matches string concatenation expressions, and
- // a transform that calculates the total string length.
- struct StringLength
- : proto::or_<
- proto::when<
- // When you find a character array ...
- proto::terminal<char[proto::N]>
- // ... the length is the size of the array minus 1.
- , mpl::prior<mpl::sizeof_<proto::_value> >()
- >
- , proto::when<
- // The length of a concatenated string is ...
- proto::plus<StringLength, StringLength>
- // ... the sum of the lengths of each sub-string.
- , proto::fold<
- _
- , mpl::size_t<0>()
- , mpl::plus<StringLength, proto::_state>()
- >
- >
- >
- {};
-
-Notice the use of _fold_pt_. It is a primitive transform that takes a sequence, a state, and function, just like `std::accumulate()`. The three template parameters are transforms. The first yields the sequence of expressions over which to fold, the second yields the initial state of the fold, and the third is the function to apply at each iteration. The use of `proto::_` as the first parameter might have you confused. In addition to being Proto's wildcard, `proto::_` is also a primitive transform that returns the current expression, which (if it is a non-terminal) is a sequence of its child expressions.
-
-Next, we need a function object that accepts a narrow string, a wide character buffer, and a `std::ctype<>` facet for doing the locale-specific stuff. It's fairly straightforward.
-
- // A function object that writes a narrow string
- // into a wide buffer.
- struct WidenCopy : proto::callable
- {
- typedef wchar_t *result_type;
-
- wchar_t *
- operator()(char const *str, wchar_t *buf, std::ctype<char> const &ct) const
- {
- for(; *str; ++str, ++buf)
- *buf = ct.widen(*str);
- return buf;
- }
- };
-
-Finally, we need some transforms that actually walk the concatenated string expression, widens the characters and writes them to a buffer. We will pass a `wchar_t*` as the state parameter and update it as we go. We'll also pass the `std::ctype<>` facet as the data parameter. It looks like this:
-
- // Write concatenated strings into a buffer, widening
- // them as we go.
- struct StringCopy
- : proto::or_<
- proto::when<
- proto::terminal<char[proto::N]>
- , WidenCopy(proto::_value, proto::_state, proto::_data)
- >
- , proto::when<
- proto::plus<StringCopy, StringCopy>
- , StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
- )
- >
- >
- {};
-
-Let's look more closely at the transform associated with non-terminals:
-
- StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
- )
-
-This bears a resemblance to the transform in the previous section that folded an expression tree into a list. First we recurse on the left child, writing its strings into the `wchar_t*` passed in as the state parameter. That returns the new value of the `wchar_t*`, which is passed as state while transforming the right child. Both invocations receive the same `std::ctype<>`, which is passed in as the data parameter.
-
-With these pieces in our pocket, we can implement our concatenate-and-widen function as follows:
-
- template<typename Expr>
- void widen( Expr const &expr )
- {
- // Make sure the expression conforms to our grammar
- BOOST_MPL_ASSERT(( proto::matches<Expr, StringLength> ));
-
- // Calculate the length of the string and allocate a buffer statically
- static std::size_t const length =
- boost::result_of<StringLength(Expr)>::type::value;
- wchar_t buffer[ length + 1 ] = {L'\0'};
-
- // Get the current ctype facet
- std::locale loc;
- std::ctype<char> const &ct(std::use_facet<std::ctype<char> >(loc));
-
- // Concatenate and widen the string expression
- StringCopy()(expr, &buffer[0], ct);
-
- // Write out the buffer.
- std::wcout << buffer << std::endl;
- }
-
- int main()
- {
- widen( proto::lit("hello") + " " + "world" );
- }
-
-The above code displays:
-
-[pre
-hello world
-]
-
-This is a rather round-about way of demonstrating that you can pass extra data to a transform as a third parameter. There are no restrictions on what this parameter can be, and (unlike the state parameter) Proto will never mess with it.
-
-[heading Implicit Parameters to Primitive Transforms]
-
-Let's use the above example to illustrate some other niceties of Proto transforms. We've seen that grammars, when used as function objects, can accept up to 3 parameters, and that when using these grammars in callable transforms, you can also specify up to 3 parameters. Let's take another look at the transform associated with non-terminals above:
-
- StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
- )
-
-Here we specify all three parameters to both invocations of the `StringCopy` grammar. But we don't have to specify all three. If we don't specify a third parameter, `proto::_data` is assumed. Likewise for the second parameter and `proto::_state`. So the above transform could have been writen more simply as:
-
- StringCopy(
- proto::_right
- , StringCopy(proto::_left)
- )
-
-The same is true for any primitive transform. The following are all equivalent:
-
-[table Implicit Parameters to Primitive Transforms
- [[Equivalent Transforms]]
- [[`proto::when<_, StringCopy>`]]
- [[`proto::when<_, StringCopy(_)>`]]
- [[`proto::when<_, StringCopy(_, proto::_state)>`]]
- [[`proto::when<_, StringCopy(_, proto::_state, proto::_data)>`]]
-]
-
-[note *Grammars Are Primitive Transforms Are Function Objects*
-
-So far, we've said that all Proto grammars are function objects. But it's more accurate to say that Proto grammars are primitive transforms -- a special kind of function object that takes between 1 and 3 arguments, and that Proto knows to treat specially when used in a callable transform, as in the table above.]
-
-[note *Not All Function Objects Are Primitive Transforms*
-
-You might be tempted now to drop the `_state` and `_data` parameters to `WidenCopy(proto::_value, proto::_state, proto::_data)`. That would be an error. `WidenCopy` is just a plain function object, not a primitive transform, so you must specify all its arguments. We'll see later how to write your own primitive transforms.]
-
-Once you know that primitive transforms will always receive all three parameters -- expression, state, and data -- it makes things possible that wouldn't be otherwise. For instance, consider that for binary expressions, these two transforms are equivalent. Can you see why?
-
-[table Two Equivalent Transforms
- [[Without [^proto::fold<>]][With [^proto::fold<>]]]
- [[``StringCopy(
- proto::_right
- , StringCopy(proto::_left, proto::_state, proto::_data)
- , proto::_data
-)``
-][``proto::fold<_, proto::_state, StringCopy>``]]
-]
-
-[endsect]
-
-[/===========================================]
-[section:built_in Proto's Built-In Transforms]
-[/===========================================]
-
-[def _N_ [~N]]
-[def _G_ [~G]]
-[def _G0_ [~G0]]
-[def _G1_ [~G1]]
-[def _CT_ [~CT]]
-[def _OT_ [~OT]]
-[def _ET_ [~ET]]
-[def _ST_ [~ST]]
-[def _FT_ [~FT]]
-
-Primitive transforms are the building blocks for more interesting composite transforms. Proto defines a bunch of generally useful primitive transforms. They are summarized below.
-
-[variablelist
- [[_value_pt_]
- [Given a terminal expression, return the value of the terminal.]]
- [[_child_c_pt_]
- [Given a non-terminal expression, `proto::_child_c<_N_>` returns the _N_-th
- child.]]
- [[_child_pt_]
- [A synonym for `proto::_child_c<0>`.]]
- [[_left_pt_]
- [A synonym for `proto::_child_c<0>`.]]
- [[_right_pt_]
- [A synonym for `proto::_child_c<1>`.]]
- [[_expr_pt_]
- [Returns the current expression unmodified.]]
- [[_state_pt_]
- [Returns the current state unmodified.]]
- [[_data_pt_]
- [Returns the current data unmodified.]]
- [[_call_pt_]
- [For a given callable transform `_CT_`, `proto::call<_CT_>` turns the
- callable transform into a primitive transform. This is useful for
- disambiguating callable transforms from object transforms, and also for
- working around compiler bugs with nested function types.]]
- [[_make_pt_]
- [For a given object transform `_OT_`, `proto::make<_OT_>` turns the
- object transform into a primitive transform. This is useful for
- disambiguating object transforms from callable transforms, and also for
- working around compiler bugs with nested function types.]]
- [[_default_pt_]
- [Given a grammar _G_, `proto::_default<_G_>` evaluates the current node
- according to the standard C++ meaning of the operation the node represents.
- For instance, if the current node is a binary plus node, the two children
- will both be evaluated according to `_G_` and the results will be added and
- returned. The return type is deduced with the help of the Boost.Typeof
- library.]]
- [[_fold_pt_]
- [Given three transforms `_ET_`, `_ST_`, and `_FT_`,
- `proto::fold<_ET_, _ST_, _FT_>` first evaluates `_ET_` to obtain a Fusion
- sequence and `_ST_` to obtain an initial state for the fold, and then
- evaluates `_FT_` for each element in the sequnce to generate the next
- state from the previous.]]
- [[_reverse_fold_pt_]
- [Like _fold_pt_, except the elements in the Fusion sequence are iterated in
- reverse order.]]
- [[_fold_tree_pt_]
- [Like `proto::fold<_ET_, _ST_, _FT_>`, except that the result of the `_ET_`
- transform is treated as an expression tree that is /flattened/ to generate
- the sequence to be folded. Flattening an expression tree causes child nodes
- with the same tag type as the parent to be put into sequence. For instance,
- `a >> b >> c` would be flattened to the sequence \[`a`, `b`, `c`\], and this
- is the sequence that would be folded.]]
- [[_reverse_fold_tree_pt_]
- [Like _fold_tree_pt_, except that the flattened sequence is iterated in
- reverse order.]]
- [[_lazy_pt_]
- [A combination of _make_pt_ and _call_pt_ that is useful when the nature of
- the transform depends on the expression, state and/or data parameters.
- `proto::lazy<R(A0,A1...An)>` first evaluates `proto::make<R()>` to compute a
- callable type `R2`. Then, it evaluates `proto::call<R2(A0,A1...An)>`.]]
-]
-
-[/============================================]
-[heading All Grammars Are Primitive Transforms]
-[/============================================]
-
-In addition to the above primitive transforms, all of Proto's grammar elements are also primitive transforms. Their behaviors are described below.
-
-[variablelist
- [[_wild_pt_]
- [Returns the current expression unmodified.]]
- [[_or_]
- [For the specified set of alternate sub-grammars, find the one that matches
- the given expression and apply its associated transform.]]
- [[_and_]
- [For the given set of sub-grammars, take the /last/ sub-grammar and apply its
- associated transform.]]
- [[_not_]
- [Returns the current expression unmodified.]]
- [[_if_]
- [Given three transforms, evaluate the first and treat the result as a
- compile-time Boolean value. If it is true, evaluate the second transform.
- Otherwise, evaluate the third.]]
- [[_terminal_]
- [Returns the current terminal expression unmodified.]]
- [[_plus_, _nary_expr_, et. al.]
- [A Proto grammar that matches a non-terminal such as
- `proto::plus<_G0_, _G1_>`, when used as a primitive transform, creates a new
- plus node where the left child is transformed according to `_G0_` and the
- right child with `_G1_`.]]
-]
-
-[/=================================]
-[heading The Pass-Through Transform]
-[/=================================]
-
-Note the primitive transform associated with grammar elements such as _plus_ described above. They possess a so-called /pass-through/ transform. The pass-through transform accepts an expression of a certain tag type (say, `proto::tag::plus`) and creates a new expression of the same tag type, where each child expression is transformed according to the corresponding child grammar of the pass-through transform. So for instance this grammar ...
-
- proto::function< X, proto::vararg<Y> >
-
-... matches function expressions where the first child matches the `X` grammar and the rest match the `Y` grammar. When used as a transform, the above grammar will create a new function expression where the first child is transformed according to `X` and the rest are transformed according to `Y`.
-
-The following class templates in Proto can be used as grammars with pass-through transforms:
-
-[table Class Templates With Pass-Through Transforms
- [[Templates with Pass-Through Transforms]]
- [[`proto::unary_plus<>`]]
- [[`proto::negate<>`]]
- [[`proto::dereference<>`]]
- [[`proto::complement<>`]]
- [[`proto::address_of<>`]]
- [[`proto::logical_not<>`]]
- [[`proto::pre_inc<>`]]
- [[`proto::pre_dec<>`]]
- [[`proto::post_inc<>`]]
- [[`proto::post_dec<>`]]
- [[`proto::shift_left<>`]]
- [[`proto::shift_right<>`]]
- [[`proto::multiplies<>`]]
- [[`proto::divides<>`]]
- [[`proto::modulus<>`]]
- [[`proto::plus<>`]]
- [[`proto::minus<>`]]
- [[`proto::less<>`]]
- [[`proto::greater<>`]]
- [[`proto::less_equal<>`]]
- [[`proto::greater_equal<>`]]
- [[`proto::equal_to<>`]]
- [[`proto::not_equal_to<>`]]
- [[`proto::logical_or<>`]]
- [[`proto::logical_and<>`]]
- [[`proto::bitwise_and<>`]]
- [[`proto::bitwise_or<>`]]
- [[`proto::bitwise_xor<>`]]
- [[`proto::comma<>`]]
- [[`proto::mem_ptr<>`]]
- [[`proto::assign<>`]]
- [[`proto::shift_left_assign<>`]]
- [[`proto::shift_right_assign<>`]]
- [[`proto::multiplies_assign<>`]]
- [[`proto::divides_assign<>`]]
- [[`proto::modulus_assign<>`]]
- [[`proto::plus_assign<>`]]
- [[`proto::minus_assign<>`]]
- [[`proto::bitwise_and_assign<>`]]
- [[`proto::bitwise_or_assign<>`]]
- [[`proto::bitwise_xor_assign<>`]]
- [[`proto::subscript<>`]]
- [[`proto::if_else_<>`]]
- [[`proto::function<>`]]
- [[`proto::unary_expr<>`]]
- [[`proto::binary_expr<>`]]
- [[`proto::nary_expr<>`]]
-]
-
-[/=====================================================]
-[heading The Many Roles of Proto Operator Metafunctions]
-[/=====================================================]
-
-We've seen templates such as _terminal_, _plus_ and _nary_expr_ fill many roles. They are metafunction that generate expression types. They are grammars that match expression types. And they are primitive transforms. The following code samples show examples of each.
-
-[*As Metafunctions ...]
-
- // proto::terminal<> and proto::plus<> are metafunctions
- // that generate expression types:
- typedef proto::terminal<int>::type int_;
- typedef proto::plus<int_, int_>::type plus_;
-
- int_ i = {42}, j = {24};
- plus_ p = {i, j};
-
-[*As Grammars ...]
-
- // proto::terminal<> and proto::plus<> are grammars that
- // match expression types
- struct Int : proto::terminal<int> {};
- struct Plus : proto::plus<Int, Int> {};
-
- BOOST_MPL_ASSERT(( proto::matches< int_, Int > ));
- BOOST_MPL_ASSERT(( proto::matches< plus_, Plus > ));
-
-[*As Primitive Transforms ...]
-
- // A transform that removes all unary_plus nodes in an expression
- struct RemoveUnaryPlus
- : proto::or_<
- proto::when<
- proto::unary_plus<RemoveUnaryPlus>
- , RemoveUnaryPlus(proto::_child)
- >
- // Use proto::terminal<> and proto::nary_expr<>
- // both as grammars and as primitive transforms.
- , proto::terminal<_>
- , proto::nary_expr<_, proto::vararg<RemoveUnaryPlus> >
- >
- {};
-
- int main()
- {
- proto::literal<int> i(0);
-
- proto::display_expr(
- +i - +(i - +i)
- );
-
- proto::display_expr(
- RemoveUnaryPlus()( +i - +(i - +i) )
- );
- }
-
-The above code displays the following, which shows that unary plus nodes have been stripped from the expression:
-
-[pre
-minus(
- unary_plus(
- terminal(0)
- )
- , unary_plus(
- minus(
- terminal(0)
- , unary_plus(
- terminal(0)
- )
- )
- )
-)
-minus(
- terminal(0)
- , minus(
- terminal(0)
- , terminal(0)
- )
-)
-]
-
-[endsect]
-
-[/======================================================]
-[section:primitives Building Custom Primitive Transforms]
-[/======================================================]
-
-In previous sections, we've seen how to compose larger transforms out of smaller transforms using function types. The smaller transforms from which larger transforms are composed are /primitive transforms/, and Proto provides a bunch of common ones such as `_child0` and `_value`. In this section we'll see how to author your own primitive transforms.
-
-[note There are a few reasons why you might want to write your own primitive transforms. For instance, your transform may be complicated, and composing it out of primitives becomes unwieldy. You might also need to work around compiler bugs on legacy compilers that makes composing transforms using function types problematic. Finally, you might also decide to define your own primitive transforms to improve compile times. Since Proto can simply invoke a primitive transform directly without having to process arguments or differentiate callable transforms from object transforms, primitive transforms are more efficient.]
-
-Primitive transforms inherit from `proto::transform<>` and have a nested `impl<>` template that inherits from `proto::transform_impl<>`. For example, this is how Proto defines the `_child_c<_N_>` transform, which returns the _N_-th child of the current expression:
-
- namespace boost { namespace proto
- {
- // A primitive transform that returns N-th child
- // of the current expression.
- template<int N>
- struct _child_c : transform<_child_c<N> >
- {
- template<typename Expr, typename State, typename Data>
- struct impl : transform_impl<Expr, State, Data>
- {
- typedef
- typename result_of::child_c<Expr, N>::type
- result_type;
-
- result_type operator ()(
- typename impl::expr_param expr
- , typename impl::state_param state
- , typename impl::data_param data
- ) const
- {
- return proto::child_c<N>(expr);
- }
- };
- };
-
- // Note that _child_c<N> is callable, so that
- // it can be used in callable transforms, as:
- // _child_c<0>(_child_c<1>)
- template<int N>
- struct is_callable<_child_c<N> >
- : mpl::true_
- {};
- }}
-
-The `proto::transform<>` base class provides the `operator()` overloads and the nested `result<>` template that make your transform a valid function object. These are implemented in terms of the nested `impl<>` template you define.
-
-The `proto::transform_impl<>` base class is a convenience. It provides some nested typedefs that are generally useful. The are specified in the table below:
-
-[table proto::transform_impl<Expr, State, Data> typedefs
-[[typedef][Equivalent To]]
-[[`expr`][`typename remove_reference<Expr>::type`]]
-[[`state`][`typename remove_reference<State>::type`]]
-[[`data`][`typename remove_reference<Data>::type`]]
-[[`expr_param`][`typename add_reference<typename add_const<Expr>::type>::type`]]
-[[`state_param`][`typename add_reference<typename add_const<State>::type>::type`]]
-[[`data_param`][`typename add_reference<typename add_const<Data>::type>::type`]]
-]
-
-You'll notice that `_child_c::impl::operator()` takes arguments of types `expr_param`, `state_param`, and `data_param`. The typedefs make it easy to accept arguments by reference or const reference accordingly.
-
-The only other interesting bit is the `is_callable<>` specialization, which will be described in the [link boost_proto.users_guide.expression_transformation.is_callable next section].
-
-[endsect]
-
-[/=================================================]
-[section:is_callable Making Your Transform Callable]
-[/=================================================]
-
-Transforms are typically of the form `proto::when< Something, R(A0,A1,...) >`. The question is whether `R` represents a function to call or an object to construct, and the answer determines how _when_ evaluates the transform. _when_ uses the `proto::is_callable<>` trait to disambiguate between the two. Proto does its best to guess whether a type is callable or not, but it doesn't always get it right. It's best to know the rules Proto uses, so that you know when you need to be more explicit.
-
-For most types `R`, `proto::is_callable<R>` checks for inheritence from `proto::callable`. However, if the type `R` is a template specialization, Proto assumes that it is /not/ callable ['even if the template inherits from `proto::callable`]. We'll see why in a minute. Consider the following erroneous callable object:
-
- // Proto can't tell this defines something callable!
- template<typename T>
- struct times2 : proto::callable
- {
- typedef T result_type;
-
- T operator()(T i) const
- {
- return i * 2;
- }
- };
-
- // ERROR! This is not going to multiply the int by 2:
- struct IntTimes2
- : proto::when<
- proto::terminal<int>
- , times2<int>(proto::_value)
- >
- {};
-
-The problem is that Proto doesn't know that `times2<int>` is callable, so rather that invoking the `times2<int>` function object, Proto will try to construct a `times2<int>` object and initialize it will an `int`. That will not compile.
-
-[note Why can't Proto tell that `times2<int>` is callable? After all, it inherits from `proto::callable`, and that is detectable, right? The problem is that merely asking whether some type `X<Y>` inherits from `callable` will cause the template `X<Y>` to be instantiated. That's a problem for a type like `std::vector<_value(_child1)>`. `std::vector<>` will not suffer to be instantiated with `_value(_child1)` as a template parameter. Since merely asking the question will sometimes result in a hard error, Proto can't ask; it has to assume that `X<Y>` represents an object to construct and not a function to call.]
-
-There are a couple of solutions to the `times2<int>` problem. One solution is to wrap the transform in `proto::call<>`. This forces Proto to treat `times2<int>` as callable:
-
- // OK, calls times2<int>
- struct IntTimes2
- : proto::when<
- proto::terminal<int>
- , proto::call<times2<int>(proto::_value)>
- >
- {};
-
-This can be a bit of a pain, because we need to wrap every use of `times2<int>`, which can be tedious and error prone, and makes our grammar cluttered and harder to read.
-
-Another solution is to specialize `proto::is_callable<>` on our `times2<>` template:
-
- namespace boost { namespace proto
- {
- // Tell Proto that times2<> is callable
- template<typename T>
- struct is_callable<times2<T> >
- : mpl::true_
- {};
- }}
-
- // OK, times2<> is callable
- struct IntTimes2
- : proto::when<
- proto::terminal<int>
- , times2<int>(proto::_value)
- >
- {};
-
-This is better, but still a pain because of the need to open Proto's namespace.
-
-You could simply make sure that the callable type is not a template specialization. Consider the following:
-
- // No longer a template specialization!
- struct times2int : times2<int> {};
-
- // OK, times2int is callable
- struct IntTimes2
- : proto::when<
- proto::terminal<int>
- , times2int(proto::_value)
- >
- {};
-
-This works because now Proto can tell that `times2int` inherits (indirectly) from `proto::callable`. Any non-template types can be safely checked for inheritance because, as they are not templates, there is no worry about instantiation errors.
-
-There is one last way to tell Proto that `times2<>` is callable. You could add an extra dummy template parameter that defaults to `proto::callable`:
-
- // Proto will recognize this as callable
- template<typename T, typename Callable = proto::callable>
- struct times2 : proto::callable
- {
- typedef T result_type;
-
- T operator()(T i) const
- {
- return i * 2;
- }
- };
-
- // OK, this works!
- struct IntTimes2
- : proto::when<
- proto::terminal<int>
- , times2<int>(proto::_value)
- >
- {};
-
-Note that in addition to the extra template parameter, `times2<>` still inherits from `proto::callable`. That's not necessary in this example but it's good style because any types derived from `times2<>` (as `times2int` defined above) will still be considered callable.
-
-[endsect]
-
-[endsect]
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk