Documentation
¶
Index ¶
- Constants
- Variables
- func AllFeatures() []string
- func CompileSyntaxRules(ctx context.Context, env *environment.EnvironmentFrame, ...) (*machine.MachineClosure, error)
- func CopyLibraryBindingsToEnv(lib *CompiledLibrary, bindings map[string]string, ...) error
- func CopyLibraryBindingsToEnvAtPhase(lib *CompiledLibrary, bindings map[string]string, ...) error
- func IsFeatureSupported(feature string) bool
- func LookupPhaseBinding[T any](phaseEnv *environment.EnvironmentFrame, sym *values.Symbol, ...) T
- func NewERCompareClosure(useEnv *environment.EnvironmentFrame) *machine.ForeignClosure
- func NewERRenameClosure(defExpandEnv *environment.EnvironmentFrame, introScope *syntax.Scope) *machine.ForeignClosure
- func RegisterAllPhaseHandlers(env *environment.EnvironmentFrame) error
- func RegisterPhaseBindings[F any](env *environment.EnvironmentFrame, ...) error
- func RegisterPrimitiveExpanders(env *environment.EnvironmentFrame) error
- func RegisterSyntaxCompilers(env *environment.EnvironmentFrame) error
- func ResolveAndInstallImportSet(ctx context.Context, datum values.Value, env *environment.EnvironmentFrame, ...) error
- func VerifyAllPhaseHandlers() error
- func VerifyCompilers() error
- func VerifyExpanders() error
- type ChainFileResolver
- type CompileTimeCallContext
- type CompileTimeContinuation
- func (p *CompileTimeContinuation) AppendOperations(ops ...machine.Operation)
- func (p *CompileTimeContinuation) CompileBeginForSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileCondExpand(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileDefineForSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileDefineLibrary(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileDefineSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileEvalWhen(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileExport(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileExpression(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileImport(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileInclude(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileIncludeCi(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileMeta(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileQuasisyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileSelfEvaluating(_ CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileSymbol(ctctx CompileTimeCallContext, expr *syntax.SyntaxSymbol) error
- func (p *CompileTimeContinuation) CompileSyntax(_ CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileSyntaxCase(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileUnquote(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileUnquoteSplicing(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileUnsyntax(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileUnsyntaxSplicing(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) CompileValidatedApply(ctctx CompileTimeCallContext, v *validate.ValidatedApply) error
- func (p *CompileTimeContinuation) CompileValidatedBegin(ctctx CompileTimeCallContext, v *validate.ValidatedBegin) error
- func (p *CompileTimeContinuation) CompileValidatedCaseLambda(ctctx CompileTimeCallContext, v *validate.ValidatedCaseLambda) error
- func (p *CompileTimeContinuation) CompileValidatedDefine(ctctx CompileTimeCallContext, v *validate.ValidatedDefine) error
- func (p *CompileTimeContinuation) CompileValidatedDefineFn(ctctx CompileTimeCallContext, v *validate.ValidatedDefine) error
- func (p *CompileTimeContinuation) CompileValidatedDynamicWind(ctctx CompileTimeCallContext, v *validate.ValidatedDynamicWind) error
- func (p *CompileTimeContinuation) CompileValidatedIf(ctctx CompileTimeCallContext, v *validate.ValidatedIf) error
- func (p *CompileTimeContinuation) CompileValidatedLambda(ctctx CompileTimeCallContext, v *validate.ValidatedLambda) error
- func (p *CompileTimeContinuation) CompileValidatedLet(ctctx CompileTimeCallContext, v *validate.ValidatedLet) error
- func (p *CompileTimeContinuation) CompileValidatedQuasiquote(ctctx CompileTimeCallContext, v *validate.ValidatedQuasiquote) error
- func (p *CompileTimeContinuation) CompileValidatedQuote(_ CompileTimeCallContext, v *validate.ValidatedQuote) error
- func (p *CompileTimeContinuation) CompileValidatedSetBang(ctctx CompileTimeCallContext, v *validate.ValidatedSetBang) error
- func (p *CompileTimeContinuation) CompileValidatedWithContinuationMark(ctctx CompileTimeCallContext, v *validate.ValidatedWithContinuationMark) error
- func (p *CompileTimeContinuation) CompileWithSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
- func (p *CompileTimeContinuation) SetFileResolver(r FileResolver)
- func (p *CompileTimeContinuation) SetInlineThreshold(n int)
- func (p *CompileTimeContinuation) SetLibraryCallback(cb func(*CompiledLibrary))
- type CompiledLibrary
- type CompilerFunc
- type ERMacroTransformer
- type EmbedFileResolver
- type ExpanderContext
- func (p *ExpanderContext) Env() *environment.EnvironmentFrame
- func (p *ExpanderContext) Expand(stx syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderContext) ExpandOnce(stx syntax.SyntaxValue) (syntax.SyntaxValue, bool, error)
- func (p *ExpanderContext) IntroductionScope() *syntax.Scope
- func (p *ExpanderContext) SetIntroductionScope(scope *syntax.Scope)
- func (p *ExpanderContext) SetUseSiteScope(scope *syntax.Scope)
- func (p *ExpanderContext) UseSiteScope() *syntax.Scope
- type ExpanderTimeContinuation
- func (p *ExpanderTimeContinuation) Context() context.Context
- func (p *ExpanderTimeContinuation) ExpandBodyWithDefineSyntax(forms []syntax.SyntaxValue) ([]syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandExpression(expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandOnce(expr syntax.SyntaxValue) (syntax.SyntaxValue, bool, error)
- func (p *ExpanderTimeContinuation) ExpandPrimitiveForm(primName string, sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandSelfEvaluating(expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandSymbol(expr *syntax.SyntaxSymbol) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandSyntaxArgumentList(args syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandSyntaxExpression(sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
- func (p *ExpanderTimeContinuation) ExpandSyntaxOrProcedureCall(car syntax.SyntaxValue, cdr syntax.SyntaxValue) (syntax.SyntaxValue, error)
- type FSFileResolver
- type FeatureRequirement
- func NewAndRequirement(reqs ...FeatureRequirement) FeatureRequirement
- func NewElseRequirement() FeatureRequirement
- func NewFeatureIdentifier(name string) FeatureRequirement
- func NewLibraryRequirement(name LibraryName) FeatureRequirement
- func NewNotRequirement(req FeatureRequirement) FeatureRequirement
- func NewOrRequirement(reqs ...FeatureRequirement) FeatureRequirement
- type FileResolver
- type ImportSet
- type LibraryEnumerator
- type LibraryImportEvent
- type LibraryImportObserver
- type LibraryName
- func DiscoverAvailableLibraries(resolver FileResolver, reg *LibraryRegistry) ([]LibraryName, error)
- func FilePathToLibraryName(path string) (LibraryName, error)
- func NewLibraryName(parts ...string) LibraryName
- func ParseLibraryNameFromDatum(ctx context.Context, expr values.Value) (LibraryName, error)
- type LibraryRegistry
- func (p *LibraryRegistry) All() []*CompiledLibrary
- func (p *LibraryRegistry) AllNames() []LibraryName
- func (p *LibraryRegistry) FinishLoading(name LibraryName)
- func (p *LibraryRegistry) GetSearchPaths() []string
- func (p *LibraryRegistry) ImportObserver() LibraryImportObserver
- func (p *LibraryRegistry) IsLoading(name LibraryName) bool
- func (p *LibraryRegistry) Lookup(name LibraryName) *CompiledLibrary
- func (p *LibraryRegistry) PrependSearchPath(path string)
- func (p *LibraryRegistry) Register(lib *CompiledLibrary) error
- func (p *LibraryRegistry) SetImportObserver(obs LibraryImportObserver)
- func (p *LibraryRegistry) SetSearchPaths(paths []string)
- func (p *LibraryRegistry) StartLoading(name LibraryName)
- type OSFileResolver
- type PhaseEntry
- type PrimitiveExpander
- func (p *PrimitiveExpander) EqualTo(other values.Value) bool
- func (p *PrimitiveExpander) Expand(etc *ExpanderTimeContinuation, sym *syntax.SyntaxSymbol, ...) (syntax.SyntaxValue, error)
- func (p *PrimitiveExpander) IsVoid() bool
- func (p *PrimitiveExpander) Name() string
- func (p *PrimitiveExpander) SchemeString() string
- type PrimitiveExpanderFunc
- type ResolvedImportSet
- type SyntaxCompiler
- type SyntaxCompilerFunc
Constants ¶
const DefaultInlineThreshold = 5
DefaultInlineThreshold is the default maximum body length for procedure inlining. A lambda body with more expressions than this is not inlined.
const ImplementationName = "wile"
ImplementationName is the name of this Scheme implementation.
const (
// SchemeIncludePathEnv is the environment variable name for the Scheme include path
SchemeIncludePathEnv = "SCHEME_INCLUDE_PATH"
)
Variables ¶
var DefaultLibraryPaths = []string{
".",
"./stdlib/lib",
}
DefaultLibraryPaths are the default directories to search for libraries.
Functions ¶
func AllFeatures ¶
func AllFeatures() []string
AllFeatures returns all supported feature identifiers.
func CompileSyntaxRules ¶
func CompileSyntaxRules(ctx context.Context, env *environment.EnvironmentFrame, syntaxRulesForm syntax.SyntaxValue, libraryScope *syntax.Scope) (*machine.MachineClosure, error)
CompileSyntaxRules compiles a syntax-rules form into a transformer procedure.
R7RS Forms:
(syntax-rules (literal ...) (pattern template) ...) (syntax-rules <ellipsis> (literal ...) (pattern template) ...) ; custom ellipsis
The compilation process:
- Parse optional custom ellipsis identifier
- Parse the literals list - these symbols are matched literally, not as variables
- For each clause, identify pattern variables (symbols not in literals list)
- Compile each pattern to bytecode (see match/syntax_compiler.go)
- Create a machine.MachineClosure that, when invoked: - Tries each pattern in order against the input form - On first match, expands the template with captured bindings - Adds an "intro scope" to the expansion for hygiene
The returned closure is stored in the environment with BindingTypeSyntax, allowing the expander to recognize it as a macro transformer.
func CopyLibraryBindingsToEnv ¶
func CopyLibraryBindingsToEnv(lib *CompiledLibrary, bindings map[string]string, targetEnv *environment.EnvironmentFrame) error
CopyLibraryBindingsToEnv copies exported bindings from a library to an environment. bindings is the map from localName -> externalName produced by ApplyToExports. Both runtime and syntax bindings are copied. This is a convenience wrapper that imports to phase 0 (runtime).
func CopyLibraryBindingsToEnvAtPhase ¶
func CopyLibraryBindingsToEnvAtPhase(lib *CompiledLibrary, bindings map[string]string, targetEnv *environment.EnvironmentFrame, targetPhase int) error
func IsFeatureSupported ¶
IsFeatureSupported checks if a feature identifier is supported.
func LookupPhaseBinding ¶
func LookupPhaseBinding[T any]( phaseEnv *environment.EnvironmentFrame, sym *values.Symbol, scopes []*syntax.Scope, ) T
LookupPhaseBinding looks up a binding by symbol in the target phase environment. Returns the value cast to type T if found, or the zero value if not found or if the value is not of type T.
This function handles hygiene by using scoped lookup - it will only match bindings whose scopes are a subset of the symbol's scopes.
func NewERCompareClosure ¶
func NewERCompareClosure(useEnv *environment.EnvironmentFrame) *machine.ForeignClosure
NewERCompareClosure creates the `compare` closure for an ER macro invocation. useEnv is the use-site environment for resolving identifiers. The closure accepts two identifier arguments and returns #t if both resolve to the same binding (pointer equality) or both are unbound with the same name.
func NewERRenameClosure ¶
func NewERRenameClosure( defExpandEnv *environment.EnvironmentFrame, introScope *syntax.Scope, ) *machine.ForeignClosure
NewERRenameClosure creates the `rename` closure for an ER macro invocation. defExpandEnv is the definition-site expand environment. introScope is a fresh scope unique to this macro invocation, used to ensure that renamed symbols not found in the definition-site env (e.g., temporary names like 'tmp') get a unique identity that prevents variable capture. The returned closure accepts a single symbol argument and returns a SyntaxSymbol that resolves to the definition-site binding. Results are cached per symbol name so that (eq? (rename 'x) (rename 'x)) is #t.
func RegisterAllPhaseHandlers ¶ added in v1.10.7
func RegisterAllPhaseHandlers(env *environment.EnvironmentFrame) error
RegisterAllPhaseHandlers registers both syntax compilers (compile phase) and primitive expanders (expand phase) in the correct order. Use this instead of calling RegisterSyntaxCompilers and RegisterPrimitiveExpanders separately at engine/bootstrap/test init sites.
func RegisterPhaseBindings ¶
func RegisterPhaseBindings[F any]( env *environment.EnvironmentFrame, phaseEnv func() *environment.EnvironmentFrame, entries []PhaseEntry[F], wrapper func(name string, fn F) values.Value, ) error
RegisterPhaseBindings binds all entries in the target phase environment. This is a generic helper for registering primitives in expand or compile phases.
Parameters:
- env: The top-level environment
- phaseEnv: Accessor for the target phase (e.g., env.Expand or env.Compile)
- entries: Slice of (name, function) pairs to register
- wrapper: Creates the values.Value wrapper from name and function
func RegisterPrimitiveExpanders ¶
func RegisterPrimitiveExpanders(env *environment.EnvironmentFrame) error
func RegisterSyntaxCompilers ¶
func RegisterSyntaxCompilers(env *environment.EnvironmentFrame) error
RegisterSyntaxCompilers binds all syntax compilers in the compile-time environment (env.Compile()). These bindings serve two purposes:
- Library export/import: findLibraryBinding in library_bindings.go searches the compile environment to locate syntax compilers when exporting or importing forms like syntax-case, define-syntax, etc.
- Scope-aware lookup via LookupSyntaxCompiler for hygiene resolution.
Compilation dispatch itself goes through the forms registry (register.go), not through these bindings. Both paths are populated from syntaxCompilerEntries to stay in sync.
The syntax compilers are bound with BindingTypePrimitive to distinguish them from syntax transformers (BindingTypeSyntax) and regular variables.
func ResolveAndInstallImportSet ¶
func ResolveAndInstallImportSet(ctx context.Context, datum values.Value, env *environment.EnvironmentFrame, phase int, evaluator machine.MacroEvaluator) error
ResolveAndInstallImportSet resolves an import set and installs bindings into env at the appropriate phase. Used for top-level imports (both expander and compiler). Library-internal imports share the resolution step (resolveImportSet) but use copyLibraryBindingsDirect for installation.
func VerifyAllPhaseHandlers ¶ added in v1.10.7
func VerifyAllPhaseHandlers() error
VerifyAllPhaseHandlers cross-checks all three phase registries: form validators (internal/forms), compilers (Tier 1 + Tier 2), and primitive expanders. Returns the first inconsistency found, or nil.
Call from tests only — not on the production init path.
func VerifyCompilers ¶
func VerifyCompilers() error
VerifyCompilers checks that every form registered in the forms package has a corresponding compiler — either in the registry (Tier 2) or in the type switch (Tier 1). Returns an error listing any gaps.
func VerifyExpanders ¶ added in v1.10.7
func VerifyExpanders() error
VerifyExpanders checks that every Tier 2 syntax compiler entry has a corresponding primitive expander entry. A Tier 2 form without an expander is silently treated as a procedure call during expansion — the most dangerous form of registration drift.
Types ¶
type ChainFileResolver ¶
type ChainFileResolver struct {
// contains filtered or unexported fields
}
ChainFileResolver tries multiple resolvers in order, falling through to the next on ErrFileNotFound. Non-file-not-found errors (security denials, I/O errors) propagate immediately.
func NewChainFileResolver ¶
func NewChainFileResolver(resolvers []FileResolver) *ChainFileResolver
NewChainFileResolver creates a resolver that tries each resolver in order. Panics if resolvers is empty.
func (*ChainFileResolver) EnumerateLibraries ¶
func (p *ChainFileResolver) EnumerateLibraries() ([]LibraryName, error)
EnumerateLibraries unions library enumerations from all child resolvers that implement LibraryEnumerator. First resolver wins on duplicate keys, matching the resolution priority order. Errors from child resolvers propagate immediately, matching ChainFileResolver.ResolveAndOpen behavior.
func (*ChainFileResolver) ResolveAndOpen ¶
type CompileTimeCallContext ¶
type CompileTimeCallContext struct {
// contains filtered or unexported fields
}
CompileTimeCallContext carries contextual information through the compilation process. It tracks whether an expression is in tail position, which controls whether the compiler emits SaveContinuation (non-tail) or reuses the current frame (tail).
This structure is passed by value (not pointer) through the compiler, allowing each compilation step to create modified copies without affecting the caller's context.
Tail Call Optimization ¶
Tail call optimization (Steele 1977, R7RS §3.5): tail calls reuse the caller's continuation frame instead of allocating a new one, making recursive procedures in tail position run in constant stack space. See BIBLIOGRAPHY.md "Tail Call Optimization".
The inTail flag tracks whether an expression is in tail position. An expression is in tail position if its value will be the final result of the enclosing procedure. When inTail is true, the compiler can generate a tail call that reuses the current stack frame instead of creating a new one, preventing stack overflow in recursive procedures.
Per R7RS Section 3.5, these positions are tail positions:
- The body of a lambda expression
- The last expression in a begin sequence (if the begin is in tail position)
- The consequent and alternative of an if expression (if the if is in tail position)
- The body of a let/let*/letrec (if the let is in tail position)
These are NOT tail positions (use NotInTail()):
- Function arguments: (f (g x)) - the call to g is not in tail position
- Condition of if: (if (pred x) ...) - pred is not in tail position
- Definitions: (define x (expr)) - expr is not in tail position
- Non-final expressions in begin: (begin (a) (b) (c)) - only c is in tail position
func NewCompileTimeCallContext ¶
func NewCompileTimeCallContext(ctx context.Context, inTail bool) CompileTimeCallContext
NewCompileTimeCallContext creates a new compile-time context. Parameters:
- inTail: true if compiling an expression in tail position
func (CompileTimeCallContext) Context ¶
func (p CompileTimeCallContext) Context() context.Context
Context returns the context associated with this compile-time call context.
func (CompileTimeCallContext) NotInTail ¶
func (p CompileTimeCallContext) NotInTail() CompileTimeCallContext
NotInTail returns a copy of the context with inTail set to false. Use this when compiling sub-expressions that are not in tail position:
- Function arguments
- Condition expressions in if
- Initial values in define/let bindings
- Non-final expressions in begin
Example:
// Compiling (f (g x)) - the call to g is not in tail position err := p.CompileExpression(ctctx.NotInTail(), argExpr)
type CompileTimeContinuation ¶
type CompileTimeContinuation struct {
// contains filtered or unexported fields
}
CompileTimeContinuation is a continuation used during the compilation phase
func NewCompileTimeContinuation ¶
func NewCompileTimeContinuation(tpl *machine.NativeTemplate, env *environment.EnvironmentFrame, evaluator machine.MacroEvaluator) *CompileTimeContinuation
NewCompileTimeContinuation creates a new CompileTimeContinuation. The file resolver defaults to the one stored on the Namespace. If none is set, falls back to a fresh OSFileResolver.
func (*CompileTimeContinuation) AppendOperations ¶
func (p *CompileTimeContinuation) AppendOperations(ops ...machine.Operation)
AppendOperations appends operations tagged with the current source from the source stack. Routes through the integer-dispatch code[] path: Wave 1-3 operations become direct instructions, everything else goes via machine.OpComplex to the sideTable.
func (*CompileTimeContinuation) CompileBeginForSyntax ¶
func (p *CompileTimeContinuation) CompileBeginForSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileBeginForSyntax handles (begin-for-syntax expr ...).
Evaluates a sequence of expressions at compile time in the expand phase environment. Used for setting up compile-time state (hash tables, registries) that macros can access. No runtime effect — used for side effects only.
func (*CompileTimeContinuation) CompileCondExpand ¶
func (p *CompileTimeContinuation) CompileCondExpand(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileCondExpand compiles a cond-expand expression. cond-expand is evaluated at compile-time and expands to the body of the first clause whose feature requirement is satisfied.
Syntax: (cond-expand <clause> ...) where <clause> is (<feature-requirement> <expression> ...)
Example:
(cond-expand (r7rs (display "R7RS")) (else (display "other")))
func (*CompileTimeContinuation) CompileDefineForSyntax ¶
func (p *CompileTimeContinuation) CompileDefineForSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileDefineForSyntax handles (define-for-syntax name expr) or (define-for-syntax (name args...) body...).
This form defines a binding in the expand phase environment that is available during macro expansion. The expression is compiled and evaluated at compile time, and the result is stored in env.Expand().
Unlike define-syntax (which stores macro transformers), define-for-syntax stores regular values with BindingTypeVariable.
func (*CompileTimeContinuation) CompileDefineLibrary ¶
func (p *CompileTimeContinuation) CompileDefineLibrary(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileDefineLibrary handles (define-library (lib-name) <library-declaration> ...).
R7RS library syntax:
(define-library <library-name> <library-declaration> ...) <library-declaration> = | (export <export-spec> ...) | (import <import-set> ...) | (begin <command-or-definition> ...) | (include <filename> ...) | (include-ci <filename> ...)
This creates an isolated environment for the library, processes declarations in order, and registers the compiled library in the registry.
func (*CompileTimeContinuation) CompileDefineSyntax ¶
func (p *CompileTimeContinuation) CompileDefineSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileDefineSyntax handles (define-syntax keyword transformer-expr).
This is the compile-time handler for R7RS define-syntax. Unlike most definitions, define-syntax is processed entirely at compile time:
- Parse the form: (define-syntax keyword (syntax-rules ...))
- Compile the syntax-rules transformer to a machine.MachineClosure
- Store the closure in the environment with BindingTypeSyntax
- Emit NO runtime operations (the binding is already established)
The BindingTypeSyntax marker is crucial: when the expander encounters a symbol, it checks if that symbol is bound to a syntax transformer. If so, it invokes the transformer closure to expand the macro.
This is how derived expressions like 'let' work: they're defined as macros using define-syntax, and expand to lambda expressions:
(define-syntax let
(syntax-rules ()
((let ((name val) ...) body)
((lambda (name ...) body) val ...))))
Reference: R7RS Section 5.4 (Syntax definitions)
func (*CompileTimeContinuation) CompileEvalWhen ¶
func (p *CompileTimeContinuation) CompileEvalWhen(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileEvalWhen handles (eval-when (phase ...) body ...).
This form controls when code is evaluated based on phase specifiers. Phase names follow Chez Scheme's eval-when (Dybvig, TSPL §12.10):
- expand: evaluate during macro expansion (at compile time)
- compile: evaluate during compilation (currently same as expand)
- run: evaluate at runtime (generate code for normal execution)
Multiple phases can be specified. If both expand and run are specified, the body is evaluated at compile time AND code is generated for runtime.
eval-when is not part of R7RS-small; it is a Wile extension.
Examples:
(eval-when (expand) (display "at expansion time")) (eval-when (run) (display "at runtime")) (eval-when (expand run) (display "both times"))
func (*CompileTimeContinuation) CompileExport ¶
func (p *CompileTimeContinuation) CompileExport(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileExport handles top-level (export <export-spec> ...).
This is only valid within a library definition. At top-level, it's an error.
func (*CompileTimeContinuation) CompileExpression ¶
func (p *CompileTimeContinuation) CompileExpression(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileExpression compiles a general expression. Pushes the expression's source context onto the source stack so that all operations emitted during compilation (including infrastructure ops like Branch and Push) are tagged with the source location.
func (*CompileTimeContinuation) CompileImport ¶
func (p *CompileTimeContinuation) CompileImport(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileImport handles top-level (import <import-set> ...).
This is for top-level imports outside of a library definition. It loads the specified libraries and binds their exports in the current environment.
Supports Racket-style phased imports:
- (import (scheme base)) ; Phase 0 (runtime)
- (import (for-syntax (scheme base))) ; Phase 1 (expand)
- (import (for-template (scheme base))) ; Phase -1
- (import (for-meta 2 (scheme base))) ; Phase 2
func (*CompileTimeContinuation) CompileInclude ¶
func (p *CompileTimeContinuation) CompileInclude(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileInclude compiles an include expression. It reads and compiles all forms from the specified files in order. Each form is expanded and compiled in the current environment.
func (*CompileTimeContinuation) CompileIncludeCi ¶
func (p *CompileTimeContinuation) CompileIncludeCi(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileIncludeCi compiles an include-ci expression.
func (*CompileTimeContinuation) CompileMeta ¶
func (p *CompileTimeContinuation) CompileMeta(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileMeta compiles a meta expression.
func (*CompileTimeContinuation) CompileQuasisyntax ¶
func (p *CompileTimeContinuation) CompileQuasisyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileQuasisyntax compiles the (quasisyntax template) form.
quasisyntax is like quasiquote but for syntax objects. It supports:
- (unsyntax expr) - evaluate expr and splice result at depth 1
- (unsyntax-splicing expr) - evaluate and splice list at depth 1
- nested quasisyntax increases depth
Like quasiquote, unsyntax only evaluates when depth reaches 0. The result is a syntax object, not a raw datum.
func (*CompileTimeContinuation) CompileSelfEvaluating ¶
func (p *CompileTimeContinuation) CompileSelfEvaluating(_ CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileSelfEvaluating compiles a self-evaluating expression (literal).
func (*CompileTimeContinuation) CompileSymbol ¶
func (p *CompileTimeContinuation) CompileSymbol(ctctx CompileTimeCallContext, expr *syntax.SyntaxSymbol) error
CompileSymbol compiles a syntax symbol expression.
func (*CompileTimeContinuation) CompileSyntax ¶
func (p *CompileTimeContinuation) CompileSyntax(_ CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileSyntax compiles the (syntax template) form.
Unlike quote which unwraps syntax to raw values, syntax preserves the syntax structure. When used inside syntax-case, pattern variables in the template are substituted with their matched values.
For templates containing ellipsis (...), runtime expansion is used because ellipsis patterns capture variable-length lists that must be expanded dynamically.
(syntax template) -> syntax-object
func (*CompileTimeContinuation) CompileSyntaxCase ¶
func (p *CompileTimeContinuation) CompileSyntaxCase(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileSyntaxCase compiles the (syntax-case expr (literal ...) clause ...) form.
R6RS syntax-case is a pattern matching form that provides procedural macro facilities. Unlike syntax-rules which expands to templates, syntax-case evaluates arbitrary Scheme code in the body, with pattern variables bound as local variables.
Syntax:
(syntax-case expr (literal ...) (pattern body) (pattern fender body) ...)
Compilation strategy:
- Compile expr to get the input syntax object
- For each clause, generate pattern matching and body code
- Pattern variables are bound as local variables in the body's scope
- If fender exists, it's evaluated as a guard condition
func (*CompileTimeContinuation) CompileUnquote ¶
func (p *CompileTimeContinuation) CompileUnquote(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileUnquote errors - unquote outside of quasiquote
func (*CompileTimeContinuation) CompileUnquoteSplicing ¶
func (p *CompileTimeContinuation) CompileUnquoteSplicing(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileUnquoteSplicing errors - unquote-splicing outside of quasiquote
func (*CompileTimeContinuation) CompileUnsyntax ¶
func (p *CompileTimeContinuation) CompileUnsyntax(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileUnsyntax errors - unsyntax outside of quasisyntax
func (*CompileTimeContinuation) CompileUnsyntaxSplicing ¶
func (p *CompileTimeContinuation) CompileUnsyntaxSplicing(_ CompileTimeCallContext, _ syntax.SyntaxValue) error
CompileUnsyntaxSplicing errors - unsyntax-splicing outside of quasisyntax
func (*CompileTimeContinuation) CompileValidatedApply ¶
func (p *CompileTimeContinuation) CompileValidatedApply(ctctx CompileTimeCallContext, v *validate.ValidatedApply) error
CompileValidatedApply compiles a validated (apply proc arg1 ... args) form.
R7RS §6.10: apply calls proc with the arguments arg1 ... concatenated with the elements of args (the final argument, which must be a list).
Bytecode (non-tail):
SaveContinuation →after <compile proc> PUSH <compile arg1> PUSH ... <compile argN> PUSH <compile finalList> ; value = finalList OpUnpackListToStack ; stack: [proc, arg1, ..., argN, x1, x2, ...] Pull ; value = proc Apply ; calls proc(arg1, ..., argN, x1, x2, ...) after:
Tail position: same without SaveContinuation/patch.
func (*CompileTimeContinuation) CompileValidatedBegin ¶
func (p *CompileTimeContinuation) CompileValidatedBegin(ctctx CompileTimeCallContext, v *validate.ValidatedBegin) error
CompileValidatedBegin compiles a validated (begin expr...) form.
begin (R7RS 4.2.3) sequences expressions for side effects. All expressions are evaluated left-to-right; the value of the last expression becomes the value of the entire begin form.
R7RS §5.3.2: Internal definitions use letrec* semantics - all defined names are visible throughout the body, enabling forward references between defines.
Example: (begin (display "hello") (newline) 42) => 42 (after printing)
func (*CompileTimeContinuation) CompileValidatedCaseLambda ¶
func (p *CompileTimeContinuation) CompileValidatedCaseLambda(ctctx CompileTimeCallContext, v *validate.ValidatedCaseLambda) error
CompileValidatedCaseLambda compiles a validated (case-lambda [clause] ...) form.
case-lambda (R7RS 4.2.9) creates a procedure that dispatches to different implementations based on the number of arguments. For example:
(case-lambda ((x) (* x x)) ; 1 arg: square ((x y) (* x y)) ; 2 args: multiply ((x y . rest) (apply + x y rest))) ; 2+ args: sum all
At runtime, the VM selects the first clause whose arity matches the call.
func (*CompileTimeContinuation) CompileValidatedDefine ¶
func (p *CompileTimeContinuation) CompileValidatedDefine(ctctx CompileTimeCallContext, v *validate.ValidatedDefine) error
CompileValidatedDefine compiles a validated define form.
func (*CompileTimeContinuation) CompileValidatedDefineFn ¶
func (p *CompileTimeContinuation) CompileValidatedDefineFn(ctctx CompileTimeCallContext, v *validate.ValidatedDefine) error
CompileValidatedDefineFn compiles the function shorthand form of define.
Usage: (define (name param ...) body ...)
(define (name param ... . rest) body ...)
This is syntactic sugar equivalent to:
(define name (lambda (param ...) body ...))
Examples:
(define (square x) (* x x)) ; fixed arity (define (sum . args) (apply + args)) ; variadic (all args) (define (sum x . rest) (apply + x rest)) ; variadic (1+ args)
The function name is bound before compiling the body to enable self-recursion:
(define (fact n) (if (<= n 1) 1 (* n (fact (- n 1)))))
func (*CompileTimeContinuation) CompileValidatedDynamicWind ¶
func (p *CompileTimeContinuation) CompileValidatedDynamicWind(ctctx CompileTimeCallContext, v *validate.ValidatedDynamicWind) error
CompileValidatedDynamicWind compiles a validated (dynamic-wind before thunk after) form.
R7RS §6.10: dynamic-wind calls thunk without arguments, returning the result(s). Before is called whenever execution enters the dynamic extent of the call to thunk, and after is called whenever it exits.
The key insight is that by compiling to bytecode, the cleanup code (calling after) is in the bytecode stream. When a continuation is captured inside the thunk and later restored, the cleanup code will run on normal completion.
Bytecode structure:
<compile before> PUSH <compile thunk> PUSH <compile after> PUSH ; Stack: [before, thunk, after] PEEK_K 2 ; value = before SAVE_CONTINUATION →after_before APPLY ; call before() after_before: ; Stack: [before, thunk, after] OP_PUSH_WIND ; create winding frame PEEK_K 1 ; value = thunk SAVE_CONTINUATION →after_thunk APPLY ; call thunk() after_thunk: ; Stack: [before, thunk, after] PUSH ; save thunk result, Stack: [before, thunk, after, result] OP_POP_WIND ; pop winding frame PEEK_K 1 ; value = after SAVE_CONTINUATION →after_after APPLY ; call after() after_after: ; Stack: [before, thunk, after, result] PEEK_K 0 ; value = result (thunk's return value) DROP DROP DROP DROP ; clean up stack
func (*CompileTimeContinuation) CompileValidatedIf ¶
func (p *CompileTimeContinuation) CompileValidatedIf(ctctx CompileTimeCallContext, v *validate.ValidatedIf) error
CompileValidatedIf compiles a validated (if test conseq [alt]) form. The structure is guaranteed to be valid by the validator.
Constant folding (Aho et al., Compilers §8.5): when the test is a compile-time literal, the entire if-form reduces to one branch. This is the simplest form of constant folding — evaluating known expressions at compile time rather than runtime. See BIBLIOGRAPHY.md "Constant Folding".
func (*CompileTimeContinuation) CompileValidatedLambda ¶
func (p *CompileTimeContinuation) CompileValidatedLambda(ctctx CompileTimeCallContext, v *validate.ValidatedLambda) error
CompileValidatedLambda compiles a validated (lambda params body...) form.
func (*CompileTimeContinuation) CompileValidatedLet ¶
func (p *CompileTimeContinuation) CompileValidatedLet( ctctx CompileTimeCallContext, v *validate.ValidatedLet, ) error
CompileValidatedLet compiles all binding forms based on Kind.
let: <inits> Push... | OpPushEnv | StoreLocal(reverse) | body | OpPopEnv let*: OpPushEnv | (init Push StoreLocal)... | body | OpPopEnv letrec: OpPushEnv | <inits> Push... | StoreLocal(reverse) | body | OpPopEnv letrec*: OpPushEnv | (init Push StoreLocal)... | body | OpPopEnv
func (*CompileTimeContinuation) CompileValidatedQuasiquote ¶
func (p *CompileTimeContinuation) CompileValidatedQuasiquote(ctctx CompileTimeCallContext, v *validate.ValidatedQuasiquote) error
CompileValidatedQuasiquote compiles a validated (quasiquote template) form. Quasiquote has complex runtime semantics, so we delegate to the existing compiler.
func (*CompileTimeContinuation) CompileValidatedQuote ¶
func (p *CompileTimeContinuation) CompileValidatedQuote(_ CompileTimeCallContext, v *validate.ValidatedQuote) error
CompileValidatedQuote compiles a validated (quote datum) form.
func (*CompileTimeContinuation) CompileValidatedSetBang ¶
func (p *CompileTimeContinuation) CompileValidatedSetBang(ctctx CompileTimeCallContext, v *validate.ValidatedSetBang) error
CompileValidatedSetBang compiles a validated (set! name expr) form.
func (*CompileTimeContinuation) CompileValidatedWithContinuationMark ¶
func (p *CompileTimeContinuation) CompileValidatedWithContinuationMark( ctctx CompileTimeCallContext, v *validate.ValidatedWithContinuationMark, ) error
CompileValidatedWithContinuationMark compiles (with-continuation-mark key val body).
Tail position:
<compile key> PUSH <compile val> SetContMark ; pops key, sets marks[key] = val <compile body in tail>
Non-tail position:
<compile key> PUSH <compile val> SaveContMark ; pops key, saves (key, old) on stack, sets mark <compile body in non-tail> RestoreContMark ; pops (old, key), restores mark
func (*CompileTimeContinuation) CompileWithSyntax ¶
func (p *CompileTimeContinuation) CompileWithSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
CompileWithSyntax compiles the (with-syntax ((pattern expr) ...) body ...) form.
with-syntax is a convenience form for binding pattern variables from expressions. It's equivalent to:
(syntax-case (list expr ...) () ((pattern ...) (let () body ...)))
For now, this implements a simple transformation approach.
func (*CompileTimeContinuation) SetFileResolver ¶
func (p *CompileTimeContinuation) SetFileResolver(r FileResolver)
SetFileResolver overrides the file resolver used by include/load. Nil resets to the environment's resolver (or OSFileResolver as fallback).
func (*CompileTimeContinuation) SetInlineThreshold ¶ added in v1.10.7
func (p *CompileTimeContinuation) SetInlineThreshold(n int)
SetInlineThreshold sets the maximum body length for procedure inlining. 0 disables inlining entirely.
func (*CompileTimeContinuation) SetLibraryCallback ¶
func (p *CompileTimeContinuation) SetLibraryCallback(cb func(*CompiledLibrary))
SetLibraryCallback sets a callback function that will be called when a library is compiled via CompileDefineLibrary. This is used by LoadLibrary to capture the compiled library.
type CompiledLibrary ¶
type CompiledLibrary struct {
Name LibraryName // Library name
Description string // from (description ...) clause; "" if absent
Env *environment.EnvironmentFrame // Library's private environment
Exports map[string]string // external-name -> internal-name
SourceFile string // Path to .sld file (for error messages)
Template *machine.NativeTemplate // Compiled bytecode (for execution)
}
CompiledLibrary holds a loaded and compiled library.
func LoadLibrary ¶
func LoadLibrary(ctx context.Context, name LibraryName, env *environment.EnvironmentFrame, evaluator machine.MacroEvaluator) (*CompiledLibrary, error)
LoadLibrary loads a library by name, compiling and executing it if not already loaded. Returns the CompiledLibrary which can be used to import bindings.
The function: 1. Checks if already loaded (returns cached library) 2. Checks for circular dependencies 3. Resolves and opens the library file via FileResolver 4. Parses and compiles the define-library form 5. Executes the library to create runtime bindings 6. Registers the library in the registry
func NewCompiledLibrary ¶
func NewCompiledLibrary(name LibraryName, env *environment.EnvironmentFrame) *CompiledLibrary
NewCompiledLibrary creates a new compiled library.
func (*CompiledLibrary) AddExport ¶
func (p *CompiledLibrary) AddExport(externalName, internalName string)
AddExport adds an export to the library. If internalName is empty, it defaults to externalName (no rename).
func (*CompiledLibrary) GetInternalName ¶
func (p *CompiledLibrary) GetInternalName(externalName string) string
GetInternalName returns the internal name for an exported external name. Returns empty string if not exported.
func (*CompiledLibrary) IsExported ¶
func (p *CompiledLibrary) IsExported(externalName string) bool
IsExported returns true if the given external name is exported.
type CompilerFunc ¶
type CompilerFunc func(ctc *CompileTimeContinuation, ctctx CompileTimeCallContext, expr *validate.ValidatedLiteral) error
CompilerFunc is the signature for Tier 2 (syntax passthrough) compiler functions. These receive ValidatedLiteral because Tier 2 forms pass through validation as literals with a FormName. Tier 1 forms (if, define, lambda, etc.) are dispatched by type switch in compileValidated and never reach the registry.
func LookupCompiler ¶
func LookupCompiler(name string) CompilerFunc
LookupCompiler returns the compiler function for a form name, or nil.
type ERMacroTransformer ¶
type ERMacroTransformer struct {
// contains filtered or unexported fields
}
ERMacroTransformer wraps a 3-arg machine.MachineClosure to identify it as an explicit-renaming transformer in expandMacroInvocation. The defEnv captures the expand-time environment at the macro definition site, used by the rename closure to resolve definition-site bindings.
func NewERMacroTransformer ¶
func NewERMacroTransformer(closure *machine.MachineClosure, defEnv *environment.EnvironmentFrame) *ERMacroTransformer
func (*ERMacroTransformer) Closure ¶
func (p *ERMacroTransformer) Closure() *machine.MachineClosure
func (*ERMacroTransformer) DefEnv ¶
func (p *ERMacroTransformer) DefEnv() *environment.EnvironmentFrame
func (*ERMacroTransformer) IsVoid ¶
func (p *ERMacroTransformer) IsVoid() bool
func (*ERMacroTransformer) SchemeString ¶
func (p *ERMacroTransformer) SchemeString() string
type EmbedFileResolver ¶
type EmbedFileResolver struct {
// contains filtered or unexported fields
}
EmbedFileResolver resolves files from an embedded filesystem (or any fs.FS). No path resolution or security checks — paths are looked up directly.
func NewEmbedFileResolver ¶
func NewEmbedFileResolver(fsys fs.FS) *EmbedFileResolver
NewEmbedFileResolver creates a resolver backed by the given filesystem.
func (*EmbedFileResolver) ResolveAndOpen ¶
type ExpanderContext ¶
type ExpanderContext struct {
// contains filtered or unexported fields
}
ExpanderContext provides access to the macro expander from within Scheme code during macro expansion. It is set on machine.MachineContext when invoking macro transformers, enabling syntax-local-* primitives.
func NewExpanderContext ¶
func NewExpanderContext( env *environment.EnvironmentFrame, expander *ExpanderTimeContinuation, ) *ExpanderContext
NewExpanderContext creates a new ExpanderContext.
func (*ExpanderContext) Env ¶
func (p *ExpanderContext) Env() *environment.EnvironmentFrame
Env returns the environment frame associated with this context.
func (*ExpanderContext) Expand ¶
func (p *ExpanderContext) Expand(stx syntax.SyntaxValue) (syntax.SyntaxValue, error)
Expand fully expands a syntax object.
func (*ExpanderContext) ExpandOnce ¶
func (p *ExpanderContext) ExpandOnce(stx syntax.SyntaxValue) (syntax.SyntaxValue, bool, error)
ExpandOnce performs a single step of macro expansion. Returns (expanded-syntax, did-expand, error). If the input is a macro call, it expands it once and returns (result, true, nil). If the input is not a macro call, it returns (input, false, nil).
func (*ExpanderContext) IntroductionScope ¶
func (p *ExpanderContext) IntroductionScope() *syntax.Scope
IntroductionScope returns the introduction scope for the current macro expansion. This scope is added to identifiers introduced by a macro and can be flipped using syntax-local-introduce.
func (*ExpanderContext) SetIntroductionScope ¶
func (p *ExpanderContext) SetIntroductionScope(scope *syntax.Scope)
SetIntroductionScope sets the introduction scope for the current macro expansion.
func (*ExpanderContext) SetUseSiteScope ¶
func (p *ExpanderContext) SetUseSiteScope(scope *syntax.Scope)
SetUseSiteScope sets the use-site scope for binding forms.
func (*ExpanderContext) UseSiteScope ¶
func (p *ExpanderContext) UseSiteScope() *syntax.Scope
UseSiteScope returns the use-site scope for binding forms. This scope is used by syntax-local-identifier-as-binding to mark identifiers as binding sites.
type ExpanderTimeContinuation ¶
type ExpanderTimeContinuation struct {
// contains filtered or unexported fields
}
ExpanderTimeContinuation is a continuation used during the expansion phase.
It walks the syntax tree, detecting and expanding macro invocations. The env field provides access to macro definitions (BindingTypeSyntax bindings).
func NewExpanderTimeContinuation ¶
func NewExpanderTimeContinuation(ctx context.Context, env *environment.EnvironmentFrame, evaluator machine.MacroEvaluator) *ExpanderTimeContinuation
NewExpanderTimeContinuation creates a new ExpanderTimeContinuation.
func (*ExpanderTimeContinuation) Context ¶
func (p *ExpanderTimeContinuation) Context() context.Context
Context returns the context associated with this expander continuation.
func (*ExpanderTimeContinuation) ExpandBodyWithDefineSyntax ¶
func (p *ExpanderTimeContinuation) ExpandBodyWithDefineSyntax( forms []syntax.SyntaxValue, ) ([]syntax.SyntaxValue, error)
ExpandBodyWithDefineSyntax expands a sequence of body forms, compiling define-syntax forms as encountered so subsequent forms can use the macros.
This unifies the expansion pattern used by: - Lambda bodies (internal define-syntax) - Library bodies (top-level define-syntax) - Include files (top-level define-syntax)
R7RS §5.3: Internal define-syntax forms must be processed before expanding subsequent body expressions so that locally-defined macros are visible.
R7RS §5.3.2: Bodies use letrec* semantics where all defined names are visible to all initializers. This enables forward references within macros - a macro can reference a definition that appears later in the same body.
func (*ExpanderTimeContinuation) ExpandExpression ¶
func (p *ExpanderTimeContinuation) ExpandExpression(expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandExpression expands a syntax expression.
func (*ExpanderTimeContinuation) ExpandOnce ¶
func (p *ExpanderTimeContinuation) ExpandOnce(expr syntax.SyntaxValue) (syntax.SyntaxValue, bool, error)
ExpandOnce performs a single step of macro expansion. Returns (expanded-syntax, did-expand, error). If the input is a macro call, it expands it once and returns (result, true, nil). If the input is not a macro call, it returns (input, false, nil). Unlike ExpandExpression, this does NOT recursively expand the result.
func (*ExpanderTimeContinuation) ExpandPrimitiveForm ¶
func (p *ExpanderTimeContinuation) ExpandPrimitiveForm(primName string, sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandPrimitiveForm handles expansion within primitive forms like if, begin, lambda, define, etc. Some primitives need their subexpressions expanded (like if, begin) while others should be left unchanged (like quote, define-syntax).
This function looks up the primitive expander in the expand environment registry. If found, it invokes the expander; otherwise returns the form unchanged.
func (*ExpanderTimeContinuation) ExpandSelfEvaluating ¶
func (p *ExpanderTimeContinuation) ExpandSelfEvaluating(expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandSelfEvaluating handles self-evaluating expressions.
func (*ExpanderTimeContinuation) ExpandSymbol ¶
func (p *ExpanderTimeContinuation) ExpandSymbol(expr *syntax.SyntaxSymbol) (syntax.SyntaxValue, error)
ExpandSymbol handles a symbol expression.
func (*ExpanderTimeContinuation) ExpandSyntaxArgumentList ¶
func (p *ExpanderTimeContinuation) ExpandSyntaxArgumentList(args syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandSyntaxArgumentList expands each argument in the argument list. It returns a new syntax list with the expanded arguments.
func (*ExpanderTimeContinuation) ExpandSyntaxExpression ¶
func (p *ExpanderTimeContinuation) ExpandSyntaxExpression(sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandSyntaxExpression checks if sym is a macro and expands it, or returns the expression as a procedure call if not.
This is where macro invocation happens:
- Look up the symbol in the expand environment
- If bound with BindingTypeSyntax, it's a macro - invoke the transformer
- If it's a primitive (like quote, if, define-syntax), don't expand args
- Otherwise, treat as procedure call and expand arguments
The transformer closure (machine.MachineClosure from CompileSyntaxRules) is invoked by creating a machine.MachineContext and running it. The transformer:
- Receives the full macro invocation form on the eval stack
- Pattern matches against its clauses (OperationSyntaxRulesTransform)
- Expands the matching template with captured bindings
- Adds an intro scope to the expansion for hygiene
- Returns the expanded syntax in the value register
The expanded result may itself contain macro invocations, so the caller should recursively expand it.
func (*ExpanderTimeContinuation) ExpandSyntaxOrProcedureCall ¶
func (p *ExpanderTimeContinuation) ExpandSyntaxOrProcedureCall(car syntax.SyntaxValue, cdr syntax.SyntaxValue) (syntax.SyntaxValue, error)
ExpandSyntaxOrProcedureCall handles a list expression. The car may be a symbol (possibly a macro), a nested pair (computed procedure), or a self-evaluating value (like in quoted data or malformed expressions).
type FSFileResolver ¶
type FSFileResolver struct {
// contains filtered or unexported fields
}
FSFileResolver resolves files from a virtual filesystem (fs.FS). Used when an embedder provides WithSourceFS. All paths are relative to the FS root. Absolute paths are rejected.
Resolution priority:
- Relative to current load directory (from LoadPathStack)
- Library registry search paths
- Relative to FS root (path as-is)
func NewFSFileResolver ¶
func NewFSFileResolver(fsys fs.FS, env *environment.EnvironmentFrame) *FSFileResolver
NewFSFileResolver creates a resolver backed by the given filesystem. Panics if fsys is nil.
func (*FSFileResolver) EnumerateLibraries ¶
func (p *FSFileResolver) EnumerateLibraries() ([]LibraryName, error)
EnumerateLibraries walks the virtual filesystem to discover all libraries. Library registry search paths are walked first (each with its own relPath base), then the FS root is walked to find files not under any search path. Duplicate library names (same key) are deduplicated with earlier discovery winning. Hidden directories (starting with ".") are always skipped.
Best-effort: non-existent directories and unauthorized files are skipped. Walk errors are joined and returned alongside partial results.
func (*FSFileResolver) ResolveAndOpen ¶
type FeatureRequirement ¶
type FeatureRequirement interface {
// IsSatisfied returns true if this requirement is satisfied.
// The registry parameter is used to check if a library is already loaded.
// The resolver parameter is used to check if a library file exists
// (via the FileResolver chain, supporting both OS and virtual fs.FS).
IsSatisfied(ctx context.Context, registry *LibraryRegistry, resolver FileResolver) bool
}
FeatureRequirement represents a parsed cond-expand feature requirement. Feature requirements can be:
- A symbol (feature identifier)
- (library <library-name>) - check if library is available
- (and <req> ...) - all requirements must be satisfied
- (or <req> ...) - at least one requirement must be satisfied
- (not <req>) - requirement must NOT be satisfied
func NewAndRequirement ¶
func NewAndRequirement(reqs ...FeatureRequirement) FeatureRequirement
NewAndRequirement creates an and requirement.
func NewElseRequirement ¶
func NewElseRequirement() FeatureRequirement
NewElseRequirement creates an else requirement (always satisfied).
func NewFeatureIdentifier ¶
func NewFeatureIdentifier(name string) FeatureRequirement
NewFeatureIdentifier creates a feature identifier requirement.
func NewLibraryRequirement ¶
func NewLibraryRequirement(name LibraryName) FeatureRequirement
NewLibraryRequirement creates a library requirement.
func NewNotRequirement ¶
func NewNotRequirement(req FeatureRequirement) FeatureRequirement
NewNotRequirement creates a not requirement.
func NewOrRequirement ¶
func NewOrRequirement(reqs ...FeatureRequirement) FeatureRequirement
NewOrRequirement creates an or requirement.
type FileResolver ¶
type FileResolver = environment.FileResolver
FileResolver resolves and opens files for include/load operations. The interface is defined in the environment package; this alias keeps the name available in compilation without re-declaration.
type ImportSet ¶
type ImportSet struct {
LibraryName LibraryName // Base library to import from
Only map[string]struct{} // If non-nil, only import these names
Except map[string]struct{} // If non-nil, import all except these
Prefix string // If non-empty, add this prefix to all names
Renames map[string]string // old-name -> new-name
PhaseShift int // Phase offset: 0=runtime, 1=for-syntax, -1=for-template
}
ImportSet represents a parsed import specification. It can be a simple library reference or include modifiers.
PhaseShift supports Racket-style phased imports:
- (import (scheme base)) ; Phase 0 (runtime) - default
- (import (for-syntax (scheme base))) ; Phase +1 (expand)
- (import (for-template (scheme base))) ; Phase -1
- (import (for-meta 2 (scheme base))) ; Phase +2
- (import (for-meta -1 (scheme base))) ; Phase -1 (same as for-template)
Phase shifts compose additively: (for-syntax (for-syntax lib)) = phase +2
func NewImportSet ¶
func NewImportSet(name LibraryName) *ImportSet
NewImportSet creates a new import set for a library.
func ParseImportSetFromDatum ¶
ParseImportSetFromDatum parses an import set from datum values. Used at both runtime (by the 'environment' procedure) and compile time (via UnwrapAll on syntax objects).
Import sets can be:
- (<library-name>) : import all exports
- (only <import-set> <id> ...) : import only specified identifiers
- (except <import-set> <id> ...): import all except specified
- (prefix <import-set> <prefix>): add prefix to all imported names
- (rename <import-set> (<old> <new>) ...): rename specific imports
- (for-syntax <import-set>) : import at phase +1 (macro expansion)
- (for-template <import-set>) : import at phase -1
- (for-meta <n> <import-set>) : import at phase +n
func (*ImportSet) ApplyToExports ¶
func (p *ImportSet) ApplyToExports(lib *CompiledLibrary) (map[string]string, error)
ApplyToExports applies the import modifiers and returns the final bindings. Returns a map of local-name -> external-name (the name in the library).
type LibraryEnumerator ¶
type LibraryEnumerator interface {
EnumerateLibraries() ([]LibraryName, error)
}
LibraryEnumerator is an optional interface that FileResolvers can implement to support library discovery. Enumeration is the inverse of resolution: same directories, same priority, but walking files instead of looking up a specific name.
type LibraryImportEvent ¶
type LibraryImportEvent struct {
Library LibraryName // imported library name, e.g., (scheme base)
SourceFile string // path to .sld file (empty for synthetic libraries)
Exports []string // all names exported by the library
Imported []string // names that actually landed in the importer (after only/except/prefix/rename)
Importer LibraryName // importing library name (zero value for top-level import)
Phase int // pipeline phase: environment.PhaseExpand or environment.PhaseCompile
}
LibraryImportEvent records what happened when a library was imported.
type LibraryImportObserver ¶
type LibraryImportObserver func(LibraryImportEvent)
LibraryImportObserver is called when a library is imported. Observers are read-only — they cannot influence the import.
type LibraryName ¶
type LibraryName struct {
Parts []string // e.g., ["scheme", "base"]
}
LibraryName represents an R7RS library name like (scheme base) or (my lib). Library names are lists of identifiers used to uniquely identify a library.
func DiscoverAvailableLibraries ¶
func DiscoverAvailableLibraries(resolver FileResolver, reg *LibraryRegistry) ([]LibraryName, error)
DiscoverAvailableLibraries returns all importable library names by combining filesystem discovery (via the resolver's LibraryEnumerator) with registry-known libraries (synthetic extension libraries). Returns a sorted, deduplicated list.
If the resolver does not implement LibraryEnumerator, only registry libraries are returned. If reg is nil, only filesystem libraries are returned.
func FilePathToLibraryName ¶
func FilePathToLibraryName(path string) (LibraryName, error)
FilePathToLibraryName converts a forward-slash-separated file path with .sld or .scm extension to a LibraryName. This is the inverse of ToFSPath(). Returns an error if the path has no recognized extension or is empty.
func NewLibraryName ¶
func NewLibraryName(parts ...string) LibraryName
NewLibraryName creates a LibraryName from a list of string parts.
func ParseLibraryNameFromDatum ¶
ParseLibraryNameFromDatum extracts a LibraryName from a datum list like (scheme base). Used at both runtime (by the 'environment' procedure) and compile time (via UnwrapAll on syntax objects).
func (LibraryName) Key ¶
func (p LibraryName) Key() string
Key returns a unique string key for map lookups.
func (LibraryName) SchemeString ¶
func (p LibraryName) SchemeString() string
SchemeString returns the Scheme representation like "(scheme base)".
func (LibraryName) String ¶
func (p LibraryName) String() string
String returns a human-readable representation like "scheme/base".
func (LibraryName) ToFSPath ¶
func (p LibraryName) ToFSPath() string
ToFSPath returns the library name as a forward-slash-separated path with .sld extension, suitable for fs.FS and FileResolver operations.
func (LibraryName) ToSchemeValue ¶
func (p LibraryName) ToSchemeValue() values.Value
ToSchemeValue converts a LibraryName to a Scheme list. Parts that parse as nonnegative integers become exact integers; all others become symbols. Matches R7RS library name syntax.
type LibraryRegistry ¶
type LibraryRegistry struct {
// contains filtered or unexported fields
}
LibraryRegistry manages loaded libraries and handles library loading.
func NewLibraryRegistry ¶
func NewLibraryRegistry() *LibraryRegistry
NewLibraryRegistry creates a new library registry with default search paths.
func (*LibraryRegistry) All ¶
func (p *LibraryRegistry) All() []*CompiledLibrary
All returns all loaded libraries, sorted by name key for determinism.
func (*LibraryRegistry) AllNames ¶
func (p *LibraryRegistry) AllNames() []LibraryName
AllNames returns the names of all registered libraries, sorted by key.
func (*LibraryRegistry) FinishLoading ¶
func (p *LibraryRegistry) FinishLoading(name LibraryName)
FinishLoading marks a library as finished loading.
func (*LibraryRegistry) GetSearchPaths ¶
func (p *LibraryRegistry) GetSearchPaths() []string
GetSearchPaths returns the current library search paths.
func (*LibraryRegistry) ImportObserver ¶
func (p *LibraryRegistry) ImportObserver() LibraryImportObserver
ImportObserver returns the current import observer, or nil.
func (*LibraryRegistry) IsLoading ¶
func (p *LibraryRegistry) IsLoading(name LibraryName) bool
IsLoading returns true if the library is currently being loaded. Used to detect circular dependencies.
func (*LibraryRegistry) Lookup ¶
func (p *LibraryRegistry) Lookup(name LibraryName) *CompiledLibrary
Lookup returns a library by name, or nil if not found.
func (*LibraryRegistry) PrependSearchPath ¶
func (p *LibraryRegistry) PrependSearchPath(path string)
PrependSearchPath adds a path to the beginning of the search path list.
func (*LibraryRegistry) Register ¶
func (p *LibraryRegistry) Register(lib *CompiledLibrary) error
Register adds a compiled library to the registry.
func (*LibraryRegistry) SetImportObserver ¶
func (p *LibraryRegistry) SetImportObserver(obs LibraryImportObserver)
SetImportObserver sets an optional observer that is called each time a library is imported. The observer is read-only and cannot influence the import. Pass nil to remove the observer.
func (*LibraryRegistry) SetSearchPaths ¶
func (p *LibraryRegistry) SetSearchPaths(paths []string)
SetSearchPaths sets the library search paths.
func (*LibraryRegistry) StartLoading ¶
func (p *LibraryRegistry) StartLoading(name LibraryName)
StartLoading marks a library as being loaded.
type OSFileResolver ¶
type OSFileResolver struct {
// contains filtered or unexported fields
}
OSFileResolver resolves files from the operating system filesystem, using the load path stack, library registry, SCHEME_INCLUDE_PATH, and CWD as fallback directories. It also enforces security authorization.
func NewOSFileResolver ¶
func NewOSFileResolver(env *environment.EnvironmentFrame) *OSFileResolver
NewOSFileResolver creates a resolver that finds files on the OS filesystem.
func (*OSFileResolver) EnumerateLibraries ¶
func (p *OSFileResolver) EnumerateLibraries() ([]LibraryName, error)
EnumerateLibraries walks the OS filesystem to discover importable libraries. Searches the same directories as ResolveAndOpen: library registry paths, SCHEME_INCLUDE_PATH, and CWD. First directory wins on duplicate library names.
Best-effort: non-existent directories and unauthorized files are skipped. Walk errors are joined and returned alongside partial results.
func (*OSFileResolver) ResolveAndOpen ¶
type PhaseEntry ¶
PhaseEntry represents a named item to register in a phase environment.
type PrimitiveExpander ¶
type PrimitiveExpander struct {
// contains filtered or unexported fields
}
PrimitiveExpander wraps a PrimitiveExpanderFunc as a values.Value so it can be stored in the environment.
func LookupPrimitiveExpander ¶
func LookupPrimitiveExpander(env *environment.EnvironmentFrame, sym *values.Symbol, scopes []*syntax.Scope) *PrimitiveExpander
LookupPrimitiveExpander looks up a primitive expander by symbol in the expand environment. Returns the PrimitiveExpander if found, or nil if the symbol does not name a primitive expander.
This function handles hygiene by using scoped lookup - it will only match bindings whose scopes are a subset of the symbol's scopes.
func NewPrimitiveExpander ¶
func NewPrimitiveExpander(name string, fn PrimitiveExpanderFunc) *PrimitiveExpander
NewPrimitiveExpander creates a new primitive expander.
func (*PrimitiveExpander) EqualTo ¶
func (p *PrimitiveExpander) EqualTo(other values.Value) bool
EqualTo implements values.Value interface.
func (*PrimitiveExpander) Expand ¶
func (p *PrimitiveExpander) Expand( etc *ExpanderTimeContinuation, sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue, ) (syntax.SyntaxValue, error)
Expand invokes the primitive expander function.
func (*PrimitiveExpander) IsVoid ¶
func (p *PrimitiveExpander) IsVoid() bool
IsVoid returns false — named handlers are never void.
func (*PrimitiveExpander) Name ¶
func (p *PrimitiveExpander) Name() string
Name returns the handler's name.
func (*PrimitiveExpander) SchemeString ¶
func (p *PrimitiveExpander) SchemeString() string
SchemeString returns the Scheme representation: #<prefix:name>.
type PrimitiveExpanderFunc ¶
type PrimitiveExpanderFunc func( etc *ExpanderTimeContinuation, sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue, ) (syntax.SyntaxValue, error)
PrimitiveExpanderFunc is the type for expand-time special form handlers. These functions handle macro expansion of primitive forms like `if`, `lambda`, `define`, `quote`, etc.
Parameters:
- etc: The expander-time continuation (expander state, carries context)
- sym: The keyword symbol (e.g., 'if', 'lambda')
- expr: The expression arguments (everything after the keyword)
Returns the expanded syntax value.
type ResolvedImportSet ¶
type ResolvedImportSet struct {
ImportSet *ImportSet
Library *CompiledLibrary
Bindings map[string]string // localName -> externalName
}
ResolvedImportSet holds the result of parsing and loading an import set. This is the shared prefix of all import processing: parse the import set datum, load the named library, and apply modifiers (only, except, prefix, rename) to produce the final binding map.
type SyntaxCompiler ¶
type SyntaxCompiler struct {
// contains filtered or unexported fields
}
SyntaxCompiler wraps a SyntaxCompilerFunc as a values.Value so it can be stored in the environment.
func LookupSyntaxCompiler ¶
func LookupSyntaxCompiler(env *environment.EnvironmentFrame, sym *values.Symbol, scopes []*syntax.Scope) *SyntaxCompiler
LookupSyntaxCompiler looks up a syntax compiler by symbol in the compile environment. Returns the SyntaxCompiler if found, or nil if the symbol does not name a syntax compiler.
This function handles hygiene by using scoped lookup - it will only match bindings whose scopes are a subset of the symbol's scopes.
func NewSyntaxCompiler ¶
func NewSyntaxCompiler(name string, fn SyntaxCompilerFunc) *SyntaxCompiler
NewSyntaxCompiler creates a new syntax compiler.
func (*SyntaxCompiler) Compile ¶
func (p *SyntaxCompiler) Compile(ctc *CompileTimeContinuation, ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
Compile invokes the syntax compiler function.
func (*SyntaxCompiler) EqualTo ¶
func (p *SyntaxCompiler) EqualTo(other values.Value) bool
EqualTo implements values.Value interface.
func (*SyntaxCompiler) IsVoid ¶
func (p *SyntaxCompiler) IsVoid() bool
IsVoid returns false — named handlers are never void.
func (*SyntaxCompiler) Name ¶
func (p *SyntaxCompiler) Name() string
Name returns the handler's name.
func (*SyntaxCompiler) SchemeString ¶
func (p *SyntaxCompiler) SchemeString() string
SchemeString returns the Scheme representation: #<prefix:name>.
type SyntaxCompilerFunc ¶
type SyntaxCompilerFunc func(ctc *CompileTimeContinuation, ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error
SyntaxCompilerFunc is the type for compile-time special form handlers. These functions handle syntax-directed compilation of extension forms like `syntax-case`, `import`, `define-syntax`, `include`, etc.
Parameters:
- ctc: The compile-time continuation (compiler state)
- ctctx: The compile-time call context (tail position info, etc.)
- expr: The expression arguments (everything after the keyword)
The function should emit operations via ctc.AppendOperations and return nil on success.
Source Files
¶
- compile_begin_for_syntax.go
- compile_closure.go
- compile_cond_expand.go
- compile_define_for_syntax.go
- compile_define_syntax.go
- compile_er_macro.go
- compile_eval_when.go
- compile_helpers.go
- compile_import.go
- compile_let.go
- compile_library_forms.go
- compile_quasisyntax.go
- compile_syntax_case.go
- compile_syntax_form.go
- compile_syntax_rules.go
- compile_time_call_context.go
- compile_time_continuation.go
- compile_time_continuation_include.go
- compile_time_continuation_library.go
- compile_time_continuation_quasiquote.go
- compile_transformer.go
- compile_validated.go
- compile_with_syntax.go
- compiler_registry.go
- er_macro_compare.go
- er_macro_rename.go
- er_macro_transformer.go
- expander_body.go
- expander_context.go
- expander_lambda.go
- expander_let.go
- expander_let_syntax.go
- expander_primitive_forms.go
- expander_time_continuation.go
- features.go
- file_resolver.go
- import_set_datum.go
- letrec_semantics.go
- library_bindings.go
- library_discovery.go
- library_loader.go
- library_registry.go
- named_handler_base.go
- phase_registry.go
- primitive_expander.go
- primitive_expanders_registry.go
- quasi_expand.go
- register.go
- syntax_compiler.go
- syntax_compilers_registry.go