[−][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.