This module contains code for hygienic macros.
Hygienic macros are implemented using the algorithm from the paper Macros That Work by William Clinger and Jonathan Rees. During transformation, the following components are considered:
- Pattern (part of a rule that matches input)
- Transform (what the macro expands into)
- Literal Identifiers (from the macro definition)
- Input (the actual code in the user's program)
- Environments of macro definition and macro use
At a high level, macro transformation is broken down into the following steps:
- Walk the input code looking for a macro definition or macro call. If a macro call is found -
- Search for a rule that matches the input. During this process, any pattern variables in the input are loaded into a temporary environment
- If a rule matches,
- Transcribe the rule's template by walking the template, inserting pattern variables and renaming free identifiers as needed.
- Walk the expanded code, checking for each of the cases from Macros That Work. If a case is found (such as a macro call or procedure abstraction) then the appropriate handler will be called to deal with it.
macroEval Search for macros in the AST, and transform any that are found.
Parent environment containing the let*-syntax expression
Environment of the let*-syntax body
|-> Maybe Env|
Environment of renamed variables, if applicable
True if the macro was defined inside another macro
List containing syntax-rule definitions
|-> IOThrowsError LispVal|
A dummy value, unless an error is thrown
Helper function to load macros from a let*-syntax expression