husk-scheme- R5RS Scheme interpreter, compiler, and library.

Safe HaskellSafe-Infered



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:

0) Walk the input code looking for a macro definition or macro call. If a macro call is found - 1) Search for a rule that matches the input. During this process, any pattern variables in the input are loaded into a temporary environment 2) If a rule matches, 3) Transcribe the rule's template by walking the template, inserting pattern variables and renaming free identifiers as needed. 4) 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 :: Env -> LispVal -> IOThrowsError LispValSource

macroEval Search for macro's in the AST, and transform any that are found.



:: Env

Parent environment containing the let*-syntax expression

-> Env

Environment of the let*-syntax body

-> Maybe Env

Environment of renamed variables, if applicable

-> Bool

True if the macro was defined inside another macro

-> [LispVal]

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

expand :: Env -> Bool -> LispVal -> IOThrowsError LispValSource

This function walks the given block of code using the macro expansion algorithm, recursively expanding macro calls as they are encountered.

It is essentially a wrapper for the function walkExpanded which is internal to this module.