diff --git a/doc/back_end.qbk b/doc/back_end.qbk index e8b466c..8d481ef 100644 --- a/doc/back_end.qbk +++ b/doc/back_end.qbk @@ -10,7 +10,23 @@ Making Expression Templates Do Useful Work] [/================================================================================] -[section:expression_evaluation Expression Evaluation: Imparting Behaviors With A Context] +Now that you've written the front end for your DSEL compiler, and you've learned a bit about the intermediate form it produces, it's time to think about what to /do/ with the intermediate form. This is where you put your domain-specific algorithms and optimizations. Proto gives you two ways to evaluate and manipulate expression templates: contexts and transforms. + +* A /context/ is like a function object that you pass along with an expression to + the _eval_ function. It associates behaviors with node types. _eval_ walks the + expression and invokes your context at each node. +* A /transform/ is a way to associate behaviors, not with node types in an + expression, but with rules in a Proto grammar. In this way, they are like + semantic actions in other compiler-construction toolkits. + +Two ways to evaluate expressions! How to choose? Contexts are a bit simpler to understand and to debug, since they are largely procedural, so contexts are a good place to start. But although transforms are more advanced, they are also more powerful; since they are associated with rules in your grammar, you can select the proper transform based on the entire /structure/ of a sub-expression rather than simply on the type of its top-most node. + +Also, transforms have a concise and declarative syntax that can be confusing at first, but highly expressive and fungible once you become accustomed to it. And -- this is admittedly very subjective -- the author finds programming with Proto transforms to be an inordinate amount of /fun!/ Your mileage may vary. + +[/================================================================================] +[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 @@ -28,7 +44,7 @@ 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()]] +[section:proto_eval Evaluating an Expression with [^proto::eval()]] [/================================================================] [:[*Synopsis:]] @@ -119,7 +135,7 @@ how to implement a context class from scratch. 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. +a context class. This section shows how to implement one from scratch. All context classes have roughly the following form: @@ -161,7 +177,7 @@ 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, + // The calculator_context from the "Hello Calculator" section, // implemented from scratch. struct calculator_context { @@ -236,9 +252,9 @@ to ease the job of implementing context classes. [endsect] -[/======================================] -[section:canned_contexts Canned Contexts] -[/======================================] +[/================================================] +[section:canned_contexts Proto's Built-In 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: @@ -397,7 +413,7 @@ might define an evaluation context as follows: struct increment_ints { - // By default, just evaluate all children by defering + // By default, just evaluate all children by delegating // to the null_eval<> template::type> struct eval @@ -624,7 +640,7 @@ Proto grammars are valid TR1-style function objects. That means you can use `boo [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. +Most grammars are a little more complicated than the one in the preceding 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. @@ -667,7 +683,7 @@ The next section describes this grammar further. [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: +In the grammar defined in the preceding section, the transform associated with non-terminals is a little strange-looking: proto::when< _ @@ -761,7 +777,7 @@ Although this works, it's not ideal because it doesn't warn users if they supply 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. +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 arity of an expression equals the actual number of arguments supplied. Computing the arity 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. @@ -875,7 +891,7 @@ The point of this exercise was to show that we can write a fairly simple Proto g 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. +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 heterogeneous 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. @@ -962,25 +978,25 @@ Now that we have defined the `FoldToList` function object, we can use it to turn // 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. +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 stretch your brain so far to do such basic things. [endsect] [/================================================] -[section:data Passing Auxiliary Data To Transforms] +[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.] +[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 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. +Expression templates are often used as an optimization to eliminate temporary objects. Consider 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: +We would like to concatenate this string into a statically allocated wide character buffer, widening each character 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. @@ -1102,7 +1118,7 @@ Let's use the above example to illustrate some other niceties of Proto transform , 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: +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 written more simply as: StringCopy( proto::_right @@ -1141,9 +1157,9 @@ Once you know that primitive transforms will always receive all three parameters [endsect] -[/===========================================] -[section:built_in Proto's Built-In Transforms] -[/===========================================] +[/====================================================] +[section:canned_transforms Proto's Built-In Transforms] +[/====================================================] [def _N_ [~N]] [def _G_ [~G]] @@ -1196,7 +1212,7 @@ Primitive transforms are the building blocks for more interesting composite tran [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 + evaluates `_FT_` for each element in the sequence to generate the next state from the previous.]] [[_reverse_fold_pt_] [Like _fold_pt_, except the elements in the Fusion sequence are iterated in @@ -1226,7 +1242,7 @@ In addition to the above primitive transforms, all of Proto's grammar elements a [variablelist [[_wild_] - [Returns the current expression unmodified.]] + [Return 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.]] @@ -1234,13 +1250,16 @@ In addition to the above primitive transforms, all of Proto's grammar elements a [For the given set of sub-grammars, take the /last/ sub-grammar and apply its associated transform.]] [[_not_] - [Returns the current expression unmodified.]] + [Return 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.]] + [[_switch_] + [As with _or_, find the sub-grammar that matches the given expression and + apply its associated transform.]] [[_terminal_] - [Returns the current terminal expression unmodified.]] + [Return 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 @@ -1399,7 +1418,7 @@ minus( 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.] +[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 make 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: @@ -1439,7 +1458,7 @@ Primitive transforms inherit from `proto::transform<>` and have a nested `impl<> 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: +The `proto::transform_impl<>` base class is a convenience. It provides some nested typedefs that are generally useful. They are specified in the table below: [table proto::transform_impl typedefs [[typedef][Equivalent To]] @@ -1463,7 +1482,7 @@ The only other interesting bit is the `is_callable<>` specialization, which will 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` 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: +For most types `R`, `proto::is_callable` checks for inheritance 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 @@ -1559,7 +1578,7 @@ There is one last way to tell Proto that `times2<>` is callable. You could add a > {}; -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. +Note that in addition to the extra template parameter, `times2<>` still inherits from `proto::callable`. That's not necessary in this example but it is good style because any types derived from `times2<>` (as `times2int` defined above) will still be considered callable. [endsect] diff --git a/doc/calculator.qbk b/doc/calculator.qbk index 7df901e..d5cd1f6 100644 --- a/doc/calculator.qbk +++ b/doc/calculator.qbk @@ -76,7 +76,7 @@ The following example should make it clear. It is explained below. std::vector args; // Define the result type of the calculator. - // (This makes the the calculator_context "callable".) + // (This makes the calculator_context "callable".) typedef double result_type; // Handle the placeholders: @@ -235,7 +235,7 @@ Once you have defined the grammar of your DSEL, you can use the _matches_ metafu 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. + // evaluate actually conforms to the calculator grammar. BOOST_MPL_ASSERT((proto::matches)); /* ... */ } @@ -256,7 +256,7 @@ just `#include `.] Grammars and `proto::matches<>` make it possible to detect when a user has created an invalid expression and issue a compile-time error. But what if you want to -prevent users from creating invlid expressions in the first place? By using +prevent users from creating invalid expressions in the first place? By using grammars and domains together, you can disable any of Proto's operator overloads that would create an invalid expression. It is as simple as specifying the DSEL's grammar when you define the domain, as shown below: diff --git a/doc/examples.qbk b/doc/examples.qbk index f42364c..798d70b 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -25,24 +25,22 @@ A code example is worth a thousand words ... -[/=================================================================================] -[section:hello_world Hello World: Building An Expression Template and Evaluating It] -[/=================================================================================] +[/================================================================================] +[section:hello_world Hello World: + Building an Expression Template and Evaluating It] +[/================================================================================] -A trivial example which builds and expression template -and evaluates it. +A trivial example which builds and expression template and evaluates it. [HelloWorld] [endsect] [/==================================================] -[section:calc1 Calc1: Defining An Evaluation Context] +[section:calc1 Calc1: Defining an Evaluation Context] [/==================================================] -A simple example which builds a miniature domain-specific -embedded language for lazy arithmetic expressions, with -TR1 bind-style argument placeholders. +A simple example that builds a miniature domain-specific embedded language for lazy arithmetic expressions, with TR1 bind-style argument placeholders. [Calc1] @@ -52,21 +50,17 @@ TR1 bind-style argument placeholders. [section:calc2 Calc2: Adding Members Using [^proto::extends<>]] [/============================================================] -An extension of the Calc1 example that uses _extends_ to -make calculator expressions valid function objects that -can be used with STL algorithms. +An extension of the Calc1 example that uses _extends_ to make calculator expressions valid function objects that can be used with STL algorithms. [Calc2] [endsect] [/===============================================] -[section:calc3 Calc3: Defining A Simple Transform] +[section:calc3 Calc3: Defining a Simple Transform] [/===============================================] -An extension of the Calc2 example that uses a Proto transform -to calculate the arity of a calculator expression and statically -assert that the correct number of argument are passed. +An extension of the Calc2 example that uses a Proto transform to calculate the arity of a calculator expression and statically assert that the correct number of arguments are passed. [Calc3] @@ -76,26 +70,19 @@ assert that the correct number of argument are passed. [section:lazy_vector Lazy Vector: Controlling Operator Overloads] [/==============================================================] -This example constructs a mini-library for linear algebra, using -expression templates to eliminate the need for temporaries when -adding vectors of numbers. +This example constructs a mini-library for linear algebra, using expression templates to eliminate the need for temporaries when adding vectors of numbers. -This example uses a domain with a grammar to prune the set -of overloaded operators. Only those operators that produce -valid lazy vector expressions are allowed. +This example uses a domain with a grammar to prune the set of overloaded operators. Only those operators that produce valid lazy vector expressions are allowed. [LazyVector] [endsect] [/========================================================] -[section:rgb RGB: Type Manipulations With Proto Transforms] +[section:rgb RGB: Type Manipulations with Proto Transforms] [/========================================================] -This is a simple example of doing arbitrary type manipulations with Proto -transforms. It takes some expression involving primiary colors and combines -the colors according to arbitrary rules. It is a port of the RGB example -from _PETE_. +This is a simple example of doing arbitrary type manipulations with Proto transforms. It takes some expression involving primary colors and combines the colors according to arbitrary rules. It is a port of the RGB example from _PETE_. [RGB] @@ -105,35 +92,27 @@ from _PETE_. [section:tarray TArray: A Simple Linear Algebra Library] [/=====================================================] -This example constructs a mini-library for linear algebra, using -expression templates to eliminate the need for temporaries when -adding arrays of numbers. It duplicates the TArray example from -_PETE_. +This example constructs a mini-library for linear algebra, using expression templates to eliminate the need for temporaries when adding arrays of numbers. It duplicates the TArray example from _PETE_. [TArray] [endsect] [/========================================================] -[section:vec3 Vec3: Computing With Transforms And Contexts] +[section:vec3 Vec3: Computing With Transforms and Contexts] [/========================================================] -This is a simple example using `proto::extends<>` to extend a terminal type -with additional behaviors, and using custom contexts and `proto::eval()` for -evaluating expressions. It is a port of the Vec3 example from -_PETE_. +This is a simple example using `proto::extends<>` to extend a terminal type with additional behaviors, and using custom contexts and `proto::eval()` for evaluating expressions. It is a port of the Vec3 example from _PETE_. [Vec3] [endsect] [/========================================================] -[section:vector Vector: Adapting A Non-Proto Terminal Type] +[section:vector Vector: Adapting a Non-Proto Terminal Type] [/========================================================] -This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Proto-ify -expressions using `std::vector<>`, a non-Proto type. It is a port of the -Vector example from _PETE_. +This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Protofy expressions using `std::vector<>`, a non-Proto type. It is a port of the Vector example from _PETE_. [Vector] @@ -143,9 +122,7 @@ Vector example from _PETE_. [section:mixed Mixed: Adapting Several Non-Proto Terminal Types] [/=============================================================] -This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Proto-ify -expressions using `std::vector<>` and `std::list<>`, non-Proto types. It is a -port of the Mixed example from _PETE_. +This is an example of using `BOOST_PROTO_DEFINE_OPERATORS()` to Protofy expressions using `std::vector<>` and `std::list<>`, non-Proto types. It is a port of the Mixed example from _PETE_. [Mixed] @@ -155,10 +132,7 @@ port of the Mixed example from _PETE_. [section:map_assign Map Assign: An Intermediate Transform] [/=======================================================] -A demonstration of how to implement `map_list_of()` from the Boost.Assign -library using Proto. `map_list_assign()` is used to conveniently initialize a -`std::map<>`. By using Proto, we can avoid any dynamic allocation while -building the intermediate representation. +A demonstration of how to implement `map_list_of()` from the Boost.Assign library using Proto. `map_list_assign()` is used to conveniently initialize a `std::map<>`. By using Proto, we can avoid any dynamic allocation while building the intermediate representation. [MapAssign] @@ -168,10 +142,7 @@ building the intermediate representation. [section:future_group Future Group: A More Advanced Transform] [/===========================================================] -An advanced example of a Proto transform that implements -Howard Hinnant's design for /future groups/ that block -for all or some asynchronous operations to complete and -returns their results in a tuple of the appropriate type. +An advanced example of a Proto transform that implements Howard Hinnant's design for /future groups/ that block for all or some asynchronous operations to complete and returns their results in a tuple of the appropriate type. [FutureGroup] @@ -181,9 +152,7 @@ returns their results in a tuple of the appropriate type. [section:lambda Lambda: A Simple Lambda Library with Proto] [/========================================================] -This is an advanced example that shows how to implement a simple -lambda DSEL with Proto, like the Boost.Lambda_library. It uses -contexts, transforms and expression extension. +This is an advanced example that shows how to implement a simple lambda DSEL with Proto, like the Boost.Lambda_library. It uses contexts, transforms and expression extension. [Lambda] diff --git a/doc/front_end.qbk b/doc/front_end.qbk index 2136351..a9d219b 100644 --- a/doc/front_end.qbk +++ b/doc/front_end.qbk @@ -32,7 +32,7 @@ Defining terminals -- with aggregate initialization -- can be a little awkward a proto::literal i = 0; // Proto literals are really just Proto terminal expressions. - // For example, this build a Proto expression template: + // For example, this builds 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: @@ -70,7 +70,7 @@ Proto also overloads `operator=`, `operator[]`, and `operator()`, but these oper _1(8,9); // OK, builds a ternary function tree node // ... etc. -For the first two lines, assigment and subscript, it should be fairly unsurprising +For the first two lines, assignment 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 @@ -117,7 +117,7 @@ code works and does what you might expect, but not in the obvious way: [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. +If we limited 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. @@ -150,7 +150,7 @@ That may look strange at first. It creates an integer terminal with _lit_, and t [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. +Now, what if we wanted to add a `pow()` function to our calculator DSEL that users could invoke as follows? // A calculator expression that takes one argument // and raises it to the 2nd power @@ -197,7 +197,7 @@ In the code above, notice how the `proto::function<>` and _terminal_ metafunctio [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. +With the above definition of the `pow()` function, we can create calculator expressions like the one below and evaluate them using the `calculator_context` we implemented in the Introduction. // Initialize a calculator context calculator_context ctx; @@ -256,7 +256,7 @@ Notice how we use the `proto::result_of::as_child<>` metafunction to calculate t [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. +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 handles 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) @@ -283,7 +283,7 @@ In the function body is the runtime invocation of _make_expr_. It closely mirror [endsect] [/==============================================] -[section Adding Members By Extending Expressions] +[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. @@ -397,7 +397,7 @@ With the new `calculator<>` type, we can redefine our placeholders to be statica 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. +We need to make one additional small change to accommodate 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: @@ -424,7 +424,7 @@ What does `BOOST_PROTO_EXTENDS()` do? It defines a data member of expression typ } }; -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. +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<>` template 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. @@ -442,11 +442,11 @@ In summary, here are the macros you can use to define expression extensions, and )``] [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()`.]] + [Defines `operator=`. Only valid when preceded by `BOOST_PROTO_BASIC_EXTENDS()`.]] [[`BOOST_PROTO_EXTENDS_SUBSCRIPT()`] - [Defines `operator[]`. Only valid when preceeded by `BOOST_PROTO_BASIC_EXTENDS()`.]] + [Defines `operator[]`. Only valid when preceded 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()`.]] + [Defines `operator()` and a nested `result<>` template for return type calculation. Only valid when preceded by `BOOST_PROTO_BASIC_EXTENDS()`.]] [[``BOOST_PROTO_EXTENDS( __expression__ , __extension__ @@ -476,7 +476,7 @@ The last thing that remains to be done is to tell Proto that it needs to wrap al 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 we used `BOOST_PROTO_EXTENDS()` to keep our expression extension type POD, then we need to use `proto::pod_generator<>` instead of `proto::generator<>`, as follows: // If calculator<> uses BOOST_PROTO_EXTENDS() instead of // use proto::extends<>, use proto::pod_generator<> instead diff --git a/doc/glossary.qbk b/doc/glossary.qbk index 6c08de1..997e4e2 100644 --- a/doc/glossary.qbk +++ b/doc/glossary.qbk @@ -36,8 +36,8 @@ never created. Domains are empty structs that inherit from `proto::domain<>`.]] [ [ [anchor dsel] domain-specific embedded language] - [A domain-specific language implemented as a library. The langauge in which - the library is written is called the "host" langauge, and the language + [A domain-specific language implemented as a library. The language in which + the library is written is called the "host" language, and the language implemented by the library is called the "embedded" language.]] [ [ [anchor dsl] domain-specific language] [A programming language that targets a particular problem space by providing @@ -72,7 +72,7 @@ object to construct and the arguments are treated as transforms that yield the parameters to the constructor.]] [ [ [anchor polymorphic_function_object] polymorphic function object] - [An instance of a class type with an overloaded function call operator and an + [An instance of a class type with an overloaded function call operator and a nested `result_type` typedef or `result<>` template for calculating the return type of the function call operator.]] [ [ [anchor primitive_transform] primitive transform] diff --git a/doc/intermediate_form.qbk b/doc/intermediate_form.qbk index 56539b7..79ce00f 100644 --- a/doc/intermediate_form.qbk +++ b/doc/intermediate_form.qbk @@ -72,7 +72,7 @@ The _expr_ struct is defined as follows: 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 +initialized with the initializer `{{}}`. The outer braces are 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. @@ -248,7 +248,7 @@ the behavior of the `child_c<>` metafunction. 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 +and _left_ are synonymous with `child_c<0>()`, and _right_ is synonymous with `child_c<1>()`. Another very common operation is accessing the value stored within a Proto @@ -267,7 +267,7 @@ 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 +sequences are 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. @@ -296,7 +296,7 @@ Fusion to print the function arguments in order. 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 +`proto::functional::value()` creates a function object that is equivalent to the `proto::value()` function. The above invocation of `fusion::for_each()` displays the following: @@ -561,7 +561,7 @@ sections, all the really interesting things you can do with Proto begin right here. [/===============================================] -[section:patterns Finding Patterns In Expressions] +[section:patterns Finding Patterns in Expressions] [/===============================================] Imagine your DSEL is a miniature I/O facility, with iostream operations @@ -580,7 +580,7 @@ First, let's define some terminals we can use in our lazy I/O expressions: 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 +that we can execute later. To define grammars that match input and output expressions of the form `cin_ >> i` and `cout_ << 1` we do this: struct Input @@ -713,7 +713,7 @@ 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` will only match an `int &`. It will not match an `int` -or a `int const &`. +or an `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 @@ -741,7 +741,7 @@ 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::type`. That's a terminal containing a -a 6-element character array. Naturally, you can match this terminal +6-element character array. Naturally, you can match this terminal with the grammar `proto::terminal`, but the grammar `proto::terminal` will match it as well, as the following code fragment illustrates. @@ -834,7 +834,7 @@ 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_` you +The _if_ template has a couple of variants. In addition to `if_` you can also say `if_` and `if_`. These let you select one sub-grammar or another based on the `Condition`. @@ -849,7 +849,7 @@ When your Proto grammar gets large, you'll start to run into some scalability pr 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 + // Here is a big, inefficient grammar struct ABigGrammar : proto::or_< proto::terminal @@ -1076,7 +1076,7 @@ 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 +literals, addition, subtraction, multiplication, 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: diff --git a/doc/preface.qbk b/doc/preface.qbk index a74e64f..6660b09 100644 --- a/doc/preface.qbk +++ b/doc/preface.qbk @@ -30,7 +30,7 @@ Expression Templates are an advanced technique that C++ library developers use t In short, Proto is a DSEL for defining DSELs. [/====================================] -[heading How To Use This Documentation] +[heading How to Use This Documentation] [/====================================] This documentation makes use of the following naming and formatting conventions. diff --git a/doc/resources.qbk b/doc/resources.qbk index 3d3f532..ba81759 100644 --- a/doc/resources.qbk +++ b/doc/resources.qbk @@ -16,7 +16,7 @@ redesigned and improved Spirit-2 and the related Karma library. As a result of these efforts, Proto evolved into a generic and abstract grammar and tree transformation framework applicable in a wide variety of DSEL scenarios. -The grammar and tree transformation framework is modelled on Spirit's grammar and +The grammar and tree transformation framework is modeled on Spirit's grammar and semantic action framework. The expression tree data structure is similar to Fusion data structures in many respects, and is interoperable with Fusion's iterators and algorithms. diff --git a/example/calc2.cpp b/example/calc2.cpp index dcac958..10b0396 100644 --- a/example/calc2.cpp +++ b/example/calc2.cpp @@ -4,8 +4,8 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // This example enhances the simple arithmetic expression evaluator -// in calc1.cpp by using proto::extends to make arithemetic -// expressions immediately evaluatable with operator (), a-la a +// in calc1.cpp by using proto::extends to make arithmetic +// expressions immediately evaluable with operator (), a-la a // function object #include diff --git a/example/map_assign.cpp b/example/map_assign.cpp index b85999c..f5a2f71 100644 --- a/example/map_assign.cpp +++ b/example/map_assign.cpp @@ -40,7 +40,7 @@ struct insert } }; -// The grammmar for valid map-list expressions, and a +// The grammar for valid map-list expressions, and a // transform that populates the map. struct MapListOf : proto::or_< diff --git a/example/mixed.cpp b/example/mixed.cpp index 140b977..6765a67 100644 --- a/example/mixed.cpp +++ b/example/mixed.cpp @@ -4,7 +4,7 @@ // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to proto-ify +// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy // expressions using std::vector<> and std::list, non-proto types. It is a port // of the Mixed example from PETE. // (http://www.codesourcery.com/pooma/download.html). diff --git a/example/rgb.cpp b/example/rgb.cpp index e48cca5..51b0f45 100644 --- a/example/rgb.cpp +++ b/example/rgb.cpp @@ -5,7 +5,7 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // This is a simple example of doing arbitrary type manipulations with proto -// transforms. It takes some expression involving primiary colors and combines +// transforms. It takes some expression involving primary colors and combines // the colors according to arbitrary rules. It is a port of the RGB example // from PETE (http://www.codesourcery.com/pooma/download.html). diff --git a/example/vector.cpp b/example/vector.cpp index cc81cc4..a2b80fe 100644 --- a/example/vector.cpp +++ b/example/vector.cpp @@ -4,7 +4,7 @@ // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to proto-ify +// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy // expressions using std::vector<>, a non-proto type. It is a port of the // Vector example from PETE (http://www.codesourcery.com/pooma/download.html).