[][src]Macro stateful_macro_rules::stateful_macro_rules

stateful_macro_rules!() { /* proc-macro */ }

Generate macro_rules! macros that have states.

Basic: Macro name and body

To specify the generated macro name and its final expanded content, use name() { body }.

For example, the code below generates a macro called foo!() and it expands to "foo".

stateful_macro_rules! {
    foo() { "foo" };
}

States

To define states, add them to the () after the macro name. A state can be defined as state_name: (pattern) = (default_value)). Multiple states are separated by ,. States can be referred by their pattern name.

For example, the code below defines a plus!() macro with x and y states (but there is no real way to use this macro):

stateful_macro_rules! {
    pos(x: ($x:expr) = (0), y: ($y:expr) = (0)) { ($x, $y) };
}

Rules

To make the macro useful, macro rules like (pattern) => { body } are needed. Unlike rules in classic macro_rules!, the pattern matches incomplete tokens (use ... to mark the incomplete portion), and body can only contain changes to states like state_name.set(tokens), or state_name.append(tokens).

stateful_macro_rules! {
    pos(x: ($x:expr) = (0), y: ($y:expr) = (0)) { ($x, $y) };
    (incx($i:expr) ...) => { x.set($x + $i); };
    (incx ...) => { x.set($x + 1); };
    (incy($i:expr) ...) => { y.set($y + $i); };
    (incy ...) => { y.set($y + 1); };

    // `...` is implicitly at the end
    (reset) => { x.set(0); y.set(0); };  

    // `...` can be in the middle
    (eval( ... )) => { };
}
assert_eq!(pos!(incx(3) reset incy incy(10) incx), (1, 11));
assert_eq!(pos!(eval(incx(10) incy(20))), (10, 20));

Conditional Rules

Rules can be disabled by states. This is done by the when block.

stateful_macro_rules! {
    toggle(result: ($v:tt) = (0)) { $v };
    (T) when { result: (0) } => { result.set(1); };
    (T) when { result: (1) } => { result.set(0); };
}
assert_eq!(toggle![T T T], 1);

Debugging

If the debug feature is on, debug; can be used to print the generated code to stderr. The code can be used as a drop-in macro replacement to help debugging.