|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r76315 - trunk/libs/proto/doc
From: eric_at_[hidden]
Date: 2012-01-05 01:10:06
Author: eric_niebler
Date: 2012-01-05 01:10:05 EST (Thu, 05 Jan 2012)
New Revision: 76315
URL: http://svn.boost.org/trac/boost/changeset/76315
Log:
doc feedback from Thomas Heller
Text files modified:
trunk/libs/proto/doc/acknowledgements.qbk | 27 +++++++++++----------------
trunk/libs/proto/doc/back_end.qbk | 12 ++++++------
trunk/libs/proto/doc/front_end.qbk | 12 +++++++++---
trunk/libs/proto/doc/proto.qbk | 4 ++++
4 files changed, 30 insertions(+), 25 deletions(-)
Modified: trunk/libs/proto/doc/acknowledgements.qbk
==============================================================================
--- trunk/libs/proto/doc/acknowledgements.qbk (original)
+++ trunk/libs/proto/doc/acknowledgements.qbk 2012-01-05 01:10:05 EST (Thu, 05 Jan 2012)
@@ -7,22 +7,17 @@
[section:acknowledgements Appendix E: Acknowledgements]
-I'd like to thank Joel de Guzman and Hartmut Kaiser for being willing to take a
-chance on using Proto for their work on Spirit-2 and Karma when Proto was
-little more than a vision. Their requirements and feedback have been
-indespensable.
-
-Thanks to Daniel James for providing a patch to remove the dependence on
-deprecated configuration macros for C++0x features.
-
-Thanks to Dave Abrahams for an especially detailed review, and for making a
-VM with msvc-7.1 available so I could track down portability issues on that
-compiler.
-
-Many thanks to Daniel Wallin who first implemented the code used to find the
-common domain among a set, accounting for super- and sub-domains. Thanks also
-to Jeremiah Willcock, John Bytheway and Krishna Achuthan who offered alternate
-solutions to this tricky programming problem.
+I'd like to thank Joel de Guzman and Hartmut Kaiser for being willing to take a chance on using Proto for their work on Spirit-2 and Karma when Proto was little more than a vision. Their requirements and feedback have been indespensable.
+
+Thanks also to Thomas Heller and again to Hartmut for their feedback and suggestions during the redesign of Phoenix. That effort yielded several valuable advanced features such as sub-domains, external transforms, and per-domain `as_child` customization.
+
+Thanks to Daniel James for providing a patch to remove the dependence on deprecated configuration macros for C++0x features.
+
+Thanks to Joel Falcou and Christophe Henry for their enthusiasm, support, feedback, and humor; and for volunteering to be Proto's co-maintainers.
+
+Thanks to Dave Abrahams for an especially detailed review, and for making a VM with msvc-7.1 available so I could track down portability issues on that compiler.
+
+Many thanks to Daniel Wallin who first implemented the code used to find the common domain among a set, accounting for super- and sub-domains. Thanks also to Jeremiah Willcock, John Bytheway and Krishna Achuthan who offered alternate solutions to this tricky programming problem.
Thanks also to the developers of _PETE_. I found many good ideas there.
Modified: trunk/libs/proto/doc/back_end.qbk
==============================================================================
--- trunk/libs/proto/doc/back_end.qbk (original)
+++ trunk/libs/proto/doc/back_end.qbk 2012-01-05 01:10:05 EST (Thu, 05 Jan 2012)
@@ -1164,9 +1164,9 @@
[note This is an advanced topic that is only necessary for people defining large EDSLs. Feel free to skip this if you're just getting started with Proto.]
-So far, we've seen examples of grammars with embedded transforms. In practice, grammars can get pretty large, and you may want to use them to drive several different computations. For instance, you may have a grammar for a linear algebra domain, and you may want to use it to compute the shape of the result (vector or matrix?) and also to compute the result optimally. You don't want to have to copy and paste the whole shebang just to tweak one of the embedded transforms. What you want instead is to define the grammar once, and specify the transforms later when you're ready to evaluate an expression. For that, you use /external transforms/.
+So far, we've seen examples of grammars with embedded transforms. In practice, grammars can get pretty large, and you may want to use them to drive several different computations. For instance, you may have a grammar for a linear algebra domain, and you may want to use it to compute the shape of the result (vector or matrix?) and also to compute the result optimally. You don't want to have to copy and paste the whole shebang just to tweak one of the embedded transforms. What you want instead is to define the grammar once, and specify the transforms later when you're ready to evaluate an expression. For that, you use /external transforms/. The pattern you'll use is this: replace one or more of the transforms in your grammar with the special placeholder _external_transform_. Then, you'll create a bundle of transforms that you will pass to the grammar in the data parameter (the 3rd parameter after the expression and state) when evaluating it.
-Let's begin this exercise by revisiting our old friend the calculator EDSL. Here is a bare-bones front end that defines a domain, a grammar, an expression wrapper, and some placeholder terminals.
+To illustrate external transforms, we'll build a calculator evaluator that can be configured to throw an exception on division by zero. Here is a bare-bones front end that defines a domain, a grammar, an expression wrapper, and some placeholder terminals.
#include <boost/assert.hpp>
#include <boost/mpl/int.hpp>
@@ -1248,9 +1248,9 @@
int result = calc_grammar()(_1 + _2, fusion::make_vector(3, 4));
BOOST_ASSERT(result == 7);
-Now, imagine we want an alternative evaluation strategy that checks for division by zero and throws an exception. Just how rediculous would it be to copy the entire `calc_grammar` just to change the one line that transforms division expressions?! There are a few ways to solve this problem. One would be to make `calc_grammar` a template parameterized on the division transform. Instead, let's use an external transform.
+We also want an alternative evaluation strategy that checks for division by zero and throws an exception. Just how ridiculous would it be to copy the entire `calc_grammar` just to change the one line that transforms division expressions?! External transforms are ideally suited to this problem.
-First, we give the division rule in our grammar a "name"; that is, we make it a struct. We'll use this type later to dispatch to the right transforms.
+First, we give the division rule in our grammar a "name"; that is, we make it a struct. We'll use this unique type later to dispatch to the right transforms.
struct calc_grammar;
struct divides_rule : proto::divides<calc_grammar, calc_grammar> {};
@@ -1269,9 +1269,9 @@
>
{};
-The use of `proto::external_transform` above makes the handling of division expressions externally parameterizeable.
+The use of _external_transform_ above makes the handling of division expressions externally parameterizeable.
-Next, we use `proto::external_transforms<>` (note the trailing 's') to capture our evaluation strategy in a bundle that we can pass along to the transform in the data parameter. Read on for the explanation.
+Next, we use _external_transforms_ (note the trailing 's') to capture our evaluation strategy in a bundle that we can pass along to the transform in the data parameter. Read on for the explanation.
// Evaluate division nodes as before
struct non_checked_division
Modified: trunk/libs/proto/doc/front_end.qbk
==============================================================================
--- trunk/libs/proto/doc/front_end.qbk (original)
+++ trunk/libs/proto/doc/front_end.qbk 2012-01-05 01:10:05 EST (Thu, 05 Jan 2012)
@@ -602,6 +602,8 @@
[section:per_domain_as_child Controlling How Child Expressions Are Captured]
[/=========================================================================]
+[note This is an advanced topic. Feel free to skip this if you're just getting started with Proto.]
+
Proto's operator overloads build expressions from sub-expressions. The sub-expressions become children of the new expression. By default, the children are stored in the parent by reference. This section describes how to change that default.
[/-----------------------------------------]
@@ -614,9 +616,9 @@
auto l = proto::as_expr(x); // Turn x into a Proto expression, hold the result in a local
-The above works regardless of whether `x` is already a Proto expression or not. The object `l` is guaranteed to be a valid Proto expression. If `x` is a non-Proto object, it is turned into terminal expression that hold `x` /by value/.[footnote It's not always possible to hold something by value. By default, _as_expr_ makes an exception for functions, abstract types, and iostreams (types derived from `std::ios_base`). These objects are held by reference. All others are held by value, even arrays.] If `x` is a Proto object already, _as_expr_ returns it /by value/ unmodified.
+The above works regardless of whether `x` is already a Proto expression or not. The object `l` is guaranteed to be a valid Proto expression. If `x` is a non-Proto object, it is turned into a terminal expression that holds `x` /by value/.[footnote It's not always possible to hold something by value. By default, _as_expr_ makes an exception for functions, abstract types, and iostreams (types derived from `std::ios_base`). These objects are held by reference. All others are held by value, even arrays.] If `x` is a Proto object already, _as_expr_ returns it /by value/ unmodified.
-In contrast, _as_child_ is used internally by Proto to pre-process some object before making it a child of another expression. Since it's internal to Proto, you don't see it explicitly, but it's there behind the scenes in expressions like this:
+In contrast, _as_child_ is used internally by Proto to pre-process objects before making them children of another expression. Since it's internal to Proto, you don't see it explicitly, but it's there behind the scenes in expressions like this:
x + y; // Consider that y is a Proto expression, but x may or may not be.
@@ -630,6 +632,8 @@
[[[^proto::as_child(t)]] [Return (by value) a new Proto terminal holding [^t] by reference.] [Return [^t] by reference unmodified.]]
]
+[note There is one important place where Proto uses both `as_expr` /and/ `as_child`: _make_expr_. The _make_expr_ function requires you to specify for each child whether it should be held by value or by reference. Proto uses _as_expr_ to pre-process the children to be held by value, and _as_child_ for the ones to be held by reference.]
+
Now that you know what _as_child_ and _as_expr_ are, where they are used, and what they do by default, you may decide that one or both of these functions should have different behavior for your domain. For instance, given the above description of _as_child_, the following code is always wrong:
proto::literal<int> i(0);
@@ -742,13 +746,15 @@
[section:subdomains EDSL Interoperatability: Sub-Domains]
[/======================================================]
+[note This is an advanced topic. Feel free to skip this if you're just getting started with Proto.]
+
The ability to /compose/ different EDSLs is one of their most exciting features. Consider how you build a parser using yacc. You write your grammar rules in yacc's domain-specific language. Then you embed semantic actions written in C within your grammar. Boost's Spirit parser generator gives you the same ability. You write grammar rules using Spirit.Qi and embed semantic actions using the Phoenix library. Phoenix and Spirit are both Proto-based domain-specific languages with their own distinct syntax and semantics. But you can freely embed Phoenix expressions within Spirit expressions. This section describes Proto's /sub-domain/ feature that lets you define famalies of interoperable domains.
[/======================]
[heading Dueling Domains]
[/======================]
-Sub-domains solve a specific problem that only comes up when you try to create an expression from two sub-expressions in different domains: what is the domain of the resulting expression? Consider the following code:
+When you try to create an expression from two sub-expressions in different domains, what is the domain of the resulting expression? This is the fundamental problem that is addressed by sub-domains. Consider the following code:
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
Modified: trunk/libs/proto/doc/proto.qbk
==============================================================================
--- trunk/libs/proto/doc/proto.qbk (original)
+++ trunk/libs/proto/doc/proto.qbk 2012-01-05 01:10:05 EST (Thu, 05 Jan 2012)
@@ -57,6 +57,10 @@
[classref boost::proto::default_domain `proto::default_domain`]]
[def _extends_
[classref boost::proto::extends `proto::extends<>`]]
+[def _external_transform_
+ [classref boost::proto::external_transform `proto::external_transform`]]
+[def _external_transforms_
+ [classref boost::proto::external_transforms `proto::external_transforms<>`]]
[def _as_expr_
[funcref boost::proto::as_expr `proto::as_expr()`]]
[def _as_child_
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