Macro definitions and the environment (MacroEnv) they're registered in, shared by the macro expander (expand.nim) — parameter shapes for &optional/&rest/&body/&key, gensym/hygiene id allocation, and the import-cycle tracking used while inlining .nfl files.
Types
MacroDef = object name*: string params*: seq[Syntax] optParams*: seq[MacroOptParam] restParam*: string bodyParam*: string keyParams*: seq[MacroKeyParam] body*: seq[Syntax] span*: Span
- A single macro's parameter shape and body.
MacroEnv = ref object macros*: Table[string, MacroDef] macroProcs*: Table[string, MacroDef] ## `defmacro-proc` definitions (#70) macroProcDepth*: int ## current `defmacro-proc` call nesting — guards ## against unbounded evaluator recursion, since ## `maxExpansionDepth` only counts expansions gensymCounter*: int includedFiles*: HashSet[string] ## resolved paths of .nfl files already ## inlined (#10) — a second `(import ## ...)` of the same file is a no-op so ## diamond imports don't duplicate decls includingStack*: seq[string] ## resolved paths currently being ## inlined, in inclusion order — used to ## detect and report circular imports
- Expansion-time state: registered macros, gensym counter, and import-cycle tracking.
MacroKeyParam = object keyword*: string local*: string default*: Option[Syntax]
- A &key macro parameter.
MacroOptParam = object name*: string default*: Option[Syntax]
- An &optional macro parameter.
Consts
macroReservedNames = ["quote", "quasiquote", "if", "block", "let", "break-from", "symbol?", "list?", "vector?", "string?", "int?", "float?", "bool?", "nil?", "first", "rest", "cons", "list", "append", "syntax->datum", "datum->syntax", "gensym", "macro-error", "+", "-", "*", "/", "div", "mod", "<", "<=", ">", ">=", "=", "/=", "not", "nth", "length", "reverse", "member", "symbol->string", "string->symbol", "string-append"]
Procs
proc defineMacro(env: MacroEnv; def: MacroDef) {....raises: [CompilerError], tags: [], forbids: [].}
- Registers def in env; raises CompilerError if a macro with the same name is already defined.
proc defineMacroProc(env: MacroEnv; def: MacroDef) {....raises: [CompilerError], tags: [], forbids: [].}
- Registers def in env; raises CompilerError if a macro-proc with the same name is already defined, or if def.name shadows a macro-time special form or builtin (macroReservedNames) — both would otherwise be silently unreachable behind the reserved name's own dispatch.
proc getMacroProc(env: MacroEnv; name: string): MacroDef {....raises: [KeyError], tags: [], forbids: [].}
proc hasMacroProc(env: MacroEnv; name: string): bool {....raises: [], tags: [], forbids: [].}
- True if a defmacro-proc named name is registered in env.
proc newHygienicId(env: MacroEnv): int {....raises: [], tags: [], forbids: [].}
- Allocates a fresh hygieneId for the automatic template-hygiene rename pass (#11) — shares gensymCounter with explicit gensym calls so both mechanisms draw from the same id space; backend.nim's hygienicSymbols table treats an id as opaque regardless of which produced it.
proc newMacroEnv(): MacroEnv {....raises: [], tags: [], forbids: [].}
- Creates an empty MacroEnv ready for expansion.