Copyright | Justin Ethier |
---|---|
License | MIT (see LICENSE in the distribution) |
Maintainer | github.com/justinethier |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell98 |
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.
- expand :: Env -> Bool -> LispVal -> (LispVal -> LispVal -> [LispVal] -> IOThrowsError LispVal) -> IOThrowsError LispVal
- macroEval :: Env -> LispVal -> (LispVal -> LispVal -> [LispVal] -> IOThrowsError LispVal) -> IOThrowsError LispVal
- loadMacros :: Env -> Env -> Maybe Env -> Bool -> [LispVal] -> IOThrowsError LispVal
- getDivertedVars :: Env -> IOThrowsError [LispVal]
Documentation
:: Env | Environment of the code being expanded |
-> Bool | True if the macro was defined within another macro |
-> LispVal | Code to expand |
-> (LispVal -> LispVal -> [LispVal] -> IOThrowsError LispVal) | Apply func |
-> 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 |
-> (LispVal -> LispVal -> [LispVal] -> IOThrowsError LispVal) | Eval func |
-> 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
getDivertedVars :: Env -> IOThrowsError [LispVal] Source #
Get a list of variables that the macro hygiene subsystem diverted back into the calling environment.
This is a specialized function that is only mean to be used by the husk compiler.