Skip to content

Commit ddfa21e

Browse files
committed
Add capture section
And add Cpp1 lowering notes for parameter passing
1 parent 9f75d36 commit ddfa21e

File tree

4 files changed

+76
-15
lines changed

4 files changed

+76
-15
lines changed

docs/cpp2/common.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Both **`123.nm()`** and **`123.u8()`** are very similar to user-defined literal
122122

123123
Operators have the same precedence and associativity as in Cpp1, but some unary operators that are prefix (always or sometimes) in Cpp1 are postfix (always) in Cpp2.
124124

125-
## Unary operators
125+
### Unary operators
126126

127127
The operators `!`, `+`, and `-` are prefix, as in Cpp1. For example:
128128

@@ -178,7 +178,7 @@ Unary suffix operators must not be preceded by whitespace. When `*`, `&`, and `~
178178
For more details, see [Design note: Postfix unary operators vs binary operators](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-unary-operators-vs-binary-operators).
179179

180180

181-
## Binary operators
181+
### Binary operators
182182

183183
Binary operators are the same as in Cpp1. From highest to lowest precedence:
184184

docs/cpp2/expressions.md

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,68 @@ For more examples, see also the examples in the previous two sections on `is` an
212212
213213
## `$` — captures, including interpolations
214214
215-
TODO
215+
Suffix `$` is pronounced **"paste the value of"** and captures the value of an expression at the point when the expression where the capture is written is evaluated. Depending the complexity of the capture expression `expr$` and where it is used, parentheses `(expr)$` may be required for precedence or to show the boundaries of the expression.
216+
217+
`x$` always captures `x` by value. To capture by reference, take the address and capture a pointer using `x&$`. If the value is immediately used, dereference again; for example `:(val) total&$* += val` adds to the `total` local variable itself, not a copy.
218+
219+
Any capture is evaluated at the point where it is written, in the function expression, contract postcondition, or string literal. The stored captured value can then be used later when the context it is in is evaluated, such as when the function expression body it's in is actually called later (one or more times), when the postcondition it's in is evaluated later when the function returns, or when the string literal it's in is read later.
220+
221+
222+
### Capture in function expressions (aka lambdas)
223+
224+
Any capture in a function expression body is evaluated at the point where the function expression is written, at the declaration of the function expression. The function expression itself is then evaluated each time the function is invoked, and can reference the captured value.
225+
226+
For example:
227+
228+
``` cpp title="Capture in an unnamed function expression (aka lambda)" hl_lines="6 7"
229+
main: () = {
230+
s := "-sh\n";
231+
vec: std::vector = (1, 2, 3, 5, 8, 13 );
232+
233+
vec.std::ranges::for_each(
234+
:(i) = { std::cout << i << s$; }
235+
// Function capture: Paste local variable value
236+
);
237+
}
238+
```
239+
240+
The design and syntax are selected so that capture is spelled the same way in all contexts. For details, see [Design note: Capture](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Capture).
241+
242+
243+
### Capture in contract postconditions
244+
245+
Any capture in a postcondition is evaluated at the point where the postcondition is written, at the beginning (entry) of the function. The postcondition itself is then evaluated when the function returns, and can reference the captured value.
246+
247+
For example:
248+
249+
``` cpp title="Capture in contract postconditions" hl_lines="2 3"
250+
push_back: (coll, value)
251+
[[post: coll.ssize() == coll.ssize()$ + 1]]
252+
// Postcondition capture: Paste "old" size
253+
= {
254+
// ...
255+
}
256+
```
257+
258+
259+
### Capture in string interpolation
260+
261+
A string literal can capture the value of an expression `expr` by writing `(expr)$` inside the string literal. The `(` `)` are required, and cannot be nested.
262+
263+
Any capture in a string literal is evaluated at the point where the string literal is written. The string literal can be used repeatedly later, and includes the captured value.
264+
265+
For example:
266+
267+
``` cpp title="Capture for string interpolation" hl_lines="2 4"
268+
x := 0;
269+
std::cout << "x is (x)$\n";
270+
x = 1;
271+
std::cout << "now x+2 is (x+2)$\n";
272+
273+
// prints:
274+
// x is 0
275+
// now x+2 is 3
276+
```
277+
278+
A string literal has type `std::string` if it performs any captures, otherwise it is a normal C/C++ string literal (array of characters).
216279

217-
For details, see [Design note: Capture](https://github.com/hsutter/cppfront/wiki/Design-note%3A-Capture).

docs/cpp2/functions.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ TODO
1010

1111
There are six ways to pass parameters that cover all use cases:
1212

13-
| Parameter kind | "Pass me an `x` I can ______" | Accepts arguments that are | Special semantics |
14-
|---|---|---|---|
15-
| `in` (default) | read from | anything | always `#!cpp const`<p>automatically passes by value if cheaply copyable |
16-
| `copy` | take a copy of | anything | acts like a normal local variable initialized with the argument |
17-
| `inout` | read from and write to | lvalues | |
18-
| `out` | write to (including construct) | lvalues, including uninitialized lvalues | must `=` assign/construct before other uses |
19-
| `move` | move from | rvalues | automatically moves from every definite last use |
20-
| `forward` | forward | anything | automatically forwards from every definite last use |
21-
13+
| Parameter ***kind*** | "Pass me an `x` I can ______" | Accepts arguments that are | Special semantics | ***kind*** `x: X` Compiles to Cpp1 as |
14+
|---|---|---|---|---|
15+
| `in` (default) | read from | anything | always `#!cpp const`<p>automatically passes by value if cheaply copyable | `X const x` or `X const& x` |
16+
| `copy` | take a copy of | anything | acts like a normal local variable initialized with the argument | `X x` |
17+
| `inout` | read from and write to | lvalues | | `X& x` |
18+
| `out` | write to (including construct) | lvalues, including uninitialized lvalues | must `=` assign/construct before other uses | `cpp2::out<X>` |
19+
| `move` | move from | rvalues | automatically moves from every definite last use | `X&&` |
20+
| `forward` | forward | anything | automatically forwards from every definite last use | `T&&` constrained to type `X` |
2221

2322

2423
> Note: All parameters and other objects in Cpp2 are `#!cpp const` by default, except for local variables. For details, see [Design note: `#!cpp const` objects by default](https://github.com/hsutter/cppfront/wiki/Design-note%3A-const-objects-by-default).

mkdocs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ nav:
5555
- 'Hello, world!': welcome/hello-world.md
5656
- 'Adding cppfront to your existing C++ project': welcome/integration.md
5757
- 'Cpp2 reference':
58-
- 'Common programming concepts': cpp2/common.md
59-
- 'Common expressions': cpp2/expressions.md
58+
- 'Common concepts': cpp2/common.md
59+
- 'Expressions': cpp2/expressions.md
6060
- 'Declaration syntax': cpp2/declarations.md
6161
- 'Objects, initialization, and memory': cpp2/objects.md
6262
- 'Functions, branches, and loops': cpp2/functions.md

0 commit comments

Comments
 (0)