OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [vendor/] [googletest/] [googletest/] [docs/] [PumpManual.md] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
 
2
 
3
Pump is Useful for Meta Programming.
4
 
5
# The Problem #
6
 
7
Template and macro libraries often need to define many classes,
8
functions, or macros that vary only (or almost only) in the number of
9
arguments they take. It's a lot of repetitive, mechanical, and
10
error-prone work.
11
 
12
Variadic templates and variadic macros can alleviate the problem.
13
However, while both are being considered by the C++ committee, neither
14
is in the standard yet or widely supported by compilers.  Thus they
15
are often not a good choice, especially when your code needs to be
16
portable. And their capabilities are still limited.
17
 
18
As a result, authors of such libraries often have to write scripts to
19
generate their implementation. However, our experience is that it's
20
tedious to write such scripts, which tend to reflect the structure of
21
the generated code poorly and are often hard to read and edit. For
22
example, a small change needed in the generated code may require some
23
non-intuitive, non-trivial changes in the script. This is especially
24
painful when experimenting with the code.
25
 
26
# Our Solution #
27
 
28
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
29
Programming, or Practical Utility for Meta Programming, whichever you
30
prefer) is a simple meta-programming tool for C++. The idea is that a
31
programmer writes a `foo.pump` file which contains C++ code plus meta
32
code that manipulates the C++ code. The meta code can handle
33
iterations over a range, nested iterations, local meta variable
34
definitions, simple arithmetic, and conditional expressions. You can
35
view it as a small Domain-Specific Language. The meta language is
36
designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
37
for example) and concise, making Pump code intuitive and easy to
38
maintain.
39
 
40
## Highlights ##
41
 
42
  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
43
  * Pump tries to be smart with respect to [Google's style guide](http://code.google.com/p/google-styleguide/): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
44
  * The format is human-readable and more concise than XML.
45
  * The format works relatively well with Emacs' C++ mode.
46
 
47
## Examples ##
48
 
49
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
50
 
51
```
52
$var n = 3     $$ Defines a meta variable n.
53
$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
54
$for i [[
55
               $$ Meta loop.
56
// Foo$i does blah for $i-ary predicates.
57
$range j 1..i
58
template 
59
class Foo$i {
60
$if i == 0 [[
61
  blah a;
62
]] $elif i <= 2 [[
63
  blah b;
64
]] $else [[
65
  blah c;
66
]]
67
};
68
 
69
]]
70
```
71
 
72
will be translated by the Pump compiler to:
73
 
74
```
75
// Foo0 does blah for 0-ary predicates.
76
template 
77
class Foo0 {
78
  blah a;
79
};
80
 
81
// Foo1 does blah for 1-ary predicates.
82
template 
83
class Foo1 {
84
  blah b;
85
};
86
 
87
// Foo2 does blah for 2-ary predicates.
88
template 
89
class Foo2 {
90
  blah b;
91
};
92
 
93
// Foo3 does blah for 3-ary predicates.
94
template 
95
class Foo3 {
96
  blah c;
97
};
98
```
99
 
100
In another example,
101
 
102
```
103
$range i 1..n
104
Func($for i + [[a$i]]);
105
$$ The text between i and [[ is the separator between iterations.
106
```
107
 
108
will generate one of the following lines (without the comments), depending on the value of `n`:
109
 
110
```
111
Func();              // If n is 0.
112
Func(a1);            // If n is 1.
113
Func(a1 + a2);       // If n is 2.
114
Func(a1 + a2 + a3);  // If n is 3.
115
// And so on...
116
```
117
 
118
## Constructs ##
119
 
120
We support the following meta programming constructs:
121
 
122
| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
123
|:----------------|:-----------------------------------------------------------------------------------------------|
124
| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
125
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
126
| `$($)`          | Generates a single `$` character.                                                              |
127
| `$id`           | Value of the named constant or iteration variable.                                             |
128
| `$(exp)`        | Value of the expression.                                                                       |
129
| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
130
| `[[ code ]]`    | Meta lexical block.                                                                            |
131
| `cpp_code`      | Raw C++ code.                                                                                  |
132
| `$$ comment`    | Meta comment.                                                                                  |
133
 
134
**Note:** To give the user some freedom in formatting the Pump source
135
code, Pump ignores a new-line character if it's right after `$for foo`
136
or next to `[[` or `]]`. Without this rule you'll often be forced to write
137
very long lines to get the desired output. Therefore sometimes you may
138
need to insert an extra new-line in such places for a new-line to show
139
up in your output.
140
 
141
## Grammar ##
142
 
143
```
144
code ::= atomic_code*
145
atomic_code ::= $var id = exp
146
    | $var id = [[ code ]]
147
    | $range id exp..exp
148
    | $for id sep [[ code ]]
149
    | $($)
150
    | $id
151
    | $(exp)
152
    | $if exp [[ code ]] else_branch
153
    | [[ code ]]
154
    | cpp_code
155
sep ::= cpp_code | empty_string
156
else_branch ::= $else [[ code ]]
157
    | $elif exp [[ code ]] else_branch
158
    | empty_string
159
exp ::= simple_expression_in_Python_syntax
160
```
161
 
162
## Code ##
163
 
164
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still
165
very unpolished and lacks automated tests, although it has been
166
successfully used many times. If you find a chance to use it in your
167
project, please let us know what you think!  We also welcome help on
168
improving Pump.
169
 
170
## Real Examples ##
171
 
172
You can find real-world applications of Pump in [Google Test](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgoogletest\.googlecode\.com) and [Google Mock](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgooglemock\.googlecode\.com).  The source file `foo.h.pump` generates `foo.h`.
173
 
174
## Tips ##
175
 
176
  * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
177
  * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.