Adding a New Prelude Macro

Prelude macros are defined in prelude.lisp and loaded by the Expander before user code. They are the preferred way to add new syntactic forms that can be expressed in terms of existing forms.

Files to modify

1. prelude.lisp — Add the defmacro definition.

That's it. No Rust changes needed.

Step by step

Step 1: Add the macro to prelude.lisp (at the project root):

## my-form - description of what it does
## (my-form arg body...) => expansion
(defmacro my-form (arg & body)
   `(let [tmp ,arg]
      (if tmp (begin ,;body) nil)))

How it works

1. prelude.lisp is embedded into the binary via include_str!("../../../prelude.lisp") in src/syntax/expand/mod.rs.

2. Expander::load_prelude() parses and expands the prelude, which registers each defmacro in the Expander's macro table.

3. When user code contains (my-form ...), the Expander recognizes it as a macro call, evaluates the macro body in the VM, and splices the result back as Syntax.

4. The expanded code is then analyzed normally by the HIR analyzer.

Macro syntax reference

(defmacro name (param1 param2 & rest-params)
   template)

Existing prelude macros

MacroExpansion
defn(def name (fn params body...))
letAlias for let (retained for Scheme familiarity)
->Thread-first
->>Thread-last
when(if test (begin body...) nil)
unless(if test nil (begin body...))
try/catchFiber-based error handling
protectReturns [success? value] array
deferCleanup after body
withResource management (acquire/release)
yieldDelegate to sub-generator

When to use a macro vs. a special form

Use a prelude macro when:

Use a special form (Recipe 4) when:


See also