Procedural macro

 What a procedural macro is (in one sentence)

A procedural macro is Rust code that runs at compile time and generates Rust code by programmatically transforming syntax trees.

Normal Rust code runs at runtime

Procedural macros run while the compiler is compiling

How to use procedural macro

  1. Define the macro
#[proc_macro_attribute]
pub fn my_macro(attr: TokenStream, item: TokenStream) -> TokenStream
  • The function name (my_macro) is the macro’s identifier.
  • To use it, you write:
#[my_macro]

TokenStream

A TokenStream is:

A sequence of Rust tokens, not text, not AST.

Tokens are things like:

  • identifiers: vm_entry, fn, main
  • punctuation: #, (, ), {, }
  • literals: “hello”, 123
  • keywords: fn, struct, impl
What is a Rust token?
A token is a smallest meaningful unit of Rust syntax.

Examples of tokens:
• keywords: fn, struct, pub
• identifiers: main, x, WomirConfig
• punctuation: ( ) { } , ; #
• operators: + -> =
• literals: 123, "hello"

Spaces, newlines, indentation are NOT tokens

AST

AST = Abstract Syntax Tree

  • Tree → hierarchical structure (nodes with children)
  • Syntax → structure of the language
  • Abstract → details like whitespace, comments, formatting are removed

So:

An AST is a structured, tree-shaped representation of your code that captures its meaningful syntax, not how it was typed.

From text → tokens → AST

Rust compilation (simplified):

source code (text)
   ↓
tokens
   ↓
AST
   ↓
name resolution, type checking, MIR, LLVM, …
Example: code vs AST

Take this code:

fn add(a: i32, b: i32) -> i32 {
    a + b
}
As text

Just characters.

As tokens

Something like:

fn | add | ( | a | : | i32 | , | b | : | i32 | ) | -> | i32 | { | a | + | b | }


As AST (conceptually)
Function
├─ name: add
├─ params
│  ├─ a: i32
│  └─ b: i32
├─ return_type: i32
└─ body
   └─ BinaryExpr(+)
      ├─ Ident(a)
      └─ Ident(b)

What is syn used for in macros?

syn is used to parse a TokenStream into a Rust AST so you can inspect code structurally instead of manually reading tokens.

Most commonly used syn things

Parsing

syn::parse::<T>(tokens)
syn::parse_macro_input!(tokens as T)

Leave a Reply

Your email address will not be published. Required fields are marked *