aboutsummaryrefslogtreecommitdiff
path: root/syn/examples/trace-var/README.md
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); }
```