113481Sgiacomo.travaglini@arm.com
213481Sgiacomo.travaglini@arm.com
313481Sgiacomo.travaglini@arm.com<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
413481Sgiacomo.travaglini@arm.com
513481Sgiacomo.travaglini@arm.com# The Problem #
613481Sgiacomo.travaglini@arm.com
713481Sgiacomo.travaglini@arm.comTemplate and macro libraries often need to define many classes,
813481Sgiacomo.travaglini@arm.comfunctions, or macros that vary only (or almost only) in the number of
913481Sgiacomo.travaglini@arm.comarguments they take. It's a lot of repetitive, mechanical, and
1013481Sgiacomo.travaglini@arm.comerror-prone work.
1113481Sgiacomo.travaglini@arm.com
1213481Sgiacomo.travaglini@arm.comVariadic templates and variadic macros can alleviate the problem.
1313481Sgiacomo.travaglini@arm.comHowever, while both are being considered by the C++ committee, neither
1413481Sgiacomo.travaglini@arm.comis in the standard yet or widely supported by compilers.  Thus they
1513481Sgiacomo.travaglini@arm.comare often not a good choice, especially when your code needs to be
1613481Sgiacomo.travaglini@arm.comportable. And their capabilities are still limited.
1713481Sgiacomo.travaglini@arm.com
1813481Sgiacomo.travaglini@arm.comAs a result, authors of such libraries often have to write scripts to
1913481Sgiacomo.travaglini@arm.comgenerate their implementation. However, our experience is that it's
2013481Sgiacomo.travaglini@arm.comtedious to write such scripts, which tend to reflect the structure of
2113481Sgiacomo.travaglini@arm.comthe generated code poorly and are often hard to read and edit. For
2213481Sgiacomo.travaglini@arm.comexample, a small change needed in the generated code may require some
2313481Sgiacomo.travaglini@arm.comnon-intuitive, non-trivial changes in the script. This is especially
2413481Sgiacomo.travaglini@arm.compainful when experimenting with the code.
2513481Sgiacomo.travaglini@arm.com
2613481Sgiacomo.travaglini@arm.com# Our Solution #
2713481Sgiacomo.travaglini@arm.com
2813481Sgiacomo.travaglini@arm.comPump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
2913481Sgiacomo.travaglini@arm.comProgramming, or Practical Utility for Meta Programming, whichever you
3013481Sgiacomo.travaglini@arm.comprefer) is a simple meta-programming tool for C++. The idea is that a
3113481Sgiacomo.travaglini@arm.comprogrammer writes a `foo.pump` file which contains C++ code plus meta
3213481Sgiacomo.travaglini@arm.comcode that manipulates the C++ code. The meta code can handle
3313481Sgiacomo.travaglini@arm.comiterations over a range, nested iterations, local meta variable
3413481Sgiacomo.travaglini@arm.comdefinitions, simple arithmetic, and conditional expressions. You can
3513481Sgiacomo.travaglini@arm.comview it as a small Domain-Specific Language. The meta language is
3613481Sgiacomo.travaglini@arm.comdesigned to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
3713481Sgiacomo.travaglini@arm.comfor example) and concise, making Pump code intuitive and easy to
3813481Sgiacomo.travaglini@arm.commaintain.
3913481Sgiacomo.travaglini@arm.com
4013481Sgiacomo.travaglini@arm.com## Highlights ##
4113481Sgiacomo.travaglini@arm.com
4213481Sgiacomo.travaglini@arm.com  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
4313481Sgiacomo.travaglini@arm.com  * 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.
4413481Sgiacomo.travaglini@arm.com  * The format is human-readable and more concise than XML.
4513481Sgiacomo.travaglini@arm.com  * The format works relatively well with Emacs' C++ mode.
4613481Sgiacomo.travaglini@arm.com
4713481Sgiacomo.travaglini@arm.com## Examples ##
4813481Sgiacomo.travaglini@arm.com
4913481Sgiacomo.travaglini@arm.comThe following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
5013481Sgiacomo.travaglini@arm.com
5113481Sgiacomo.travaglini@arm.com```
5213481Sgiacomo.travaglini@arm.com$var n = 3     $$ Defines a meta variable n.
5313481Sgiacomo.travaglini@arm.com$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
5413481Sgiacomo.travaglini@arm.com$for i [[
5513481Sgiacomo.travaglini@arm.com               $$ Meta loop.
5613481Sgiacomo.travaglini@arm.com// Foo$i does blah for $i-ary predicates.
5713481Sgiacomo.travaglini@arm.com$range j 1..i
5813481Sgiacomo.travaglini@arm.comtemplate <size_t N $for j [[, typename A$j]]>
5913481Sgiacomo.travaglini@arm.comclass Foo$i {
6013481Sgiacomo.travaglini@arm.com$if i == 0 [[
6113481Sgiacomo.travaglini@arm.com  blah a;
6213481Sgiacomo.travaglini@arm.com]] $elif i <= 2 [[
6313481Sgiacomo.travaglini@arm.com  blah b;
6413481Sgiacomo.travaglini@arm.com]] $else [[
6513481Sgiacomo.travaglini@arm.com  blah c;
6613481Sgiacomo.travaglini@arm.com]]
6713481Sgiacomo.travaglini@arm.com};
6813481Sgiacomo.travaglini@arm.com
6913481Sgiacomo.travaglini@arm.com]]
7013481Sgiacomo.travaglini@arm.com```
7113481Sgiacomo.travaglini@arm.com
7213481Sgiacomo.travaglini@arm.comwill be translated by the Pump compiler to:
7313481Sgiacomo.travaglini@arm.com
7413481Sgiacomo.travaglini@arm.com```
7513481Sgiacomo.travaglini@arm.com// Foo0 does blah for 0-ary predicates.
7613481Sgiacomo.travaglini@arm.comtemplate <size_t N>
7713481Sgiacomo.travaglini@arm.comclass Foo0 {
7813481Sgiacomo.travaglini@arm.com  blah a;
7913481Sgiacomo.travaglini@arm.com};
8013481Sgiacomo.travaglini@arm.com
8113481Sgiacomo.travaglini@arm.com// Foo1 does blah for 1-ary predicates.
8213481Sgiacomo.travaglini@arm.comtemplate <size_t N, typename A1>
8313481Sgiacomo.travaglini@arm.comclass Foo1 {
8413481Sgiacomo.travaglini@arm.com  blah b;
8513481Sgiacomo.travaglini@arm.com};
8613481Sgiacomo.travaglini@arm.com
8713481Sgiacomo.travaglini@arm.com// Foo2 does blah for 2-ary predicates.
8813481Sgiacomo.travaglini@arm.comtemplate <size_t N, typename A1, typename A2>
8913481Sgiacomo.travaglini@arm.comclass Foo2 {
9013481Sgiacomo.travaglini@arm.com  blah b;
9113481Sgiacomo.travaglini@arm.com};
9213481Sgiacomo.travaglini@arm.com
9313481Sgiacomo.travaglini@arm.com// Foo3 does blah for 3-ary predicates.
9413481Sgiacomo.travaglini@arm.comtemplate <size_t N, typename A1, typename A2, typename A3>
9513481Sgiacomo.travaglini@arm.comclass Foo3 {
9613481Sgiacomo.travaglini@arm.com  blah c;
9713481Sgiacomo.travaglini@arm.com};
9813481Sgiacomo.travaglini@arm.com```
9913481Sgiacomo.travaglini@arm.com
10013481Sgiacomo.travaglini@arm.comIn another example,
10113481Sgiacomo.travaglini@arm.com
10213481Sgiacomo.travaglini@arm.com```
10313481Sgiacomo.travaglini@arm.com$range i 1..n
10413481Sgiacomo.travaglini@arm.comFunc($for i + [[a$i]]);
10513481Sgiacomo.travaglini@arm.com$$ The text between i and [[ is the separator between iterations.
10613481Sgiacomo.travaglini@arm.com```
10713481Sgiacomo.travaglini@arm.com
10813481Sgiacomo.travaglini@arm.comwill generate one of the following lines (without the comments), depending on the value of `n`:
10913481Sgiacomo.travaglini@arm.com
11013481Sgiacomo.travaglini@arm.com```
11113481Sgiacomo.travaglini@arm.comFunc();              // If n is 0.
11213481Sgiacomo.travaglini@arm.comFunc(a1);            // If n is 1.
11313481Sgiacomo.travaglini@arm.comFunc(a1 + a2);       // If n is 2.
11413481Sgiacomo.travaglini@arm.comFunc(a1 + a2 + a3);  // If n is 3.
11513481Sgiacomo.travaglini@arm.com// And so on...
11613481Sgiacomo.travaglini@arm.com```
11713481Sgiacomo.travaglini@arm.com
11813481Sgiacomo.travaglini@arm.com## Constructs ##
11913481Sgiacomo.travaglini@arm.com
12013481Sgiacomo.travaglini@arm.comWe support the following meta programming constructs:
12113481Sgiacomo.travaglini@arm.com
12213481Sgiacomo.travaglini@arm.com| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
12313481Sgiacomo.travaglini@arm.com|:----------------|:-----------------------------------------------------------------------------------------------|
12413481Sgiacomo.travaglini@arm.com| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
12513481Sgiacomo.travaglini@arm.com| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
12613481Sgiacomo.travaglini@arm.com| `$($)`          | Generates a single `$` character.                                                              |
12713481Sgiacomo.travaglini@arm.com| `$id`           | Value of the named constant or iteration variable.                                             |
12813481Sgiacomo.travaglini@arm.com| `$(exp)`        | Value of the expression.                                                                       |
12913481Sgiacomo.travaglini@arm.com| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
13013481Sgiacomo.travaglini@arm.com| `[[ code ]]`    | Meta lexical block.                                                                            |
13113481Sgiacomo.travaglini@arm.com| `cpp_code`      | Raw C++ code.                                                                                  |
13213481Sgiacomo.travaglini@arm.com| `$$ comment`    | Meta comment.                                                                                  |
13313481Sgiacomo.travaglini@arm.com
13413481Sgiacomo.travaglini@arm.com**Note:** To give the user some freedom in formatting the Pump source
13513481Sgiacomo.travaglini@arm.comcode, Pump ignores a new-line character if it's right after `$for foo`
13613481Sgiacomo.travaglini@arm.comor next to `[[` or `]]`. Without this rule you'll often be forced to write
13713481Sgiacomo.travaglini@arm.comvery long lines to get the desired output. Therefore sometimes you may
13813481Sgiacomo.travaglini@arm.comneed to insert an extra new-line in such places for a new-line to show
13913481Sgiacomo.travaglini@arm.comup in your output.
14013481Sgiacomo.travaglini@arm.com
14113481Sgiacomo.travaglini@arm.com## Grammar ##
14213481Sgiacomo.travaglini@arm.com
14313481Sgiacomo.travaglini@arm.com```
14413481Sgiacomo.travaglini@arm.comcode ::= atomic_code*
14513481Sgiacomo.travaglini@arm.comatomic_code ::= $var id = exp
14613481Sgiacomo.travaglini@arm.com    | $var id = [[ code ]]
14713481Sgiacomo.travaglini@arm.com    | $range id exp..exp
14813481Sgiacomo.travaglini@arm.com    | $for id sep [[ code ]]
14913481Sgiacomo.travaglini@arm.com    | $($)
15013481Sgiacomo.travaglini@arm.com    | $id
15113481Sgiacomo.travaglini@arm.com    | $(exp)
15213481Sgiacomo.travaglini@arm.com    | $if exp [[ code ]] else_branch
15313481Sgiacomo.travaglini@arm.com    | [[ code ]]
15413481Sgiacomo.travaglini@arm.com    | cpp_code
15513481Sgiacomo.travaglini@arm.comsep ::= cpp_code | empty_string
15613481Sgiacomo.travaglini@arm.comelse_branch ::= $else [[ code ]]
15713481Sgiacomo.travaglini@arm.com    | $elif exp [[ code ]] else_branch
15813481Sgiacomo.travaglini@arm.com    | empty_string
15913481Sgiacomo.travaglini@arm.comexp ::= simple_expression_in_Python_syntax
16013481Sgiacomo.travaglini@arm.com```
16113481Sgiacomo.travaglini@arm.com
16213481Sgiacomo.travaglini@arm.com## Code ##
16313481Sgiacomo.travaglini@arm.com
16413481Sgiacomo.travaglini@arm.comYou can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still
16513481Sgiacomo.travaglini@arm.comvery unpolished and lacks automated tests, although it has been
16613481Sgiacomo.travaglini@arm.comsuccessfully used many times. If you find a chance to use it in your
16713481Sgiacomo.travaglini@arm.comproject, please let us know what you think!  We also welcome help on
16813481Sgiacomo.travaglini@arm.comimproving Pump.
16913481Sgiacomo.travaglini@arm.com
17013481Sgiacomo.travaglini@arm.com## Real Examples ##
17113481Sgiacomo.travaglini@arm.com
17213481Sgiacomo.travaglini@arm.comYou 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`.
17313481Sgiacomo.travaglini@arm.com
17413481Sgiacomo.travaglini@arm.com## Tips ##
17513481Sgiacomo.travaglini@arm.com
17613481Sgiacomo.travaglini@arm.com  * 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.
17713481Sgiacomo.travaglini@arm.com  * 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.
178