An example of an attribute procedural macro. The #[trace_var(...)]
attribute prints the value of the given variables each time they are reassigned.
Consider the following factorial implementation.
#[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:
// Before let VAR = INIT; // After let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
// Before VAR = INIT // After { VAR = INIT; println!("VAR = {:?}", VAR); }