### Derive Macro Usage Example Source: https://github.com/veykril/tlborm/blob/main/src/proc-macros/methodical/derive.md Demonstrates how to apply a custom derive macro to a struct. Ensure the derive macro crate is imported. ```rust use tlborm_proc::TlbormDerive; #[derive(TlbormDerive)] struct Foo; ``` -------------------------------- ### Macro Expansion Order Limitation Example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/callbacks.md Illustrates the limitation where one macro cannot directly pass information to another macro's expansion due to expansion order. This example shows a macro `recognize_tree` and another `expand_to_larch` which, when called, results in an unexpected fallback output. ```rust macro_rules! recognize_tree { (larch) => { println!("#1, the Larch.") }; (redwood) => { println!("#2, the Mighty Redwood.") }; (fir) => { println!("#3, the Fir.") }; (chestnut) => { println!("#4, the Horse Chestnut.") }; (pine) => { println!("#5, the Scots Pine.") }; ($($other:tt)*) => { println!("I don't know; some kind of birch maybe?") }; } macro_rules! expand_to_larch { () => { larch }; } fn main() { recognize_tree!(expand_to_larch!()); // first expands to: recognize_tree! { expand_to_larch ! ( ) } // and then: println! { "I don't know; some kind of birch maybe?" } } ``` -------------------------------- ### Example of calling a macro with multiple function declarations Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/tt-muncher.md Illustrates how to call a macro with multiple function declarations, contrasting with a TT muncher approach. ```rust f! { fn f_u8(x: u32) -> u8; fn f_u16(x: u32) -> u16; fn f_u32(x: u32) -> u32; fn f_u64(x: u64) -> u64; fn f_u128(x: u128) -> u128; } ``` -------------------------------- ### Example Macro Invocations Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/ast.md Illustrates various syntax extension forms including function-like macros and attributes. The parser treats the arguments within these invocations as token trees. ```rust bitflags! { struct Color: u8 { const RED = 0b0001, const GREEN = 0b0010, const BLUE = 0b0100, const BRIGHT = 0b1000, } } lazy_static! { static ref FIB_100: u32 = { fn fib(a: u32) -> u32 { match a { 0 => 0, 1 => 1, a => fib(a-1) + fib(a-2) } } fib(100) }; } fn main() { use Color::*; let colors = vec![RED, GREEN, BLUE]; println!("Hello, World!"); } ``` -------------------------------- ### Recurrence Macro Invocation Example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md Demonstrates how to invoke the `recurrence!` macro to define a Fibonacci sequence and iterate over its first 10 elements. ```rust let fib = recurrence![a[n] = 0, 1, ..., a[n-2] + a[n-1]]; for e in fib.take(10) { println!("{}", e) } ``` -------------------------------- ### Expanding Initializers in a Macro Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This example shows how to expand the '$($inits:expr),+' metavariable to generate a comma-separated list of initial values for an array literal within a macro. ```rust Recurrence { mem: [$($inits),+], pos: 0 } // ^~~~~~~~~~~ changed ``` -------------------------------- ### Rust Macro `ty` Fragment Example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Illustrates the `ty` fragment specifier in Rust macros, which matches various type expressions. ```rust macro_rules! types { ($($type:ty)*) => (); } types! { foo::bar bool [u8] impl IntoIterator } # fn main() {} ``` -------------------------------- ### Using the Recurrence Macro for Factorials Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This example demonstrates how to use the `recurrence!` macro to generate a sequence of factorials. It initializes the sequence with `1.0` and defines the recursive step as `f[i-1] * i as f64`. The output is then limited to the first 10 elements. ```rust fn main() { for e in recurrence!(f[i]: f64 = 1.0; ...; f[i-1] * i as f64).take(10) { println!("{}", e) } } ``` -------------------------------- ### C/C++ Macro Example Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/source-analysis.md Illustrates how C/C++ macros can alter the perceived structure of code before compilation, using `#define` for type and block substitution. ```c #define SUB int #define BEGIN { #define END } SUB main() BEGIN printf("Oh, the horror!\n"); END ``` -------------------------------- ### Macro Declaration Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/turing-completeness.md Starts the definition of the macro that will simulate a Tag System. ```rust macro_rules! my_tag_system { ``` -------------------------------- ### Example of calling a macro for a single function declaration Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/tt-muncher.md Shows how to call a macro for a single function declaration, as an alternative to a TT muncher handling multiple declarations. ```rust f! { fn f_u8(x: u32) -> u8; } f! { fn f_u16(x: u32) -> u16; } f! { fn f_u32(x: u32) -> u32; } f! { fn f_u64(x: u64) -> u64; } f! { fn f_u128(x: u128) -> u128; } ``` -------------------------------- ### Illustrative Macro for Direct Array Expansion (Not Supported) Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/push-down-acc.md This is an example of how one might attempt direct array expansion, which is not supported in Rust macros due to the requirement for complete syntax elements at each expansion step. ```rust macro_rules! init_array { [$e:expr; $n:tt] => { { let e = $e; [accum!($n, e.clone())] } }; } macro_rules! accum { (3, $e:expr) => { $e, accum!(2, $e) }; (2, $e:expr) => { $e, accum!(1, $e) }; (1, $e:expr) => { $e }; } ``` -------------------------------- ### Empty matcher example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-methodical.md A simple `macro_rules!` macro that matches an empty input. The invocation can use `!()`, `[]`, or `{}`. ```rust macro_rules! four { () => { 1 + 3 }; } ``` -------------------------------- ### Complete Rust Example: Fibonacci Sequence with Macros Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md A full implementation of a Fibonacci sequence generator using a custom `Recurrence` struct and `IndexOffset` for accessing previous terms. The code demonstrates how to manage state and calculate terms iteratively. ```rust macro_rules! recurrence { ( a[n]: $sty:ty = $($inits:expr),+ , ... , $recur:expr ) => { /* ... */ }; } fn main() { /* let fib = recurrence![a[n]: u64 = 0, 1, ..., a[n-2] + a[n-1]]; for e in fib.take(10) { println!("{}", e) } */ let fib = { use std::ops::Index; struct Recurrence { mem: [u64; 2], pos: usize, } struct IndexOffset<'a> { slice: &'a [u64; 2], offset: usize, } impl<'a> Index for IndexOffset<'a> { type Output = u64; #[inline(always)] fn index<'b>(&'b self, index: usize) -> &'b u64 { use std::num::Wrapping; let index = Wrapping(index); let offset = Wrapping(self.offset); let window = Wrapping(2); let real_index = index - offset + window; &self.slice[real_index.0] } } impl Iterator for Recurrence { type Item = u64; #[inline] fn next(&mut self) -> Option { if self.pos < 2 { let next_val = self.mem[self.pos]; self.pos += 1; Some(next_val) } else { let next_val = { let n = self.pos; let a = IndexOffset { slice: &self.mem, offset: n }; a[n-2] + a[n-1] }; { use std::mem::swap; let mut swap_tmp = next_val; for i in [1,0] { swap(&mut swap_tmp, &mut self.mem[i]); } } self.pos += 1; Some(next_val) } } } Recurrence { mem: [0, 1], pos: 0 } }; for e in fib.take(10) { println!("{}", e) } } ``` -------------------------------- ### Example of Syntax Extension Invocation Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md Illustrates a simple syntax extension invocation within a let statement. The compiler will replace `four!()` with its expanded AST. ```rust let eight = 2 * four!(); ``` -------------------------------- ### Parsed Token Tree Structure Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/source-analysis.md Visualizes the hierarchical structure of token trees derived from the example expression, showing leaves and interior nodes. ```text «a» «+» «b» «+» «( )» «+» «e» ╭────────┴──────────╮ «c» «+» «d» «[ ]» ╭─┴─╮ «0» ``` -------------------------------- ### Usage Example of a Function-like Macro Source: https://github.com/veykril/tlborm/blob/main/src/proc-macros/methodical/function-like.md Demonstrates how to invoke a function-like macro, `tlborm_attribute!`, within a Rust function. The macro is called with specific arguments. ```Rust use tlborm_proc::tlborm_attribute; fn foo() { tlborm_attribute!(be quick; time is mana); } ``` -------------------------------- ### Setting Recursion Limit Attribute Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md Example of how to increase the syntax extension recursion limit for the entire crate using a crate-level attribute. ```rust #![recursion_limit="128"] ``` -------------------------------- ### Callback Pattern for Macro Modularity Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/callbacks.md Demonstrates the callback pattern using `macro_rules!` to pass information between macros, overcoming the expansion order limitation. This example shows `call_with_larch` invoking `recognize_tree` with a specific argument. ```rust # macro_rules! recognize_tree { # (larch) => { println!("#1, the Larch.") }; # (redwood) => { println!("#2, the Mighty Redwood.") }; # (fir) => { println!("#3, the Fir.") }; # (chestnut) => { println!("#4, the Horse Chestnut.") }; # (pine) => { println!("#5, the Scots Pine.") }; # ($($other:tt)*) => { println!("I don't know; some kind of birch maybe?") }; # } macro_rules! call_with_larch { ($callback:ident) => { $callback!(larch) }; } fn main() { call_with_larch!(recognize_tree); // first expands to: call_with_larch! { recognize_tree } // then: recognize_tree! { larch } // and finally: println! { "#1, the Larch." } } ``` -------------------------------- ### Rust AST Coercion Macros Example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/building-blocks/ast-coercion.md Demonstrates the usage of various AST coercion macros (`as_expr!`, `as_item!`, `as_pat!`, `as_stmt!`, `as_ty!`) to help the Rust parser handle substituted tt tokens. These are useful in scenarios where the parser might otherwise fail due to unexpected token types. ```rust #![allow(dead_code)] macro_rules! as_expr { ($e:expr) => {$e} } macro_rules! as_item { ($i:item) => {$i} } macro_rules! as_pat { ($p:pat) => {$p} } macro_rules! as_stmt { ($s:stmt) => {$s} } macro_rules! as_ty { ($t:ty) => {$t} } as_item!{struct Dummy;} fn main() { as_stmt!(let as_pat!(_): as_ty!(_) = as_expr!(42)); } ``` -------------------------------- ### Expansion Steps of Push-down Accumulation Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/push-down-acc.md Illustrates the step-by-step expansion process of the push-down accumulation macro, showing how tokens are built incrementally until a complete construct is formed. ```rust init_array!(String::from("hi!"); 3) accum!([3, e.clone()] -> []) accum!([2, e.clone()] -> [e.clone(),]) accum!([1, e.clone()] -> [e.clone(), e.clone(),]) accum!([0, e.clone()] -> [e.clone(), e.clone(), e.clone(),]) [e.clone(), e.clone(), e.clone(),] ``` -------------------------------- ### Halting Condition: Starts with H Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/turing-completeness.md Defines a halting condition for the macro when the input starts with the halting symbol 'H'. ```rust (H $($tail:tt)*) => {}; ``` -------------------------------- ### Expansion Steps of Direct Array Expansion Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/push-down-acc.md Demonstrates the expected expansion steps for a direct array expansion macro, highlighting why this approach fails due to incomplete intermediate expressions. ```rust [accum!(3, e.clone())] [e.clone(), accum!(2, e.clone())] [e.clone(), e.clone(), accum!(1, e.clone())] [e.clone(), e.clone(), e.clone()] ``` -------------------------------- ### Compile-fail Example: Unequal Repetitions in Macro Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-methodical.md This example shows a macro invocation that fails to compile because the metavariables within the repetition do not repeat an equal number of times. The compiler error indicates the mismatch in repetition counts. ```rust macro_rules! repeat_two { ($($i:ident)*, $($i2:ident)*) => { $( let $i: (); let $i2: (); )* } } repeat_two!( a b c d e f, x y z ); ``` -------------------------------- ### Matching Lifetimes and Labels Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Use the `lifetime` fragment to match Rust lifetimes or loop labels, which are similar to identifiers but start with a `'`. ```rust macro_rules! lifetimes { ($($lifetime:lifetime)*) => (); } lifetimes! { 'static 'shiv '_ } # fn main() {} ``` -------------------------------- ### Inspecting Macro Expansion with `rustc -Zunpretty=expanded` Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This command-line snippet demonstrates how to use the `rustc` compiler with the `-Zunpretty=expanded` flag to view the code generated after macro expansion. This is useful for debugging and understanding how macros transform code. ```shell $ rustc +nightly -Zunpretty=expanded recurrence.rs ``` -------------------------------- ### Expanded Code Example Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md The code after `four!()` has been expanded to `1 + 3`. Parentheses are implicitly added by the compiler's AST interpretation. ```rust let eight = 2 * (1 + 3); ``` -------------------------------- ### Instantiating and Using the Fibonacci Iterator Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This snippet shows how to create an instance of the `Recurrence` iterator, initialized for the Fibonacci sequence, and then use it to print the first 10 elements. ```rust let fib = { struct Recurrence { mem: [u64; 2], pos: usize, } impl Iterator for Recurrence { type Item = u64; fn next(&mut self) -> Option { if self.pos < 2 { let next_val = self.mem[self.pos]; self.pos += 1; Some(next_val) } else { let a = /* something */; let n = self.pos; let next_val = (a[n-2] + a[n-1]); self.mem.TODO_shuffle_down_and_append(next_val.clone()); self.pos += 1; Some(next_val) } } } Recurrence { mem: [0, 1], pos: 0 } }; for e in fib.take(10) { println!("{}", e) } ``` -------------------------------- ### Counting Metavariable Repetitions with count() Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/metavar-expr.md Illustrates the usage of the count() metavariable expression to get the repetition count of metavariables at different depths. ```rust #![feature(macro_metavar_expr)] macro_rules! foo { ( $( $outer:ident ( $( $inner:ident ),* ) ; )* ) => { println!("count(outer, 0): $outer repeats {} times", ${count($outer)}); println!("count(inner, 0): The $inner repetition repeats {} times in the outer repetition", ${count($inner, 0)}); println!("count(inner, 1): $inner repeats {} times in the inner repetitions", ${count($inner, 1)}); }; } fn main() { foo! { outer () ; outer ( inner , inner ) ; outer () ; outer ( inner ) ; }; } ``` -------------------------------- ### Production Rule Simulation Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/turing-completeness.md Simulates a production rule P(x) for a Tag System. It takes 'm-1' identifiers and the rest of the tail, then recursively calls the macro with the tail and the expansion of P(x). ```rust // P(x) ($x:ident $d_1:tt $d_2:tt /* ... */ $d_m_minus_1:tt $($tail:tt)*) => { my_tag_system!($($tail)* p_x) }; ``` -------------------------------- ### Using $crate with Fully Qualified Paths Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/hygiene.md Illustrates how to use $crate with a fully qualified module path when referring to non-macro items within the defining crate. This is necessary for items not directly in the crate root. ```rust pub mod inner { #[macro_export] macro_rules! call_foo { () => { $crate::inner::foo() }; } pub fn foo() {} } ``` -------------------------------- ### Getting Current Iteration Index with index() Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/metavar-expr.md Demonstrates the index() metavariable expression to retrieve the current iteration index of a repetition at specified or default depths. ```rust #![feature(macro_metavar_expr)] macro_rules! attach_iteration_counts { ( $( ( $( $inner:ident ),* ) ; )* ) => { ( $( $(( stringify!($inner), ${index(1)}, // this targets the outer repetition ${index()} // and this, being an alias for `index(0)` targets the inner repetition ),)* )* ) }; } fn main() { let v = attach_iteration_counts! { ( hello ) ; ( indices , of ) ; () ; ( these, repetitions ) ; }; println!("{v:?}"); } ``` -------------------------------- ### Comparing macro_rules! and macro Syntax Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros2.md Illustrates the syntactic similarities and differences between `macro_rules!` and `macro` for `replace_expr` and `count_tts` macros. Note the use of `macro` keyword and `,` as a rule separator in `macro`. ```rust # // This code block marked `ignore` because mdbook can't handle `#![feature(...)]`. #![feature(decl_macro)] macro_rules! replace_expr_ { ($_t:tt $sub:expr) => { $sub } } macro replace_expr($_t:tt $sub:expr) { $sub } macro_rules! count_tts_ { () => { 0 }; ($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 }; ($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 }; } macro count_tts { () => { 0 }, ($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 }, ($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 }, } ``` -------------------------------- ### Configure Proc-Macro Crate in Cargo.toml Source: https://github.com/veykril/tlborm/blob/main/src/proc-macros/methodical.md To define a proc-macro crate, set the `lib.proc-macro` key in your `Cargo.toml` file to true. This is a necessary configuration step for using procedural macros. ```toml [lib] proc-macro = true ``` -------------------------------- ### Using the Recurrence Macro for Fibonacci Sequence Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md Demonstrates how to use the `recurrence!` macro to define and generate the Fibonacci sequence. The macro simplifies the definition of sequences based on their recurrence relations. ```rust fn main() { let fib = recurrence![a[n]: u64 = 0, 1; ...; a[n-2] + a[n-1]]; for e in fib.take(10) { println!("{}", e) } } ``` -------------------------------- ### AST Visualization Before Expansion Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md A textual representation of the Abstract Syntax Tree (AST) before the `four!()` syntax extension is expanded. ```text ┌─────────────┐ │ Let │ │ name: eight │ ┌─────────┐ │ init: ◌ │╶─╴│ BinOp │ └─────────────┘ │ op: Mul │ ┌╴│ lhs: ◌ │ ┌────────┐ │ │ rhs: ◌ │╶┐ ┌────────────┐ │ LitInt │╶┘ └─────────┘ └╴│ Macro │ │ val: 2 │ │ name: four │ └────────┘ │ body: () │ └────────────┘ ``` -------------------------------- ### Non-Hygienic Macro: Creating Identifiers Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/hygiene.md This example demonstrates a non-hygienic macro that creates an identifier ('local'). If the 'local' in the assertion resolves to the one defined by the macro, the macro is not hygienic. ```rust make_local!(); assert_eq!(local, 0); ``` -------------------------------- ### Rust Macro `stmt` Fragment Example Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Demonstrates the `stmt` fragment specifier in Rust macros. It captures statements without trailing semicolons, but emits them when required by Rust syntax. ```rust macro_rules! statements { ($($stmt:stmt)*) => ($($stmt)*); } fn main() { statements! { struct Foo; fn foo() {} let zig = 3 let zig = 3; 3 3; if true {} else {} {} } } ``` -------------------------------- ### Abstract Syntax Tree (AST) for an Expression Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/source-analysis.md Presents the corresponding Abstract Syntax Tree for the same expression, contrasting its single root node structure with token trees. ```text ┌─────────┐ │ BinOp │ │ op: Add │ ┌╴│ lhs: ◌ │ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ BinOp │╶┘ └─────────┘ └╴│ Var │ │ op: Add │ │ name: e │ ┌╴│ lhs: ◌ │ └─────────┘ ┌─────────┐ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ Var │╶┐ │ BinOp │╶┘ └─────────┘ └╴│ BinOp │ │ name: a │ │ │ op: Add │ │ op: Add │ └─────────┘ └╴│ lhs: ◌ │ ┌╴│ lhs: ◌ │ ┌─────────┐ ┌╴│ rhs: ◌ │ ┌─────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ Var │╶┘ └─────────┘ │ Var │╶┘ └─────────┘ └╴│ Index │ │ name: b │ │ name: c │ ┌╴│ arr: ◌ │ └─────────┘ └─────────┘ ┌─────────┐ │ │ ind: ◌ │╶┐ │ Var │╶┘ └─────────┘ │ │ name: d │ ┌─────────┐ │ └─────────┘ │ LitInt │╶┘ │ val: 0 │ └─────────┘ ``` -------------------------------- ### Defining a Recursive Sequence Macro Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This macro defines a recursive sequence with initial values and a recurrence relation. It's designed to generate sequences like Fibonacci. The commented-out example shows how to use it. ```rust macro_rules! recurrence { ( a[n]: $sty:ty = $($inits:expr),+ , ... , $recur:expr ) => { /* ... */ }; } /* let fib = recurrence![a[n]: u64 = 0, 1, ..., a[n-2] + a[n-1]]; for e in fib.take(10) { println!("{}", e) } */ ``` -------------------------------- ### Using the Recurrence Macro in Rust Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md Demonstrates how to use the `recurrence!` macro to define a Fibonacci-like sequence and iterate over its first 10 elements. ```Rust fn main() { let fib = recurrence![a[n]: u64 = 1, 1; ...; a[n-2] + a[n-1]]; for e in fib.take(10) { println!("{}", e) } } ``` -------------------------------- ### Macro Expansion Showing Hygiene Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/hygiene.md Illustrates the expansion of the 'using_a!' macro, highlighting how the macro-introduced 'a' has a different syntax context than the 'a' used in the outer scope, leading to a compilation error. ```rust let four = { let a = 42; a / 10 }; ``` -------------------------------- ### Non-Hygienic Macro: Using Identifiers Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/hygiene.md This example shows a non-hygienic macro that uses an identifier ('local') from its surrounding context. If the 'local' within the macro resolves to the one defined before its invocation, the macro is not hygienic. ```rust let mut local = 0; use_local!(); ``` -------------------------------- ### Distinguishing `self` as Keyword vs. Identifier in Macros Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/identifiers.md Demonstrates how `macro_rules!` can distinguish between `self` as a keyword and `self` as a matched identifier. This example shows `self` being correctly interpreted in different macro contexts. ```rust macro_rules! what_is { (self) => {"the keyword `self`"}; ($i:ident) => {concat!("the identifier `", stringify!($i), "`")}; } macro_rules! call_with_ident { ($c:ident($i:ident)) => {$c!($i)}; } fn main() { println!("{}", what_is!(self)); println!("{}", call_with_ident!(what_is(self))); } ``` -------------------------------- ### Macro rule format Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-methodical.md Illustrates the standard format for a single macro rule, consisting of a matcher and an expansion. Brackets, parentheses, or braces can be used for both. ```rust ($matcher) => {$expansion} ``` -------------------------------- ### Unified Macro with Internal Rule Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/internal-rules.md Demonstrates a unified macro using an internal rule pattern, allowing for cleaner invocation and management of sub-rules. ```rust #[macro_export] macro_rules! foo { (@as_expr $e:expr) => {$e}; ($($tts:tt)*) => { foo!(@as_expr $($tts)*) }; } # # fn main() { # assert_eq!(foo!(42), 42); # } ``` -------------------------------- ### Abstract Syntax Tree Representation of Macro Invocations Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/ast.md Shows how the Rust parser simplifies complex macro invocations into generic token tree placeholders (⬚) within the AST, without understanding their internal structure. ```text bitflags! ⬚ lazy_static! ⬚ fn main() { let colors = vec! ⬚; println! ⬚; } ``` -------------------------------- ### Macro Invoking `self` as Identifier in Method Body (Compile Fail) Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/identifiers.md This example shows a macro that attempts to define a method where `self` is passed as an identifier but then used directly in the body. It fails because the macro's hygiene rules prevent direct use of the keyword `self` in this manner. ```rust,compile_fail macro_rules! double_method { ($body:expr) => { fn double(mut self) -> Dummy { $body } }; } struct Dummy(i32); impl Dummy { double_method! {{ self.0 *= 2; self }} } # # fn main() { # println!("{:?}", Dummy(4).double().0); # } ``` -------------------------------- ### Literal token tree matching Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-methodical.md Demonstrates how to match a specific sequence of literal token trees within a macro matcher. The exact sequence must be present in the input. ```rust macro_rules! gibberish { (4 fn ['spang "whammo"] @_@) => {...}; } ``` -------------------------------- ### Skeleton of a Function-like Procedural Macro Source: https://github.com/veykril/tlborm/blob/main/src/proc-macros/methodical/function-like.md This is a basic structure for a function-like procedural macro. It takes a `TokenStream` as input and returns a `TokenStream`, effectively mapping input tokens to output tokens. ```Rust use proc_macro::TokenStream; #[proc_macro] pub fn tlborm_fn_macro(input: TokenStream) -> TokenStream { input } ``` -------------------------------- ### Rust macro_rules! simulating a Tag System Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/turing-completeness.md This macro definition simulates a Tag System, which is a model of computation. It includes rules for halting and non-halting input, demonstrating the core logic for Turing completeness. ```rust macro_rules! my_tag_system { // Halting Input (H $($tail:tt)*) => {}; () => {}; ($ident_1:ident) => {}; ($ident_1:ident $ident_2:ident) => {}; /* ... */ ($ident_1:ident $ident_2:ident /* ... */ $ident_m_minus_2:ident) => {}; ($ident_1:ident $ident_2:ident /* ... */ $ident_m_minus_2:ident $ident_m_minus_1:ident) => {}; // Non-Halting Input // P(a) (a $d_1:tt $d_2:tt /* ... */ $d_m_minus_1:tt $($tail:tt)*) => { my_tag_system!($($tail)* p_a) }; // P(b) (b $d_1:tt $d_2:tt /* ... */ $d_m_minus_1:tt $($tail:tt)*) => { my_tag_system!($($tail)* p_b) }; // ... } # # fn main() {} ``` -------------------------------- ### Matching various visibility qualifiers with `vis` Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Demonstrates how the `vis` fragment specifier can match different visibility qualifiers, including an empty one. ```rust macro_rules! visibilities { // ∨~~Note this comma, since we cannot repeat a `vis` fragment on its own ($($vis:vis,)*) => (); } visibilities! { , // no vis is fine, due to the implicit `?` pub, pub(crate), pub(in super), pub(in some_path), } ``` -------------------------------- ### Observe Tokens with log_syntax! Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/debugging.md Utilize log_syntax! to output all tokens passed to the compiler. This offers more targeted debugging than trace_macros!. Requires a nightly compiler with the 'log_syntax' feature enabled. ```rust # // This code block marked `ignore` because mdbook can't handle `#![feature(...)]`. #![feature(log_syntax)] macro_rules! sing { () => {}; ($tt:tt $($rest:tt)*) => {log_syntax!($tt); sing!($($rest)*);}; } sing! { ^ < @ < . @ * '\x08' '{' '"' _ # ' ' - @ '$' && / _ % ! ( '\t' @ | = > ; '\x08' '\'' + '$' ? '\x7f' , # '"' ~ | ) '\x07' } # # fn main() {} ``` -------------------------------- ### Matching Attribute Meta Items Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Use the `meta` fragment to match the contents of attributes, including simple paths, paths with `=` and literals, or paths with delimited token trees. ```rust macro_rules! metas { ($($meta:meta)*) => (); } metas! { ASimplePath super::man path = "home" foo(bar) } # fn main() {} ``` -------------------------------- ### Usage of Attribute Procedural Macros Source: https://github.com/veykril/tlborm/blob/main/src/proc-macros/methodical/attr.md Demonstrates how to apply a custom attribute macro to functions. It shows usage with and without arguments passed to the attribute. ```rust use tlborm_proc::tlborm_attribute; #[tlborm_attribute] fn foo() {} #[tlborm_attribute(attributes are pretty handsome)] fn bar() {} ``` -------------------------------- ### Rust Macro for Array Initialization with Push-down Accumulation Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/push-down-acc.md This macro initializes an array by accumulating elements using push-down accumulation. It requires the `accum!` macro to handle the step-by-step building of the array content. ```rust macro_rules! init_array { [$e:expr; $n:tt] => { { let e = $e; accum!([$n, e.clone()] -> []) } }; } macro_rules! accum { ([3, $e:expr] -> [$($body:tt)*]) => { accum!([2, $e] -> [$($body)* $e,]) }; ([2, $e:expr] -> [$($body:tt)*]) => { accum!([1, $e] -> [$($body)* $e,]) }; ([1, $e:expr] -> [$($body:tt)*]) => { accum!([0, $e] -> [$($body)* $e,]) }; ([0, $_:expr] -> [$($body:tt)*]) => { [$($body)*] }; } let strings: [String; 3] = init_array![String::from("hi!"); 3]; # assert_eq!(format!("{:?}", strings), "[\"hi!\", \"hi!\", \"hi!\"]"); ``` -------------------------------- ### AST Visualization After Expansion Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md The AST after the `four!()` syntax extension has been expanded to `1 + 3`. Note the structural replacement. ```text ┌─────────────┐ │ Let │ │ name: eight │ ┌─────────┐ │ init: ◌ │╶─╴│ BinOp │ └─────────────┘ │ op: Mul │ ┌╴│ lhs: ◌ │ ┌────────┐ │ │ rhs: ◌ │╶┐ ┌─────────┐ │ LitInt │╶┘ └─────────┘ └╴│ BinOp │ │ val: 2 │ │ op: Add │ └────────┘ ┌╴│ lhs: ◌ │ ┌────────┐ │ │ rhs: ◌ │╶┐ ┌────────┐ │ LitInt │╶┘ └─────────┘ └╴│ LitInt │ │ val: 1 │ │ val: 3 │ └────────┘ └────────┘ ``` -------------------------------- ### Basic macro_rules! structure Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-methodical.md Defines the general structure of a `macro_rules!` macro with multiple rules. Semicolons after rules are optional. ```rust macro_rules! $name { $rule0 ; $rule1 ; // … $ruleN ; } ``` -------------------------------- ### Shadowing Macro Definitions Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/scoping.md Demonstrates that defining macro_rules! macros multiple times is allowed, with the most recent declaration shadowing previous ones unless out of scope. ```rust macro_rules! X { (1) => {}; } X!(1); macro_rules! X { (2) => {}; } // X!(1); // Error: no rule matches `1` X!(2); mod a { macro_rules! X { (3) => {}; } // X!(2); // Error: no rule matches `2` X!(3); } // X!(3); // Error: no rule matches `3` X!(2); ``` -------------------------------- ### Module Declaration Order for Macros Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/scoping.md Illustrates the importance of declaration order when using #[macro_use] on modules, where the module defining macros must precede the module using them. ```rust #[macro_use] mod some_mod_that_defines_macros; mod some_mod_that_uses_those_macros; ``` -------------------------------- ### Matching Pattern Parameters Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/fragment-specifiers.md Use `pat_param` to match patterns while allowing `|` tokens to follow, effectively providing the pre-2021 edition behavior for `pat`. ```rust macro_rules! patterns { ($( $( $pat:pat_param )|+ )*) => (); } patterns! { "literal" _ 0..5 ref mut PatternsAreNice 0 | 1 | 2 | 3 } # fn main() {} ``` -------------------------------- ### Separate Macros Before Unification Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/internal-rules.md Shows two separate macro_rules! macros, as_expr and foo, before they are unified using internal rules. ```rust #[macro_export] macro_rules! as_expr { ($e:expr) => {$e} } #[macro_export] macro_rules! foo { ($($tts:tt)*) => { as_expr!($($tts)*) }; } # # fn main() { # assert_eq!(foo!(42), 42); # } ``` -------------------------------- ### Token Capture vs. AST Node Substitution Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/metavar-and-expansion.md Compares macro behavior when capturing tokens versus when substituting an expression, showing how AST nodes become 'un-destructible'. ```rust macro_rules! capture_then_match_tokens { ($e:expr) => {match_tokens!($e)}; } macro_rules! match_tokens { ($a:tt + $b:tt) => {"got an addition"}; (($i:ident)) => {"got an identifier"}; ($($other:tt)*) => {"got something else"}; } fn main() { println!("{}\n{}\n{}\n", match_tokens!((caravan)), match_tokens!(3 + 6), match_tokens!(5)); println!("{}\n{}\n{}", capture_then_match_tokens!((caravan)), capture_then_match_tokens!(3 + 6), capture_then_match_tokens!(5)); } ``` -------------------------------- ### Macro Defining Method with Explicit `self` Parameter (Works) Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/identifiers.md Demonstrates a working macro that correctly handles `self` by explicitly accepting it as an identifier parameter. This approach bypasses the keyword/identifier ambiguity by treating `self` as a regular macro argument. ```rust macro_rules! double_method { ($self_:ident, $body:expr) => { fn double(mut $self_) -> Dummy { $body } }; } struct Dummy(i32); impl Dummy { double_method! {self, { self.0 *= 2; self }} } # # fn main() { # println!("{:?}", Dummy(4).double().0); # } ``` -------------------------------- ### Defining a Recursive Sequence Macro (Initial Attempt) Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This snippet shows an initial attempt to define a macro for recurrence relations. It was later found to have syntax issues with the '...' token. ```rust macro_rules! recurrence { ( a[n]: $sty:ty = $($inits:expr),+ ... $recur:expr ) => { // ^~~ changed /* ... */ # // Cheat :D # (vec![0u64, 1, 2, 3, 5, 8, 13, 21, 34]).into_iter() }; } fn main() { let fib = recurrence![a[n]: u64 = 0, 1, 2, 3, 5, 8, 13, 21, 34]; for e in fib.take(10) { println!("{}", e) } } ``` -------------------------------- ### Scoping of Functions and Macros Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/minutiae/scoping.md Demonstrates that the same scoping rules that apply to macros also apply to functions, with the exception of #[macro_use]. ```rust macro_rules! X { () => { Y!() }; } fn a() { macro_rules! Y { () => {"Hi!"} } assert_eq!(X!(), "Hi!"); { assert_eq!(X!(), "Hi!"); macro_rules! Y { () => {"Bye!"} } assert_eq!(X!(), "Bye!"); } assert_eq!(X!(), "Hi!"); } fn b() { macro_rules! Y { () => {"One more"} } assert_eq!(X!(), "One more"); } # # fn main() { # a(); # b(); # } ``` -------------------------------- ### Forwarding Arbitrary Arguments with Callbacks Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/patterns/callbacks.md Shows how to use `tt` repetition within a callback macro to forward arbitrary arguments to another macro. This allows for more flexible communication between macro expansions. ```rust macro_rules! callback { ($callback:ident( $($args:tt)* )) => { $callback!( $($args)* ) }; } fn main() { callback!(callback(println("Yes, this *was* unnecessary."))); } ``` -------------------------------- ### Define macro_rules! with expression capture Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros-practical.md This macro captures an expression and wraps it in a block where a variable 'a' is defined. It demonstrates the initial syntax context for 'a'. ```rust macro_rules! using_a { ( $e:expr ) => { { let a = 42; $e } } } let four = using_a!(a / 10); ``` -------------------------------- ### Intermediate Expansion Step Source: https://github.com/veykril/tlborm/blob/main/src/syntax-extensions/expansion.md Shows the code after the first expansion of `four!()` to `1 + three!()`, before `three!()` is further expanded. ```rust let x = 1 + three!(); ``` -------------------------------- ### Hygiene Difference: macro_rules! vs macro Source: https://github.com/veykril/tlborm/blob/main/src/decl-macros/macros2.md Demonstrates the hygiene difference between `macro_rules!` and `macro`. The `macro_rules!` version compiles, while the `macro` version fails due to stricter definition-site hygiene, preventing identifier leakage. ```rust # // This code block marked `ignore` because mdbook can't handle `#![feature(...)]`. #![feature(decl_macro)] // try uncommenting the following line, and commenting out the line right after macro_rules! foo { // macro foo { ($name: ident) => { pub struct $name; impl $name { pub fn new() -> $name { $name } } } } foo!(Foo); fn main() { // this fails with a `macro`, but succeeds with a `macro_rules` let foo = Foo::new(); } ```