diff options
author | Chris Baish <chris.baish@gmail.com> | 2019-07-19 06:12:46 (GMT) |
---|---|---|
committer | Chris Baish <chris.baish@gmail.com> | 2019-07-19 06:12:46 (GMT) |
commit | d64e4cf14e488f10374df7548513667e4fba6399 (patch) | |
tree | bd46a4241847510b22d81672e65fb22dbe003e53 | |
parent | adb490773e8d5f8a84e863f4bd6d96a707750093 (diff) | |
parent | b77e5c76252bac322bb82c5b444f050bd0d92451 (diff) | |
download | googletest-d64e4cf14e488f10374df7548513667e4fba6399.zip googletest-d64e4cf14e488f10374df7548513667e4fba6399.tar.gz googletest-d64e4cf14e488f10374df7548513667e4fba6399.tar.bz2 |
Merge remote-tracking branch 'upstream/master' into primer_md_table_update
-rw-r--r-- | googlemock/docs/cheat_sheet.md | 158 | ||||
-rw-r--r-- | googlemock/docs/cook_book.md | 6 | ||||
-rw-r--r-- | googlemock/docs/for_dummies.md | 4 | ||||
-rw-r--r-- | googlemock/docs/gmock_faq.md | 2 | ||||
-rw-r--r-- | googletest/README.md | 6 | ||||
-rw-r--r-- | googletest/docs/advanced.md | 4 | ||||
-rw-r--r-- | googletest/docs/faq.md | 4 | ||||
-rw-r--r-- | googletest/docs/pkgconfig.md | 53 | ||||
-rw-r--r-- | googletest/docs/primer.md | 2 | ||||
-rw-r--r-- | googletest/docs/pump_manual.md | 169 |
10 files changed, 224 insertions, 184 deletions
diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md index ea46a68..e839fa9 100644 --- a/googlemock/docs/cheat_sheet.md +++ b/googlemock/docs/cheat_sheet.md @@ -1,6 +1,6 @@ ## gMock Cheat Sheet -<!-- GOOGLETEST_CM0018 DO NOT DELETE --> +<!-- GOOGLETEST_CM0019 DO NOT DELETE --> ### Defining a Mock Class @@ -215,7 +215,7 @@ and the default action will be taken each time. ### Matchers {#MatcherList} -<!-- GOOGLETEST_CM0019 DO NOT DELETE --> +<!-- GOOGLETEST_CM0020 DO NOT DELETE --> A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value directly: @@ -340,67 +340,99 @@ or simply `expected_container` to match a container exactly. If you want to write the elements in-line, match them more flexibly, or get more informative messages, you can use: -| Matcher | Description | -| :----------------------------------- | :----------------------------------- | -| `ContainerEq(container)` | The same as `Eq(container)` except | -: : that the failure message also : -: : includes which elements are in one : -: : container but not the other. : -| `Contains(e)` | `argument` contains an element that | -: : matches `e`, which can be either a : -: : value or a matcher. : -| `Each(e)` | `argument` is a container where | -: : _every_ element matches `e`, which : -: : can be either a value or a matcher. : -| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, | -: : where the i-th element matches `ei`, : -: : which can be a value or a matcher. 0 : -: : to 10 arguments are allowed. : -| `ElementsAreArray({ e0, e1, ..., en | The same as `ElementsAre()` except | -: })`, `ElementsAreArray(array)`, or : that the expected element : -: `ElementsAreArray(array, count)` : values/matchers come from an : -: : initializer list, STL-style : -: : container, or C-style array. : -| `IsEmpty()` | `argument` is an empty container | -: : (`container.empty()`). : -| `Pointwise(m, container)` | `argument` contains the same number | -: : of elements as in `container`, and : -: : for all i, (the i-th element in : -: : `argument`, the i-th element in : -: : `container`) match `m`, which is a : -: : matcher on 2-tuples. E.g. : -: : `Pointwise(Le(), upper_bounds)` : -: : verifies that each element in : -: : `argument` doesn't exceed the : -: : corresponding element in : -: : `upper_bounds`. See more detail : -: : below. : -| `SizeIs(m)` | `argument` is a container whose size | -: : matches `m`. E.g. `SizeIs(2)` or : -: : `SizeIs(Lt(2))`. : -| `UnorderedElementsAre(e0, e1, ..., | `argument` has `n + 1` elements, and | -: en)` : under some permutation each element : -: : matches an `ei` (for a different : -: : `i`), which can be a value or a : -: : matcher. 0 to 10 arguments are : -: : allowed. : -| `UnorderedElementsAreArray({ e0, e1, | The same as `UnorderedElementsAre()` | -: ..., en })`, : except that the expected element : -: `UnorderedElementsAreArray(array)`, : values/matchers come from an : -: or `UnorderedElementsAreArray(array, : initializer list, STL-style : -: count)` : container, or C-style array. : -| `WhenSorted(m)` | When `argument` is sorted using the | -: : `<` operator, it matches container : -: : matcher `m`. E.g. : -: : `WhenSorted(ElementsAre(1, 2, 3))` : -: : verifies that `argument` contains : -: : elements `1`, `2`, and `3`, ignoring : -: : order. : -| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except | -: : that the given comparator instead of : -: : `<` is used to sort `argument`. E.g. : -: : `WhenSortedBy(std\:\:greater<int>(), : -: : ElementsAre(3, 2, 1))`. : +| Matcher | Description | +| :---------------------------------------- | :------------------------------- | +| `BeginEndDistanceIs(m)` | `argument` is a container whose | +: : `begin()` and `end()` iterators : +: : are separated by a number of : +: : increments matching `m`. E.g. : +: : `BeginEndDistanceIs(2)` or : +: : `BeginEndDistanceIs(Lt(2))`. For : +: : containers that define a : +: : `size()` method, `SizeIs(m)` may : +: : be more efficient. : +| `ContainerEq(container)` | The same as `Eq(container)` | +: : except that the failure message : +: : also includes which elements are : +: : in one container but not the : +: : other. : +| `Contains(e)` | `argument` contains an element | +: : that matches `e`, which can be : +: : either a value or a matcher. : +| `Each(e)` | `argument` is a container where | +: : *every* element matches `e`, : +: : which can be either a value or a : +: : matcher. : +| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, | +: : where the *i*-th element matches : +: : `ei`, which can be a value or a : +: : matcher. : +| `ElementsAreArray({e0, e1, ..., en})`, | The same as `ElementsAre()` | +: `ElementsAreArray(a_container)`, : except that the expected element : +: `ElementsAreArray(begin, end)`, : values/matchers come from an : +: `ElementsAreArray(array)`, or : initializer list, STL-style : +: `ElementsAreArray(array, count)` : container, iterator range, or : +: : C-style array. : +| `IsEmpty()` | `argument` is an empty container | +: : (`container.empty()`). : +| `IsFalse()` | `argument` evaluates to `false` | +: : in a Boolean context. : +| `IsSubsetOf({e0, e1, ..., en})`, | `argument` matches | +: `IsSubsetOf(a_container)`, : `UnorderedElementsAre(x0, x1, : +: `IsSubsetOf(begin, end)`, : ..., xk)` for some subset `{x0, : +: `IsSubsetOf(array)`, or : x1, ..., xk}` of the expected : +: `IsSubsetOf(array, count)` : matchers. : +| `IsSupersetOf({e0, e1, ..., en})`, | Some subset of `argument` | +: `IsSupersetOf(a_container)`, : matches : +: `IsSupersetOf(begin, end)`, : `UnorderedElementsAre(`expected : +: `IsSupersetOf(array)`, or : matchers`)`. : +: `IsSupersetOf(array, count)` : : +| `IsTrue()` | `argument` evaluates to `true` | +: : in a Boolean context. : +| `Pointwise(m, container)`, `Pointwise(m, | `argument` contains the same | +: {e0, e1, ..., en})` : number of elements as in : +: : `container`, and for all i, (the : +: : i-th element in `argument`, the : +: : i-th element in `container`) : +: : match `m`, which is a matcher on : +: : 2-tuples. E.g. `Pointwise(Le(), : +: : upper_bounds)` verifies that : +: : each element in `argument` : +: : doesn't exceed the corresponding : +: : element in `upper_bounds`. See : +: : more detail below. : +| `SizeIs(m)` | `argument` is a container whose | +: : size matches `m`. E.g. : +: : `SizeIs(2)` or `SizeIs(Lt(2))`. : +| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, | +: : and under *some* permutation of : +: : the elements, each element : +: : matches an `ei` (for a different : +: : `i`), which can be a value or a : +: : matcher. : +| `UnorderedElementsAreArray({e0, e1, ..., | The same as | +: en})`, : `UnorderedElementsAre()` except : +: `UnorderedElementsAreArray(a_container)`, : that the expected element : +: `UnorderedElementsAreArray(begin, end)`, : values/matchers come from an : +: `UnorderedElementsAreArray(array)`, or : initializer list, STL-style : +: `UnorderedElementsAreArray(array, count)` : container, iterator range, or : +: : C-style array. : +| `UnorderedPointwise(m, container)`, | Like `Pointwise(m, container)`, | +: `UnorderedPointwise(m, {e0, e1, ..., : but ignores the order of : +: en})` : elements. : +| `WhenSorted(m)` | When `argument` is sorted using | +: : the `<` operator, it matches : +: : container matcher `m`. E.g. : +: : `WhenSorted(ElementsAre(1, 2, : +: : 3))` verifies that `argument` : +: : contains elements 1, 2, and 3, : +: : ignoring order. : +| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, | +: : except that the given comparator : +: : instead of `<` is used to sort : +: : `argument`. E.g. : +: : `WhenSortedBy(std\:\:greater(), : +: : ElementsAre(3, 2, 1))`. : **Notes:** diff --git a/googlemock/docs/cook_book.md b/googlemock/docs/cook_book.md index 7116fd4..a858cd1 100644 --- a/googlemock/docs/cook_book.md +++ b/googlemock/docs/cook_book.md @@ -1,6 +1,6 @@ ## Googletest Mocking (gMock) Cookbook -<!-- GOOGLETEST_CM0011 DO NOT DELETE --> +<!-- GOOGLETEST_CM0012 DO NOT DELETE --> You can find recipes for using gMock here. If you haven't yet, please read [this](for_dummies.md) first to make sure you understand the basics. @@ -154,7 +154,7 @@ class MockStack : public StackInterface<Elem> { #### Mocking Non-virtual Methods {#MockingNonVirtualMethods} gMock can mock non-virtual functions to be used in Hi-perf dependency -injection.<!-- GOOGLETEST_CM0016 DO NOT DELETE -->. +injection.<!-- GOOGLETEST_CM0017 DO NOT DELETE -->. In this case, instead of sharing a common base class with the real class, your mock class will be *unrelated* to the real class, but contain methods with the @@ -1455,7 +1455,7 @@ mock object and gMock. #### Knowing When to Expect {#UseOnCall} -<!-- GOOGLETEST_CM0017 DO NOT DELETE --> +<!-- GOOGLETEST_CM0018 DO NOT DELETE --> **`ON_CALL`** is likely the *single most under-utilized construct* in gMock. diff --git a/googlemock/docs/for_dummies.md b/googlemock/docs/for_dummies.md index b75c9a0..5433e8b 100644 --- a/googlemock/docs/for_dummies.md +++ b/googlemock/docs/for_dummies.md @@ -1,6 +1,6 @@ ## Googletest Mocking (gMock) for Dummies {#GMockForDummies} -<!-- GOOGLETEST_CM0012 DO NOT DELETE --> +<!-- GOOGLETEST_CM0013 DO NOT DELETE --> ### What Is gMock? @@ -499,7 +499,7 @@ always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the -[cook book](http://<!-- GOOGLETEST_CM0011 DO NOT DELETE -->). +[cook book](http://<!-- GOOGLETEST_CM0012 DO NOT DELETE -->). Time for another quiz! What do you think the following means? diff --git a/googlemock/docs/gmock_faq.md b/googlemock/docs/gmock_faq.md index 27f0eb0..184c501 100644 --- a/googlemock/docs/gmock_faq.md +++ b/googlemock/docs/gmock_faq.md @@ -1,6 +1,6 @@ ## Legacy gMock FAQ {#GMockFaq} -<!-- GOOGLETEST_CM0020 DO NOT DELETE --> +<!-- GOOGLETEST_CM0021 DO NOT DELETE --> ### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem? diff --git a/googletest/README.md b/googletest/README.md index 6992f3c..766ddc1 100644 --- a/googletest/README.md +++ b/googletest/README.md @@ -174,9 +174,9 @@ We list the most frequently used macros below. For a complete list, see file ### Multi-threaded Tests Google Test is thread-safe where the pthread library is available. After -`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see -whether this is the case (yes if the macro is `#defined` to 1, no if it's -undefined.). +`#include "gtest/gtest.h"`, you can check the +`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is +`#defined` to 1, no if it's undefined.). If Google Test doesn't correctly detect whether pthread is available in your environment, you can force it with diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md index d31e4cf..ac7e689 100644 --- a/googletest/docs/advanced.md +++ b/googletest/docs/advanced.md @@ -1,6 +1,6 @@ # Advanced googletest Topics -<!-- GOOGLETEST_CM0015 DO NOT DELETE --> +<!-- GOOGLETEST_CM0016 DO NOT DELETE --> ## Introduction @@ -385,7 +385,7 @@ using ::testing::StartsWith; ``` Read this -[recipe](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#using-matchers-in-googletest-assertions) +[recipe](../../googlemock/docs/cook_book.md#using-matchers-in-googletest-assertions) in the gMock Cookbook for more details. gMock has a rich set of matchers. You can do many things googletest cannot do diff --git a/googletest/docs/faq.md b/googletest/docs/faq.md index 05baf23..0e9cfee 100644 --- a/googletest/docs/faq.md +++ b/googletest/docs/faq.md @@ -1,6 +1,6 @@ # Googletest FAQ -<!-- GOOGLETEST_CM0013 DO NOT DELETE --> +<!-- GOOGLETEST_CM0014 DO NOT DELETE --> ## Why should test suite names and test names not contain underscore? @@ -332,7 +332,7 @@ You may still want to use `SetUp()/TearDown()` in the following cases: * In the body of a constructor (or destructor), it's not possible to use the `ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal test failure that should prevent the test from running, it's necessary to - use `abort` <!-- GOOGLETEST_CM0014 DO NOT DELETE --> and abort the whole test executable, + use `abort` <!-- GOOGLETEST_CM0015 DO NOT DELETE --> and abort the whole test executable, or to use `SetUp()` instead of a constructor. * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads diff --git a/googletest/docs/pkgconfig.md b/googletest/docs/pkgconfig.md index 5ad1f01..b775873 100644 --- a/googletest/docs/pkgconfig.md +++ b/googletest/docs/pkgconfig.md @@ -1,25 +1,24 @@ -## Using GoogleTest from various build systems ## +## Using GoogleTest from various build systems GoogleTest comes with pkg-config files that can be used to determine all necessary flags for compiling and linking to GoogleTest (and GoogleMock). Pkg-config is a standardised plain-text format containing - * the includedir (-I) path - * necessary macro (-D) definitions - * further required flags (-pthread) - * the library (-L) path - * the library (-l) to link to +* the includedir (-I) path +* necessary macro (-D) definitions +* further required flags (-pthread) +* the library (-L) path +* the library (-l) to link to -All current build systems support pkg-config in one way or another. For -all examples here we assume you want to compile the sample +All current build systems support pkg-config in one way or another. For all +examples here we assume you want to compile the sample `samples/sample3_unittest.cc`. - -### CMake ### +### CMake Using `pkg-config` in CMake is fairly easy: -``` cmake +```cmake cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0048 NEW) @@ -43,11 +42,10 @@ that all libraries have been compiled with threading enabled. In addition, GoogleTest might also require `-pthread` in the compiling step, and as such splitting the pkg-config `Cflags` variable into include dirs and macros for `target_compile_definitions()` might still miss this). The same recommendation -goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which -happens to discard `-L` flags and `-pthread`. - +goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens +to discard `-L` flags and `-pthread`. -### Autotools ### +### Autotools Finding GoogleTest in Autoconf and using it from Automake is also fairly easy: @@ -77,8 +75,7 @@ testapp_CXXFLAGS = $(GTEST_CFLAGS) testapp_LDADD = $(GTEST_LIBS) ``` - -### Meson ### +### Meson Meson natively uses pkgconfig to query dependencies: @@ -96,13 +93,12 @@ testapp = executable( test('first_and_only_test', testapp) ``` +### Plain Makefiles -### Plain Makefiles ### +Since `pkg-config` is a small Unix command-line utility, it can be used in +handwritten `Makefile`s too: -Since `pkg-config` is a small Unix command-line utility, it can be used -in handwritten `Makefile`s too: - -``` Makefile +```Makefile GTEST_CFLAGS = `pkg-config --cflags gtest_main` GTEST_LIBS = `pkg-config --libs gtest_main` @@ -120,12 +116,11 @@ testapp.o: samples/sample3_unittest.cc $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS) ``` - -### Help! pkg-config can't find GoogleTest! ### +### Help! pkg-config can't find GoogleTest! Let's say you have a `CMakeLists.txt` along the lines of the one in this -tutorial and you try to run `cmake`. It is very possible that you get a -failure along the lines of: +tutorial and you try to run `cmake`. It is very possible that you get a failure +along the lines of: ``` -- Checking for one of the modules 'gtest_main' @@ -135,9 +130,9 @@ CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message): These failures are common if you installed GoogleTest yourself and have not sourced it from a distro or other package manager. If so, you need to tell -pkg-config where it can find the `.pc` files containing the information. -Say you installed GoogleTest to `/usr/local`, then it might be that the -`.pc` files are installed under `/usr/local/lib64/pkgconfig`. If you set +pkg-config where it can find the `.pc` files containing the information. Say you +installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are +installed under `/usr/local/lib64/pkgconfig`. If you set ``` export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig diff --git a/googletest/docs/primer.md b/googletest/docs/primer.md index 8f5c6e2..b8d48ba 100644 --- a/googletest/docs/primer.md +++ b/googletest/docs/primer.md @@ -164,7 +164,7 @@ you'll get a compiler error. We used to require the arguments to support the `<<` is supported, it will be called to print the arguments when the assertion fails; otherwise googletest will attempt to print them in the best way it can. For more details and how to customize the printing of the arguments, see -[documentation](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values) +[documentation](../../googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values) These assertions can work with a user-defined type, but only if you define the corresponding comparison operator (e.g. `==`, `<`, etc). Since this is diff --git a/googletest/docs/pump_manual.md b/googletest/docs/pump_manual.md index 3ec428e..10b3c5f 100644 --- a/googletest/docs/pump_manual.md +++ b/googletest/docs/pump_manual.md @@ -1,52 +1,51 @@ - - <b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming. -# The Problem # +# The Problem -Template and macro libraries often need to define many classes, -functions, or macros that vary only (or almost only) in the number of -arguments they take. It's a lot of repetitive, mechanical, and -error-prone work. +Template and macro libraries often need to define many classes, functions, or +macros that vary only (or almost only) in the number of arguments they take. +It's a lot of repetitive, mechanical, and error-prone work. -Variadic templates and variadic macros can alleviate the problem. -However, while both are being considered by the C++ committee, neither -is in the standard yet or widely supported by compilers. Thus they -are often not a good choice, especially when your code needs to be -portable. And their capabilities are still limited. +Variadic templates and variadic macros can alleviate the problem. However, while +both are being considered by the C++ committee, neither is in the standard yet +or widely supported by compilers. Thus they are often not a good choice, +especially when your code needs to be portable. And their capabilities are still +limited. -As a result, authors of such libraries often have to write scripts to -generate their implementation. However, our experience is that it's -tedious to write such scripts, which tend to reflect the structure of -the generated code poorly and are often hard to read and edit. For -example, a small change needed in the generated code may require some -non-intuitive, non-trivial changes in the script. This is especially -painful when experimenting with the code. +As a result, authors of such libraries often have to write scripts to generate +their implementation. However, our experience is that it's tedious to write such +scripts, which tend to reflect the structure of the generated code poorly and +are often hard to read and edit. For example, a small change needed in the +generated code may require some non-intuitive, non-trivial changes in the +script. This is especially painful when experimenting with the code. -# Our Solution # +# Our Solution Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta -Programming, or Practical Utility for Meta Programming, whichever you -prefer) is a simple meta-programming tool for C++. The idea is that a -programmer writes a `foo.pump` file which contains C++ code plus meta -code that manipulates the C++ code. The meta code can handle -iterations over a range, nested iterations, local meta variable -definitions, simple arithmetic, and conditional expressions. You can -view it as a small Domain-Specific Language. The meta language is -designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, -for example) and concise, making Pump code intuitive and easy to -maintain. - -## Highlights ## - - * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms. - * Pump tries to be smart with respect to [Google's style guide](https://github.com/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. - * The format is human-readable and more concise than XML. - * The format works relatively well with Emacs' C++ mode. - -## Examples ## - -The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line): +Programming, or Practical Utility for Meta Programming, whichever you prefer) is +a simple meta-programming tool for C++. The idea is that a programmer writes a +`foo.pump` file which contains C++ code plus meta code that manipulates the C++ +code. The meta code can handle iterations over a range, nested iterations, local +meta variable definitions, simple arithmetic, and conditional expressions. You +can view it as a small Domain-Specific Language. The meta language is designed +to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and +concise, making Pump code intuitive and easy to maintain. + +## Highlights + +* The implementation is in a single Python script and thus ultra portable: no + build or installation is needed and it works cross platforms. +* Pump tries to be smart with respect to + [Google's style guide](https://github.com/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. +* The format is human-readable and more concise than XML. +* The format works relatively well with Emacs' C++ mode. + +## Examples + +The following Pump code (where meta keywords start with `$`, `[[` and `]]` are +meta brackets, and `$$` starts a meta comment that ends with the line): ``` $var n = 3 $$ Defines a meta variable n. @@ -71,7 +70,7 @@ $if i == 0 [[ will be translated by the Pump compiler to: -``` cpp +```cpp // Foo0 does blah for 0-ary predicates. template <size_t N> class Foo0 { @@ -105,9 +104,10 @@ Func($for i + [[a$i]]); $$ The text between i and [[ is the separator between iterations. ``` -will generate one of the following lines (without the comments), depending on the value of `n`: +will generate one of the following lines (without the comments), depending on +the value of `n`: -``` cpp +```cpp Func(); // If n is 0. Func(a1); // If n is 1. Func(a1 + a2); // If n is 2. @@ -115,32 +115,38 @@ Func(a1 + a2 + a3); // If n is 3. // And so on... ``` -## Constructs ## +## Constructs We support the following meta programming constructs: -| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. | -|:----------------|:-----------------------------------------------------------------------------------------------| -| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later. | -| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`. | -| `$($)` | Generates a single `$` character. | -| `$id` | Value of the named constant or iteration variable. | -| `$(exp)` | Value of the expression. | -| `$if exp [[ code ]] else_branch` | Conditional. | -| `[[ code ]]` | Meta lexical block. | -| `cpp_code` | Raw C++ code. | -| `$$ comment` | Meta comment. | - -**Note:** To give the user some freedom in formatting the Pump source -code, Pump ignores a new-line character if it's right after `$for foo` -or next to `[[` or `]]`. Without this rule you'll often be forced to write -very long lines to get the desired output. Therefore sometimes you may -need to insert an extra new-line in such places for a new-line to show -up in your output. - -## Grammar ## - -``` ebnf +| `$var id = exp` | Defines a named constant value. `$id` is | +: : valid util the end of the current meta : +: : lexical block. : +| :------------------------------- | :--------------------------------------- | +| `$range id exp..exp` | Sets the range of an iteration variable, | +: : which can be reused in multiple loops : +: : later. : +| `$for id sep [[ code ]]` | Iteration. The range of `id` must have | +: : been defined earlier. `$id` is valid in : +: : `code`. : +| `$($)` | Generates a single `$` character. | +| `$id` | Value of the named constant or iteration | +: : variable. : +| `$(exp)` | Value of the expression. | +| `$if exp [[ code ]] else_branch` | Conditional. | +| `[[ code ]]` | Meta lexical block. | +| `cpp_code` | Raw C++ code. | +| `$$ comment` | Meta comment. | + +**Note:** To give the user some freedom in formatting the Pump source code, Pump +ignores a new-line character if it's right after `$for foo` or next to `[[` or +`]]`. Without this rule you'll often be forced to write very long lines to get +the desired output. Therefore sometimes you may need to insert an extra new-line +in such places for a new-line to show up in your output. + +## Grammar + +```ebnf code ::= atomic_code* atomic_code ::= $var id = exp | $var id = [[ code ]] @@ -159,19 +165,26 @@ else_branch ::= $else [[ code ]] exp ::= simple_expression_in_Python_syntax ``` -## Code ## +## Code -You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still -very unpolished and lacks automated tests, although it has been -successfully used many times. If you find a chance to use it in your -project, please let us know what you think! We also welcome help on -improving Pump. +You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). +It is still very unpolished and lacks automated tests, although it has been +successfully used many times. If you find a chance to use it in your project, +please let us know what you think! We also welcome help on improving Pump. -## Real Examples ## +## Real Examples -You can find real-world applications of Pump in [Google Test](https://github.com/google/googletest/tree/master/googletest) and [Google Mock](https://github.com/google/googletest/tree/master/googlemock). The source file `foo.h.pump` generates `foo.h`. +You can find real-world applications of Pump in +[Google Test](https://github.com/google/googletest/tree/master/googletest) and +[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The +source file `foo.h.pump` generates `foo.h`. -## Tips ## +## Tips - * 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. - * 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. +* 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. +* 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. |