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