blob: b93fae2b2ccfc30368e1525828df45f3fdade816 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
An example of an attribute procedural macro. The `#[trace_var(...)]` attribute
prints the value of the given variables each time they are reassigned.
- [`trace-var/src/lib.rs`](trace-var/src/lib.rs)
- [`example/src/main.rs`](example/src/main.rs)
Consider the following factorial implementation.
```rust
#[trace_var(p, n)]
fn factorial(mut n: u64) -> u64 {
let mut p = 1;
while n > 1 {
p *= n;
n -= 1;
}
p
}
```
Invoking this with `factorial(8)` prints all the values of `p` and `n` during
the execution of the function.
```
p = 1
p = 8
n = 7
p = 56
n = 6
p = 336
n = 5
p = 1680
n = 4
p = 6720
n = 3
p = 20160
n = 2
p = 40320
n = 1
```
The procedural macro uses a syntax tree [`Fold`] to rewrite every `let`
statement and assignment expression in the following way:
[`Fold`]: https://docs.rs/syn/1.0/syn/fold/trait.Fold.html
```rust
// Before
let VAR = INIT;
// After
let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
```
```rust
// Before
VAR = INIT
// After
{ VAR = INIT; println!("VAR = {:?}", VAR); }
```
|