husk-scheme-3.5.6: 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:

  1. Walk the input code looking for a macro definition or macro call.
  2. 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
  3. If a rule matches, 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.





:: Env

Environment of the code being expanded

-> Bool

True if the macro was defined within another macro

-> LispVal

Code to expand

-> IOThrowsError LispVal

Expanded code

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



:: Env

Current environment for the AST

-> LispVal

AST to search

-> IOThrowsError LispVal

Transformed AST containing an expanded macro if found

Examines the input AST to see if it is a macro call. If a macro call is found, the code is expanded. Otherwise the input is returned unchanged.



:: 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