machine

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package machine implements the Scheme virtual machine, compiler, and macro expander.

The machine package is the core execution engine for Wile, providing:

Compilation Pipeline

Scheme source undergoes three phases:

  1. Expansion: macro-expand via ExpanderTimeContinuation
  2. Compilation: generate bytecode via CompileTimeContinuation
  3. Execution: run bytecode via MachineContext

Virtual Machine

The VM is a stack-based interpreter with:

Continuations

Macro System

Implements R7RS hygienic macros with Flatt's "sets of scopes" model:

  • ExpanderTimeContinuation: macro expansion driver
  • syntax-rules pattern matching via internal/match
  • syntax-case with fenders and procedural macros

Foreign Functions

Go functions are exposed as ForeignFunction implementations:

type ForeignFunction func(context.Context, *MachineContext) error

The [ForeignClosure] type wraps these for the VM.

Index

Constants

View Source
const ImplementationName = "wile"

ImplementationName is the name of this Scheme implementation.

View Source
const (
	// SchemeIncludePathEnv is the environment variable name for the Scheme include path
	SchemeIncludePathEnv = "SCHEME_INCLUDE_PATH"
)

Variables

View Source
var DefaultLibraryPaths = []string{
	".",
	"./lib",
}

DefaultLibraryPaths are the default directories to search for libraries.

View Source
var DefaultPromptTag = NewPromptTag("default")

DefaultPromptTag is the default prompt tag installed at the top of execution.

View Source
var ErrMachineDoNotAdvancePC = values.NewStaticError("machine do not advance PC: operation did not advance program counter")

Functions

func AllFeatures

func AllFeatures() []string

AllFeatures returns all supported feature identifiers.

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

CopyLibraryBindingsToEnvAtPhase copies exported bindings from a library to a specific phase. bindings is the map from localName -> externalName produced by ApplyToExports.

Phase semantics:

  • targetPhase == 0: Runtime import (default). Runtime bindings go to phase 0, syntax bindings go to both phase 0 (for export) and phase 1 (for use in macros).
  • targetPhase > 0: For-syntax import. Bindings are shifted to the target phase. Runtime bindings become available during macro expansion at targetPhase. Syntax bindings go to targetPhase and targetPhase+1.
  • targetPhase < 0: For-template import. Bindings shifted to negative phase (used for generating code that will run at a lower phase).

func DecodeLocalIndex added in v1.4.0

func DecodeLocalIndex(arg int32) (slot, depth int)

DecodeLocalIndex unpacks slot and depth from a bit-packed Instruction.Arg.

func EncodeLocalIndex added in v1.4.0

func EncodeLocalIndex(li *environment.LocalIndex) int32

EncodeLocalIndex packs a LocalIndex's slot and depth into a single int32 for storage in Instruction.Arg. Slot occupies the low 16 bits; depth occupies the high 16 bits. Both values must fit in int16 range (max 32767).

func FindCommonWindingPrefix

func FindCommonWindingPrefix(current, target WindingStack) int

FindCommonPrefix finds the longest common prefix of two winding stacks. Returns the index where they diverge (0 means no common frames).

func GraftContinuation

func GraftContinuation(segment, target *MachineContinuation)

GraftContinuation walks the segment chain to its bottom frame and sets its parent to target, effectively splicing the segment onto the target chain.

func IsFeatureSupported

func IsFeatureSupported(feature string) bool

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

RegisterPrimitiveExpanders binds all primitive expanders in the expand-time environment (env.Expand()). These are looked up by ExpandPrimitiveForm() when the expander encounters a special form.

Each primitive has different expansion behavior:

  • quote, define-syntax, quasiquote: return unchanged (no expansion)
  • if: expand test, consequent, alternative separately
  • begin: expand all subexpressions
  • set!: expand only the value expression
  • define: expand value if simple define
  • lambda, case-lambda: expand body expressions
  • syntax-case, cond-expand: return unchanged (compile-time forms)

func RegisterSyntaxCompilers

func RegisterSyntaxCompilers(env *environment.EnvironmentFrame) error

RegisterSyntaxCompilers binds all syntax compilers in the compile-time environment (env.Compile()). These are looked up by CompileSyntaxPrimitive() when the compiler encounters a special form.

The compiler uses a two-tier dispatch system:

Tier 1 (Validated Forms): Core forms like if, define, lambda, set!, quote, quasiquote, begin go through the validation layer which produces type-safe ValidatedExpr types, then compile via compileValidated* methods. These are NOT registered here.

Tier 2 (Registry Forms): Extension forms like syntax-case, import, define-syntax pass through validation as ValidatedLiteral, then are dispatched via this registry. This is the single source of truth for these forms.

The syntax compilers are bound with BindingTypePrimitive to distinguish them from syntax transformers (BindingTypeSyntax) and regular variables.

func ReleaseSubContext added in v1.4.0

func ReleaseSubContext(mc *MachineContext)

ReleaseSubContext zeros the MachineContext and returns it to the pool. Exported because call sites live in other packages (registry/, extensions/).

Types

type BarrierToken added in v1.4.0

type BarrierToken struct {
	// contains filtered or unexported fields
}

BarrierToken is an opaque identity for a with-continuation-barrier scope. Each call to call-with-continuation-barrier creates a fresh token. Barrier crossing is detected by pointer identity comparison: if the capture-time token differs from the invocation-time token, the continuation would cross a barrier boundary.

nil means "not inside any barrier."

The _ field ensures non-zero struct size. Go may return the same pointer for all zero-sized allocations (runtime.zerobase), which would defeat pointer identity comparison.

func NewBarrierToken added in v1.4.0

func NewBarrierToken() *BarrierToken

NewBarrierToken creates a fresh barrier identity token.

type Breakpoint

type Breakpoint struct {
	ID       BreakpointID
	File     string
	Line     int
	Column   int // 0 = any column on line
	Enabled  bool
	HitCount int
}

Breakpoint represents a source-level breakpoint.

type BreakpointID

type BreakpointID int

BreakpointID uniquely identifies a breakpoint.

type CaseLambdaClosure

type CaseLambdaClosure struct {
	// contains filtered or unexported fields
}

CaseLambdaClosure dispatches to the first clause whose arity matches the argument count. Each clause is a MachineClosure with its own template and captured environment.

func NewCaseLambdaClosure

func NewCaseLambdaClosure(closures []*MachineClosure) *CaseLambdaClosure

func (*CaseLambdaClosure) Clauses

func (p *CaseLambdaClosure) Clauses() []*MachineClosure

func (*CaseLambdaClosure) EqualTo

func (p *CaseLambdaClosure) EqualTo(o values.Value) bool

EqualTo implements Scheme equality for case-lambda closures. Two void closures (nil receivers) are considered equal to each other. Non-void closures are equal only if they have the same number of clauses and each corresponding clause is EqualTo its counterpart.

func (*CaseLambdaClosure) FindMatchingClause

func (p *CaseLambdaClosure) FindMatchingClause(argCount int) (*MachineClosure, bool)

FindMatchingClause finds the first clause that matches the given argument count. It returns the matching closure and true when a clause can accept exactly argCount arguments (for fixed-arity clauses) or at least argCount arguments (for variadic clauses). If the receiver is nil or no clause matches, it returns nil, false.

func (*CaseLambdaClosure) IsVoid

func (p *CaseLambdaClosure) IsVoid() bool

IsVoid reports whether this value represents the absence of a case-lambda closure. A nil receiver is treated as a distinguished "void" closure value, used as a sentinel to mean "no closure" rather than an error.

func (*CaseLambdaClosure) SchemeString

func (p *CaseLambdaClosure) SchemeString() string

SchemeString returns the Scheme-readable representation of a case-lambda closure. Note that the void value (nil receiver) still prints as a case-lambda closure; callers must use IsVoid to distinguish the sentinel.

type CompileTimeCallContext

type CompileTimeCallContext struct {
	// contains filtered or unexported fields
}

CompileTimeCallContext carries contextual information through the compilation process. It tracks properties that affect code generation, particularly for tail call optimization and distinguishing definition contexts from expression contexts.

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

Definition vs Expression Context

The inExpression flag distinguishes between definition contexts (top-level or internal definitions) and expression contexts. This affects how certain forms are compiled:

  • In definition context: define creates bindings
  • In expression context: define may be an error or treated differently

Use NotInExpression() when entering a definition-only context (e.g., library body).

func NewCompileTimeCallContext

func NewCompileTimeCallContext(ctx context.Context, inTail, inExpression bool) CompileTimeCallContext

NewCompileTimeCallContext creates a new compile-time context with the given flags. Parameters:

  • inTail: true if compiling an expression in tail position
  • inExpression: true if compiling an expression (vs. a definition)

func (CompileTimeCallContext) NotInExpression

func (p CompileTimeCallContext) NotInExpression() CompileTimeCallContext

NotInExpression returns a copy of the context with inExpression set to false. Use this when entering a definition-only context where expressions are not allowed at the current level (e.g., library declaration bodies before begin).

func (CompileTimeCallContext) NotInTail

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 *NativeTemplate, env *environment.EnvironmentFrame) *CompileTimeContinuation

NewCompiletimeContinuation creates a new CompileTimeContinuation

func (*CompileTimeContinuation) AppendOperations

func (p *CompileTimeContinuation) AppendOperations(ops ...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 OpComplex to the sideTable.

func (*CompileTimeContinuation) CompileBeginForSyntax

func (p *CompileTimeContinuation) CompileBeginForSyntax(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error

CompileBeginForSyntax handles (begin-for-syntax expr ...).

This form evaluates a sequence of expressions at compile time in the expand phase environment. It is useful for setting up compile-time state like hash tables or registries that macros can access.

Each expression is compiled and executed at compile time. The expressions can use define-for-syntax bindings and runtime primitives. The result of the last expression is discarded (begin-for-syntax is used for side effects).

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:

  1. Parse the form: (define-syntax keyword (syntax-rules ...))
  2. Compile the syntax-rules transformer to a MachineClosure
  3. Store the closure in the environment with BindingTypeSyntax
  4. 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

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

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

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(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error

CompileIncludeCi compiles an include-ci expression. It reads and compiles all forms from the specified files in order, treating symbols as case-insensitive (folded to lowercase).

func (*CompileTimeContinuation) CompileMeta

CompileMeta compiles a meta expression.

func (*CompileTimeContinuation) CompilePrimitiveOrProcedureCall

func (p *CompileTimeContinuation) CompilePrimitiveOrProcedureCall(ctctx CompileTimeCallContext, expr syntax.SyntaxValue) error

CompilePrimitiveOrProcedureCall compiles either a primitive or a procedure call. It first checks if the initial element is a syntax symbol that corresponds to a primitive. If so, it compiles the primitive. If not, it treats it as a procedure call.

func (*CompileTimeContinuation) CompileProcedureCall

func (p *CompileTimeContinuation) CompileProcedureCall(ctctx CompileTimeCallContext, initial syntax.SyntaxValue, expr syntax.SyntaxValue) error

CompileProcedureCall compiles a procedure call expression. It assumes that the initial element is not a primitive and compiles it as a procedure call. The compiled code will leave the result of the procedure call on the stack.

Tail Call Optimization: When ctctx.inTail is true, we skip SaveContinuation. This allows the called function's RestoreContinuation to return directly to our caller's continuation, implementing proper tail call optimization per R7RS Section 3.5.

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

CompileSymbol compiles a syntax symbol expression.

func (*CompileTimeContinuation) CompileSyntax

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:

  1. Compile expr to get the input syntax object
  2. For each clause, generate pattern matching and body code
  3. Pattern variables are bound as local variables in the body's scope
  4. If fender exists, it's evaluated as a guard condition

func (*CompileTimeContinuation) CompileSyntaxPrimitive

func (p *CompileTimeContinuation) CompileSyntaxPrimitive(ctctx CompileTimeCallContext, sym *syntax.SyntaxSymbol, expr syntax.SyntaxValue) (bool, error)

CompileSyntaxPrimitive compiles a syntax primitive if sym corresponds to one.

func (*CompileTimeContinuation) CompileUnquote

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

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) CompileValidatedBegin

func (p *CompileTimeContinuation) CompileValidatedBegin(ctctx CompileTimeCallContext, _ string, 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, _ string, 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, formName string, v *validate.ValidatedDefine) error

CompileValidatedDefine compiles a validated define form.

func (*CompileTimeContinuation) CompileValidatedDefineFn

func (p *CompileTimeContinuation) CompileValidatedDefineFn(ctctx CompileTimeCallContext, _ string, 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, _ string, 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, _ string, 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, _ string, v *validate.ValidatedLambda) error

CompileValidatedLambda compiles a validated (lambda params body...) form.

func (*CompileTimeContinuation) CompileValidatedQuasiquote

func (p *CompileTimeContinuation) CompileValidatedQuasiquote(ctctx CompileTimeCallContext, _ string, 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

CompileValidatedQuote compiles a validated (quote datum) form.

func (*CompileTimeContinuation) CompileValidatedSetBang

func (p *CompileTimeContinuation) CompileValidatedSetBang(ctctx CompileTimeCallContext, _ string, v *validate.ValidatedSetBang) error

CompileValidatedSetBang compiles a validated (set! name expr) form.

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) 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
	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   *NativeTemplate               // Compiled bytecode (for execution)
}

CompiledLibrary holds a loaded and compiled library.

func LoadLibrary

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. Finds the library file on the search path 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 ComposableContinuation

type ComposableContinuation struct {
	// contains filtered or unexported fields
}

ComposableContinuation is a callable value wrapping a delimited continuation segment (a chain of MachineContinuation frames) plus the captured winding stack. When applied, it splices its frames onto the current continuation, effectively composing the captured computation with the current one.

This implements Racket-style composable continuations as described in Flatt, Yu, Findler, Felleisen "Adding Delimited and Composable Control to a Production Programming Environment" (ICFP 2007).

func NewComposableContinuation

func NewComposableContinuation(cont *MachineContinuation, windingStack WindingStack, threadID uint64, barrierValid *BarrierToken) *ComposableContinuation

NewComposableContinuation creates a composable continuation from a continuation chain segment and the winding stack captured at the point of capture. barrierValid is mc.BarrierValid() at capture time; nil means the capture happened outside any with-continuation-barrier.

func (*ComposableContinuation) BarrierValid added in v1.4.0

func (p *ComposableContinuation) BarrierValid() *BarrierToken

BarrierValid returns the barrier identity token captured when this continuation was created. Used by applyComposableContinuation to detect barrier crossings.

func (*ComposableContinuation) Cont

func (*ComposableContinuation) EqualTo

func (p *ComposableContinuation) EqualTo(o values.Value) bool

func (*ComposableContinuation) IsVoid

func (p *ComposableContinuation) IsVoid() bool

func (*ComposableContinuation) SchemeString

func (p *ComposableContinuation) SchemeString() string

func (*ComposableContinuation) ThreadID added in v1.1.0

func (p *ComposableContinuation) ThreadID() uint64

func (*ComposableContinuation) WindingStack

func (p *ComposableContinuation) WindingStack() WindingStack

type Debugger

type Debugger struct {
	// contains filtered or unexported fields
}

Debugger manages breakpoints and stepping.

func NewDebugger

func NewDebugger() *Debugger

NewDebugger creates a new debugger.

func (*Debugger) Breakpoints

func (p *Debugger) Breakpoints() []*Breakpoint

Breakpoints returns all breakpoints.

func (*Debugger) CheckBreakpoint

func (p *Debugger) CheckBreakpoint(mc *MachineContext) *Breakpoint

CheckBreakpoint checks if execution should break at current location.

func (*Debugger) Continue

func (p *Debugger) Continue()

Continue resumes execution.

func (*Debugger) DisableBreakpoint

func (p *Debugger) DisableBreakpoint(id BreakpointID) bool

DisableBreakpoint disables a breakpoint.

func (*Debugger) EnableBreakpoint

func (p *Debugger) EnableBreakpoint(id BreakpointID) bool

EnableBreakpoint enables a breakpoint.

func (*Debugger) IsStepping

func (p *Debugger) IsStepping() bool

IsStepping returns whether the debugger is in stepping mode.

func (*Debugger) OnBreak

func (p *Debugger) OnBreak(fn func(mc *MachineContext, bp *Breakpoint))

OnBreak sets the callback for when a breakpoint is hit.

func (*Debugger) RemoveBreakpoint

func (p *Debugger) RemoveBreakpoint(id BreakpointID) bool

RemoveBreakpoint removes a breakpoint.

func (*Debugger) SetBreakpoint

func (p *Debugger) SetBreakpoint(file string, line, column int) BreakpointID

SetBreakpoint adds a breakpoint at the given source location.

func (*Debugger) ShouldStep

func (p *Debugger) ShouldStep(mc *MachineContext) bool

ShouldStep checks if we should break due to stepping.

func (*Debugger) StepInto

func (p *Debugger) StepInto()

StepInto enables step-into mode.

func (*Debugger) StepOut

func (p *Debugger) StepOut(mc *MachineContext)

StepOut enables step-out mode.

func (*Debugger) StepOver

func (p *Debugger) StepOver(mc *MachineContext)

StepOver enables step-over mode.

func (*Debugger) TriggerBreak

func (p *Debugger) TriggerBreak(mc *MachineContext, bp *Breakpoint)

TriggerBreak calls the break callback if set.

type DynamicWindFrame

type DynamicWindFrame struct {
	Before *MachineClosure // Called when entering this extent
	After  *MachineClosure // Called when exiting this extent
	ID     uint64          // Unique identifier for extent matching
}

DynamicWindFrame represents a single dynamic-wind extent. Each frame tracks the before/after thunks for one dynamic-wind call.

R7RS §6.10: dynamic-wind establishes a dynamic extent during which the before and after thunks are called whenever control enters or exits.

func NewDynamicWindFrame

func NewDynamicWindFrame(before, after *MachineClosure) *DynamicWindFrame

NewDynamicWindFrame creates a new winding frame with a unique ID.

type ErrExceptionEscape

type ErrExceptionEscape struct {
	Condition    values.Value          // The raised condition/object
	Continuable  bool                  // Whether handler can return
	Continuation *MachineContinuation  // Return point for continuable exceptions
	Handled      bool                  // Set true after handler processes it
	WindingStack WindingStack          // Winding stack at raise point (for proper unwinding)
	Source       *syntax.SourceContext // Source location where exception was raised
	StackTrace   StackTrace            // VM stack trace at raise point
}

ErrExceptionEscape signals an exception being raised through the call stack. It is used by raise and raise-continuable to propagate exceptions to handlers.

func (*ErrExceptionEscape) Error

func (p *ErrExceptionEscape) Error() string

Error implements the error interface.

When Source is present and the condition is a NativeError, produces clean human-readable output like "file:5:3: error: division by zero". For non-NativeError conditions with Source, produces "file:5:3: exception: foo". When no Source is set, falls back to the original format for backward compat.

func (*ErrExceptionEscape) Unwrap added in v1.3.0

func (p *ErrExceptionEscape) Unwrap() error

Unwrap returns the underlying error when the condition implements the error interface (e.g., *NativeError). This enables errors.Is/errors.As to traverse through ErrExceptionEscape into the wrapped error chain, supporting sentinel matching like errors.Is(err, values.ErrDivisionByZero) from Go callers.

type ErrExitEscape added in v1.4.0

type ErrExitEscape struct {
	Value values.Value
	// contains filtered or unexported fields
}

ErrExitEscape is returned by call-with-exit escape closures to signal an upward escape from the dynamic extent of call-with-exit. Like ErrPromptAbort, it propagates through the call stack without being wrapped as a Scheme exception (OperationForeignFunctionCall passes it through unchanged).

PrimCallWithExit matches it by comparing the tag pointer. The validity check (*atomic.Bool) in the escape closure ensures stale tags are never emitted.

func NewErrExitEscape added in v1.4.0

func NewErrExitEscape(tag *ExitTag, val values.Value) *ErrExitEscape

NewErrExitEscape creates an ErrExitEscape with the given tag and escape value. Only the call-with-exit invocation that created the matching *ExitTag will catch it.

func (*ErrExitEscape) Error added in v1.4.0

func (e *ErrExitEscape) Error() string

func (*ErrExitEscape) Tag added in v1.4.0

func (e *ErrExitEscape) Tag() *ExitTag

Tag returns the opaque tag identifying which call-with-exit invocation this escape belongs to. PrimCallWithExit uses pointer comparison to match its own tag.

type ErrPromptAbort

type ErrPromptAbort struct {
	Tag    *PromptTag
	Values []values.Value
}

ErrPromptAbort signals an abort to the nearest continuation prompt matching the given tag. It propagates up through Run() and is caught by RunWithEscapeHandling() or by call-with-continuation-prompt sub-contexts.

When caught, the handler finds the matching prompt frame, unwinds dynamic-wind extents, and invokes the prompt's handler with the abort values.

func (*ErrPromptAbort) Error

func (p *ErrPromptAbort) Error() string

type ExceptionHandler

type ExceptionHandler struct {
	// contains filtered or unexported fields
}

ExceptionHandler represents an installed exception handler. Handlers form a linked list (stack) for dynamic exception handling. When an exception is raised, handlers are invoked in reverse order of installation (most recent first).

func NewExceptionHandler

func NewExceptionHandler(handler values.Value, parent *ExceptionHandler) *ExceptionHandler

NewExceptionHandler creates a new exception handler with the given handler procedure and parent handler.

func (*ExceptionHandler) Handler

func (p *ExceptionHandler) Handler() values.Value

Handler returns the handler procedure.

func (*ExceptionHandler) Parent

func (p *ExceptionHandler) Parent() *ExceptionHandler

Parent returns the previous handler in the chain.

type ExitTag added in v1.4.0

type ExitTag struct{}

ExitTag is an opaque identity type for call-with-exit escape closures. Each call-with-exit invocation creates a unique *ExitTag; pointer equality identifies which escape closure belongs to which invocation. ExitTag has no exported fields or methods — it exists solely as a unique pointer identity.

Inspired by S7 Scheme's call-with-exit.

func NewExitTag added in v1.4.0

func NewExitTag() *ExitTag

NewExitTag creates a new unique exit tag for one call-with-exit invocation.

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 MachineContext when invoking macro transformers, enabling syntax-local-* primitives.

func NewExpanderContext

func NewExpanderContext(
	ctx context.Context,
	env *environment.EnvironmentFrame,
	expander *ExpanderTimeContinuation,
) *ExpanderContext

NewExpanderContext creates a new ExpanderContext.

func (*ExpanderContext) Env

Env returns the environment frame associated with this context.

func (*ExpanderContext) Expand

Expand fully expands a syntax object.

func (*ExpanderContext) ExpandOnce

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(env *environment.EnvironmentFrame) *ExpanderTimeContinuation

NewExpanderTimeContinuation creates a new ExpanderTimeContinuation.

func (*ExpanderTimeContinuation) ExpandBodyWithDefineSyntax

func (p *ExpanderTimeContinuation) ExpandBodyWithDefineSyntax(
	ctx context.Context,
	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

ExpandExpression expands a syntax expression.

func (*ExpanderTimeContinuation) ExpandOnce

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(ctx context.Context, 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) ExpandQuasiquote

ExpandQuasiquote handles the expansion of quasiquoted expressions.

func (*ExpanderTimeContinuation) ExpandQuote

ExpandQuote handles the expansion of quoted expressions.

func (*ExpanderTimeContinuation) ExpandSelfEvaluating

func (p *ExpanderTimeContinuation) ExpandSelfEvaluating(_ context.Context, expr syntax.SyntaxValue) (syntax.SyntaxValue, error)

ExpandSelfEvaluating handles self-evaluating expressions.

func (*ExpanderTimeContinuation) ExpandSymbol

ExpandSymbol handles a symbol expression.

func (*ExpanderTimeContinuation) ExpandSyntaxArgumentList

func (p *ExpanderTimeContinuation) ExpandSyntaxArgumentList(ctx context.Context, 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(ctx context.Context, 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:

  1. Look up the symbol in the expand environment
  2. If bound with BindingTypeSyntax, it's a macro - invoke the transformer
  3. If it's a primitive (like quote, if, define-syntax), don't expand args
  4. Otherwise, treat as procedure call and expand arguments

The transformer closure (MachineClosure from CompileSyntaxRules) is invoked by creating a 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(ctx context.Context, 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 FeatureRequirement

type FeatureRequirement interface {
	// IsSatisfied returns true if this requirement is satisfied.
	// The registry parameter is used to check library availability.
	IsSatisfied(registry *LibraryRegistry) 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 ForeignFunction

type ForeignFunction func(ctx context.Context, mc *MachineContext) error

type FreeIdResolution

type FreeIdResolution struct {
	// Global is set if the free identifier refers to a global binding.
	// This enables cross-library macro hygiene by pre-resolving the binding.
	Global *environment.GlobalIndex
	// LocalScopes is set if the free identifier refers to a local binding.
	// These are the scopes of the binding at macro definition time.
	// During expansion, the free identifier gets these scopes, ensuring
	// it resolves to the definition-time binding (not a shadowing binding).
	LocalScopes []*syntax.Scope
	// HasLocalBinding is true if a local binding was found at macro definition time,
	// even if the binding has no scopes. This distinguishes "local binding with empty
	// scopes" from "no binding at all" - the former should NOT get intro scope added
	// during expansion, while the latter might (for special forms).
	HasLocalBinding bool
}

FreeIdResolution stores the resolution info for a free identifier in a macro template. Free identifiers can be resolved to either global bindings (via GlobalIndex) or local bindings (via their scope set at macro definition time).

This type implements the localScopesProvider, globalBindingProvider, and hasLocalBindingProvider interfaces used by the match package's expansion functions to handle hygiene without circular imports.

func (*FreeIdResolution) GetGlobal

func (p *FreeIdResolution) GetGlobal() *environment.GlobalIndex

GetGlobal returns the global binding's index, or nil if this is a local binding. Implements the globalBindingProvider interface for match package hygiene.

func (*FreeIdResolution) GetHasLocalBinding

func (p *FreeIdResolution) GetHasLocalBinding() bool

GetHasLocalBinding returns true if a local binding was found at macro definition time. This is used to distinguish "local binding with empty scopes" from "no binding at all". Implements the hasLocalBindingProvider interface.

func (*FreeIdResolution) GetLocalScopes

func (p *FreeIdResolution) GetLocalScopes() []*syntax.Scope

GetLocalScopes returns the local binding's scopes, or nil if this is a global binding. Implements the localScopesProvider interface for match package hygiene.

type ImportSet

type ImportSet struct {
	LibraryName LibraryName       // Base library to import from
	Only        []string          // If non-nil, only import these names
	Except      []string          // 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

func ParseImportSetFromDatum(ctx context.Context, expr values.Value) (*ImportSet, error)

ParseImportSetFromDatum parses an import set from a datum value. This is for runtime use by the 'environment' procedure. 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 InlinedOperation added in v1.4.0

type InlinedOperation interface {
	Operation
	Apply(ctx context.Context, mc *MachineContext) (*MachineContext, error)
}

InlinedOperation is the interface for operations dispatched through the side table via OpComplex. These operations carry their own Apply method because the Run() loop delegates to them rather than inlining the logic.

type Instruction added in v1.4.0

type Instruction struct {
	Op  OpCode
	Arg int32
}

Instruction is a single VM instruction for the switch-dispatch loop. Op selects the operation; Arg carries an immediate operand whose meaning depends on Op:

  • Zero-operand ops (Push, Pop, ...): Arg is unused (0).
  • Single-operand ops (Branch, LoadLiteral, ...): Arg is the offset, index, or depth.
  • Two-operand ops (LoadLocal, StoreLocal): Arg is bit-packed (slot in low 16, depth in high 16).
  • OpComplex: Arg is the index into the template's sideTable.

Size: 8 bytes (uint16 Op + 2 bytes padding + int32 Arg).

func (Instruction) String added in v1.4.0

func (instr Instruction) String() string

String returns a human-readable representation of the instruction.

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 NewLibraryName

func NewLibraryName(parts ...string) LibraryName

NewLibraryName creates a LibraryName from a list of string parts.

func ParseLibraryNameFromDatum

func ParseLibraryNameFromDatum(ctx context.Context, expr values.Value) (LibraryName, error)

ParseLibraryNameFromDatum extracts a LibraryName from a datum list like (scheme base). This is for runtime use by the 'environment' procedure.

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) ToFilePath

func (p LibraryName) ToFilePath() string

ToFilePath converts a library name to a file path. (scheme base) -> "scheme/base.sld"

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) AddSearchPath

func (p *LibraryRegistry) AddSearchPath(path string)

AddSearchPath adds a path to the beginning of the search path list.

func (*LibraryRegistry) FindLibraryFile

func (p *LibraryRegistry) FindLibraryFile(name LibraryName) (string, error)

FindLibraryFile searches for a library file in the search paths. Returns the full path to the file, or an error if not found.

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) 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) Register

func (p *LibraryRegistry) Register(lib *CompiledLibrary) error

Register adds a compiled library to the registry.

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 LiteralIndex

type LiteralIndex int

type MachineClosure

type MachineClosure struct {
	// contains filtered or unexported fields
}

func CompileSyntaxRules

func CompileSyntaxRules(ctx context.Context, env *environment.EnvironmentFrame, syntaxRulesForm syntax.SyntaxValue) (*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:

  1. Parse optional custom ellipsis identifier
  2. Parse the literals list - these symbols are matched literally, not as variables
  3. For each clause, identify pattern variables (symbols not in literals list)
  4. Compile each pattern to bytecode (see match/syntax_compiler.go)
  5. Create a 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 NewClosureWithTemplate

func NewClosureWithTemplate(tpl *NativeTemplate, env *environment.EnvironmentFrame) *MachineClosure

func NewForeignClosure

func NewForeignClosure(env *environment.EnvironmentFrame, pcnt int, vardiac bool, fn ForeignFunction) *MachineClosure

func (*MachineClosure) Copy

func (p *MachineClosure) Copy() *MachineClosure

func (*MachineClosure) EqualTo

func (p *MachineClosure) EqualTo(o values.Value) bool

func (*MachineClosure) IsVoid

func (p *MachineClosure) IsVoid() bool

func (*MachineClosure) SchemeString

func (p *MachineClosure) SchemeString() string

func (*MachineClosure) Template

func (p *MachineClosure) Template() *NativeTemplate

type MachineContext

type MachineContext struct {
	// contains filtered or unexported fields
}

MachineContext represents the execution context of a virtual machine. It holds the current environment, values, evaluation stack, continuation, and program counter. It is created from a MachineContinuation and can be modified during execution.

func NewMachineContext

func NewMachineContext(ctx context.Context, cont *MachineContinuation) *MachineContext

NewMachineContext creates a new machine context with the given context and continuation. The context enables cancellation/timeout support in the VM loop. For callers that don't need cancellation, pass context.Background().

func NewMachineContextFromMachineClosure

func NewMachineContextFromMachineClosure(ctx context.Context, cls *MachineClosure) *MachineContext

func NewThreadSubContext added in v1.3.0

func NewThreadSubContext(params SubContextParams, thread *values.Thread) *MachineContext

NewThreadSubContext creates a sub-context for a thread using previously captured parent state. Unlike NewSubContext, this doesn't access the parent MachineContext fields, making it safe to call from a different goroutine. The thread parameter should be the new thread object, which provides the thread identity for the new context.

This function is specifically designed for SRFI-18 thread creation. For other uses of sub-contexts (like map, for-each, dynamic-wind), use NewSubContext instead.

func (*MachineContext) Apply

func (p *MachineContext) Apply(mcls *MachineClosure, vs ...values.Value) (*MachineContext, error)

func (*MachineContext) ApplyCallable added in v1.2.0

func (p *MachineContext) ApplyCallable(callable values.Value, args ...values.Value) (*MachineContext, error)

ApplyCallable dispatches a procedure call to the appropriate handler based on the callee's concrete type. This is the unified entry point for all Scheme procedure application, symmetric with OperationApply.

Supported callable types:

  • *MachineClosure: standard Scheme lambda
  • *CaseLambdaClosure: R7RS case-lambda (§4.2.9)
  • *Parameter: R7RS parameter object (§4.2.6)
  • *ComposableContinuation: delimited continuation

Precondition: p.ctx must be set (always true for contexts created via NewMachineContext or NewSubContext).

func (*MachineContext) ApplyCaseLambda

func (p *MachineContext) ApplyCaseLambda(clcls *CaseLambdaClosure, vs ...values.Value) (*MachineContext, error)

ApplyCaseLambda applies a case-lambda closure by finding the matching clause.

func (*MachineContext) Arg

func (p *MachineContext) Arg(index int) values.Value

func (*MachineContext) BarrierValid added in v1.4.0

func (p *MachineContext) BarrierValid() *BarrierToken

BarrierValid returns the barrier validity flag for the current context. Non-nil means execution is inside a with-continuation-barrier; the pointer identity distinguishes which barrier. Nil means no active barrier.

Escape closures and composable continuations use this to detect barrier crossings: if the capture-time pointer differs from the invocation-time pointer, the continuation would cross a barrier boundary.

func (*MachineContext) CallDepth

func (p *MachineContext) CallDepth() int

CallDepth returns the depth of the current continuation stack.

func (*MachineContext) CaptureStackTrace

func (p *MachineContext) CaptureStackTrace(maxDepth int) StackTrace

CaptureStackTrace walks the continuation chain and builds a stack trace.

func (*MachineContext) CaptureSubContextParams added in v1.3.0

func (p *MachineContext) CaptureSubContextParams() SubContextParams

CaptureSubContextParams extracts the state needed to create a sub-context in a different goroutine. This is used by thread creation to avoid race conditions when accessing the parent MachineContext from a child goroutine (T4 from architectural review).

Call this in the parent goroutine before creating the child goroutine, then pass the result to NewThreadSubContext in the child goroutine.

func (*MachineContext) Context

func (p *MachineContext) Context() context.Context

Context returns the context for this machine context.

func (*MachineContext) Counters added in v1.1.0

func (p *MachineContext) Counters() VMCounters

Counters returns a snapshot of the performance counters for this context.

func (*MachineContext) CurrentContinuation

func (p *MachineContext) CurrentContinuation() *MachineContinuation

func (*MachineContext) CurrentSource

func (p *MachineContext) CurrentSource() *syntax.SourceContext

CurrentSource returns the source location for the current execution point. When the current template has no source (e.g., inside a foreign function), walks up the continuation chain to find the nearest call site with source info. Continuation PCs are return addresses (one past the call), so pc-1 gives the call site.

func (*MachineContext) Debugger

func (p *MachineContext) Debugger() *Debugger

Debugger returns the attached debugger, or nil if none.

func (*MachineContext) EnvironmentFrame

func (p *MachineContext) EnvironmentFrame() *environment.EnvironmentFrame

func (*MachineContext) Error

func (p *MachineContext) Error(msg string) *SchemeError

Error creates a SchemeError with the current source location and stack trace.

func (*MachineContext) EscapeCont

func (p *MachineContext) EscapeCont() *MachineContinuation

EscapeCont returns the escape continuation for this context. This is set by foreign functions (like dynamic-wind) that need call/cc inside their sub-contexts to know where to continue after completion.

func (*MachineContext) ExceptionHandler

func (p *MachineContext) ExceptionHandler() *ExceptionHandler

ExceptionHandler returns the current exception handler chain.

func (*MachineContext) ExpanderContext

func (p *MachineContext) ExpanderContext() *ExpanderContext

ExpanderContext returns the expander context, or nil if not in expansion context.

func (*MachineContext) FindPrompt

func (p *MachineContext) FindPrompt(tag *PromptTag) (*MachineContinuation, bool)

FindPrompt walks the continuation chain to find the nearest frame with a matching prompt tag. Also checks the context's own prompt tag (set by call-with-continuation-prompt on sub-contexts). Returns the matching frame and true, or nil and false.

When the prompt is on the context itself (not a continuation frame), returns nil and true — the caller should treat this as "prompt at the boundary of this sub-context" and slice the entire continuation chain.

func (*MachineContext) GetValue

func (p *MachineContext) GetValue() values.Value

GetValue returns the first (or only) value from the value register. Returns Void if the register is empty.

func (*MachineContext) GetValues

func (p *MachineContext) GetValues() MultipleValues

GetValues returns all values from the value register as a MultipleValues slice. For the single-value case this allocates a one-element slice; callers on the hot path should use GetValue instead.

func (*MachineContext) MaxCallDepth added in v1.3.0

func (p *MachineContext) MaxCallDepth() uint64

MaxCallDepth returns the maximum call depth limit. 0 means unlimited.

func (*MachineContext) NewSubContext

func (p *MachineContext) NewSubContext() *MachineContext

NewSubContext creates a new MachineContext for running sub-calls (e.g., apply, map, for-each). The sub-context shares the global environment but has a fresh call stack, eval stack, and value register. This allows foreign functions to call Scheme closures without corrupting the parent context's state.

Note: Sub-contexts have isolated continuation chains (cont = nil). When call/cc captures a continuation inside a sub-context, it captures mc.Parent() which refers to the sub-context's chain (nil). For continuations to escape back to the outer context, the escape error propagates up through the call stack and is handled by RunWithEscapeHandling at the top level.

The parentMC field tracks the parent context, allowing call/cc to find an outer continuation for proper R7RS continuation semantics when captured inside sub-contexts.

The escapeCont field is inherited, allowing nested sub-contexts to know where execution should continue after their completion (set by dynamic-wind and similar constructs).

func (*MachineContext) PC

func (p *MachineContext) PC() int

func (*MachineContext) Parent

func (p *MachineContext) Parent() *MachineContinuation

func (*MachineContext) ParentMC

func (p *MachineContext) ParentMC() *MachineContext

ParentMC returns the parent machine context (for sub-contexts), or nil for top-level contexts.

func (*MachineContext) PopContinuation

func (p *MachineContext) PopContinuation() *MachineContinuation

PopContinuation pops the current continuation from the machine context and returns it. It restores the machine context to the state saved in the popped continuation.

Note: Unlike Restore(), we do NOT copy evals here because PopContinuation is used for normal function return where the continuation is consumed once. Restore() is used for continuation re-entry (call/cc) where the same continuation may be invoked multiple times, requiring the copy to prevent stack corruption.

func (*MachineContext) PopExceptionHandler

func (p *MachineContext) PopExceptionHandler() *ExceptionHandler

PopExceptionHandler pops the current exception handler from the stack and returns it. Returns nil if no handler is installed.

func (*MachineContext) PopWindingFrame

func (p *MachineContext) PopWindingFrame() *DynamicWindFrame

PopWindingFrame removes the innermost frame from the winding stack.

func (*MachineContext) PromptTag

func (p *MachineContext) PromptTag() *PromptTag

PromptTag returns the prompt tag for this context, or nil.

func (*MachineContext) PushExceptionHandler

func (p *MachineContext) PushExceptionHandler(handler values.Value)

PushExceptionHandler pushes a new exception handler onto the handler stack.

func (*MachineContext) PushWindingFrame

func (p *MachineContext) PushWindingFrame(frame *DynamicWindFrame)

PushWindingFrame adds a frame to the winding stack.

func (*MachineContext) Restore

func (p *MachineContext) Restore(cont *MachineContinuation)

func (*MachineContext) RestoreAndRelease added in v1.4.0

func (p *MachineContext) RestoreAndRelease(cont *MachineContinuation)

RestoreAndRelease is the fast path for normal function return. It transfers the continuation's state into the MachineContext (like Restore) but avoids copying evals — instead it transfers ownership directly and pools the consumed frame. This is safe because normal return consumes the frame exactly once; call/cc and escape paths must use Restore (which copies).

Shared frames (marked by MarkChainShared during call/cc capture) cannot be pooled because a captured continuation may re-invoke them. For shared frames, evals are copied (like Restore) and the frame is left for GC instead of pooling.

The sequence for unshared frames:

  1. Release mc's current evals to the stack pool (it's dead after restore)
  2. Transfer cont's evals directly to mc (no copy)
  3. Nil cont.evals so releaseContinuation won't double-release it
  4. Pool the consumed continuation frame

func (*MachineContext) RestoreWithWinding

func (p *MachineContext) RestoreWithWinding(cont *MachineContinuation, targetStack WindingStack) error

RestoreWithWinding restores a continuation with proper dynamic-wind handling. It unwinds from the current dynamic extent, rewinds to the target extent, then restores the machine state.

If cont is nil (continuation captured in a sub-context), we still perform the winding operations but don't restore machine state - the caller should handle continued execution appropriately.

func (*MachineContext) RestoreWithWindingFrom

func (p *MachineContext) RestoreWithWindingFrom(cont *MachineContinuation, sourceStack, targetStack WindingStack) error

RestoreWithWindingFrom restores a continuation with proper dynamic-wind handling, using an explicit source winding stack instead of the current context's stack.

This is needed when the escape originated from a sub-context that has a different winding stack than the context where RestoreWithWinding is called. For example, when call/cc captures inside a sub-context and the escape propagates up, the source winding stack (where the escape happened) may have frames that the top-level context doesn't know about.

Parameters:

  • cont: The continuation to restore to
  • sourceStack: The winding stack where the escape originated (for unwinding)
  • targetStack: The winding stack to restore to (for rewinding)

func (*MachineContext) RewindTo

func (p *MachineContext) RewindTo(target WindingStack, commonDepth int) error

RewindTo runs before thunks from common ancestor to target depth. Returns error if any before thunk fails.

func (*MachineContext) Run

func (p *MachineContext) Run() error

Run executes the VM loop starting from the current pc. The pc is NOT reset here - callers are responsible for ensuring the correct initial pc:

  • NewMachineContext copies pc from the continuation (typically 0 for fresh execution)
  • Apply sets pc = 0 for fresh closure invocation
  • Restore sets pc from the saved continuation for resumption

This design allows continuation resumption (e.g., raise-continuable) to work correctly by preserving the pc set by Restore rather than unconditionally resetting to 0.

Dispatch: Run always uses switch-dispatch over integer opcodes.

Context cancellation: The loop checks p.ctx.Done() every 1024 ops, allowing preemption via context.WithTimeout or context.WithCancel. This enables:

  • Test timeouts that actually stop execution
  • REPL interrupt support (Ctrl+C)
  • Resource management for long-running computations

Run executes the VM loop using switch-dispatch with integer opcodes. Hot-path operations (Wave 1-3) are inlined as switch cases; complex operations (closures, macros, FFI) are dispatched via OpComplex to the template's sideTable.

Set the context via SetContext() before calling Run().

func (*MachineContext) RunWithEscapeHandling

func (p *MachineContext) RunWithEscapeHandling() error

RunWithEscapeHandling runs the VM loop, handling continuation escapes that weren't caught by an enclosing call/cc. This is used at the top level (REPL and file execution) to catch continuations invoked outside their original dynamic extent.

When a continuation captured inside a foreign function (like dynamic-wind's thunk) is invoked from outside, the escape error propagates up. This method catches it and restores the continuation with proper dynamic-wind handling.

For continuations captured inside sub-contexts (like dynamic-wind thunks):

  • Continuation: the inner state (inside the thunk)
  • EscapeCont: the outer continuation (after the original sub-context would have completed)

After the inner execution completes and unwinds, if there's a pending escape continuation, execution continues from there.

When execution completes normally (Run returns nil), any remaining frames on the winding stack are unwound (after thunks are called).

func (*MachineContext) SaveContinuation

func (p *MachineContext) SaveContinuation(off int) error

SaveContinuation pushes a new continuation onto the machine context with the given offset to the current program counter. Returns ErrCallDepthExceeded if the call depth limit has been reached.

Note: callDepth is incremented BEFORE calling NewMachineContinuationFromMachineContext. The continuation's own callDepth is derived from mc.cont (the parent pointer), not from mc.callDepth, so this pre-increment does not affect the continuation's cached depth. See the comment on NewMachineContinuationFromMachineContext for why this matters.

func (*MachineContext) SetBarrierValid added in v1.4.0

func (p *MachineContext) SetBarrierValid(v *BarrierToken)

SetBarrierValid sets the barrier identity token on this context. Called by PrimCallWithContinuationBarrier to mark the sub-context as inside a barrier.

func (*MachineContext) SetContext

func (p *MachineContext) SetContext(ctx context.Context)

SetContext sets the context for this machine context. This should be called before Run() to enable context cancellation/timeout.

func (*MachineContext) SetDebugger

func (p *MachineContext) SetDebugger(d *Debugger)

SetDebugger attaches a debugger to this context.

func (*MachineContext) SetEscapeCont

func (p *MachineContext) SetEscapeCont(cont *MachineContinuation)

SetEscapeCont sets the escape continuation for this context.

func (*MachineContext) SetExceptionHandler

func (p *MachineContext) SetExceptionHandler(h *ExceptionHandler)

SetExceptionHandler sets the exception handler chain.

func (*MachineContext) SetExpanderContext

func (p *MachineContext) SetExpanderContext(ctx *ExpanderContext)

SetExpanderContext sets the expander context for this machine context. This is called when invoking macro transformers to enable syntax-local-* primitives.

func (*MachineContext) SetMaxCallDepth added in v1.3.0

func (p *MachineContext) SetMaxCallDepth(n uint64)

SetMaxCallDepth sets the maximum call depth limit. 0 means unlimited.

func (*MachineContext) SetPC

func (p *MachineContext) SetPC(v int)

SetPC sets the program counter. Used by PrimCallCC for inline lambda execution.

func (*MachineContext) SetPromptTag

func (p *MachineContext) SetPromptTag(tag *PromptTag)

SetPromptTag sets the prompt tag on this context. Used by call-with-continuation-prompt to mark sub-contexts as prompt boundaries.

func (*MachineContext) SetThread added in v1.1.0

func (p *MachineContext) SetThread(t *values.Thread)

SetThread sets the SRFI-18 thread identity on this context. Both the thread object and its ID are stored for efficient comparison.

func (*MachineContext) SetValue

func (p *MachineContext) SetValue(v values.Value)

SetValue stores a single value in the value register without allocating. This is the hot path: every LoadLocal, LoadGlobal, LoadLiteral, Pull, Pop, MakeClosure, etc. goes through here.

func (*MachineContext) SetValues

func (p *MachineContext) SetValues(vs ...values.Value)

SetValues sets the value register. For a single value this uses the zero-allocation fast path (singleValue); for multiple values it falls back to the multiValues slice.

func (*MachineContext) SetWindingStack

func (p *MachineContext) SetWindingStack(stack WindingStack)

SetWindingStack sets the winding stack (used by sub-contexts).

func (*MachineContext) SliceContinuationAt

func (p *MachineContext) SliceContinuationAt(prompt *MachineContinuation) *MachineContinuation

SliceContinuationAt deep-copies the continuation chain segment from p.cont down to (but not including) the prompt frame. The returned chain's bottom frame has parent = nil, making it a standalone segment suitable for composable continuation capture.

func (*MachineContext) Template

func (p *MachineContext) Template() *NativeTemplate

func (*MachineContext) Thread added in v1.1.0

func (p *MachineContext) Thread() *values.Thread

Thread returns the SRFI-18 thread object for this context, or nil for the primordial thread.

func (*MachineContext) ThreadID added in v1.1.0

func (p *MachineContext) ThreadID() uint64

ThreadID returns the SRFI-18 thread ID for this context. 0 means the primordial thread (main goroutine).

func (*MachineContext) UnwindTo

func (p *MachineContext) UnwindTo(commonDepth int) error

UnwindTo runs after thunks from innermost to the common ancestor. Returns error if any after thunk fails.

func (*MachineContext) WindingStack

func (p *MachineContext) WindingStack() WindingStack

WindingStack returns the current winding stack.

func (*MachineContext) WrapError

func (p *MachineContext) WrapError(err error, msg string) *SchemeError

WrapError wraps an existing error with the current source location and stack trace.

type MachineContinuation

type MachineContinuation struct {
	// contains filtered or unexported fields
}

func NewMachineContinuation

func NewMachineContinuation(parent *MachineContinuation, tpl *NativeTemplate, env *environment.EnvironmentFrame) *MachineContinuation

NewMachineContinuation creates a new machine continuation with the given parent, template, environment frame, and initial values.

func NewMachineContinuationFromMachineContext

func NewMachineContinuationFromMachineContext(mc *MachineContext, off int) *MachineContinuation

NewMachineContinuationFromMachineContext creates a new machine continuation from the given machine context and an offset to the program counter. The new continuation inherits the environment, template, and evaluation stack from the machine context.

callDepth derivation: the new frame's parent is mc.cont, so its depth is derived from mc.cont's cached depth — NOT from mc.callDepth. These values differ because SaveContinuation pre-increments mc.callDepth before calling this function, but other callers do not:

  • SaveContinuation: mc.callDepth already incremented → mc.callDepth != chain length
  • PrimCallCC sub-context path (prim_control.go): mc.callDepth == 0, mc.cont == nil
  • PrimDynamicWind escape cont (prim_control.go): mc.callDepth == chain length

Using mc.callDepth - 1 would uint64-underflow to 2^64-1 in the PrimCallCC case (callDepth is uint64). The parent-pointer formula is correct for all callers and immune to underflow.

func NewMachineContinuationWithPrompt

func NewMachineContinuationWithPrompt(parent *MachineContinuation, tpl *NativeTemplate, env *environment.EnvironmentFrame, tag *PromptTag, handler *MachineClosure) *MachineContinuation

NewMachineContinuationWithPrompt creates a continuation frame that acts as a continuation prompt. The tag identifies the prompt for abort/capture, and the handler is invoked when an abort reaches this prompt.

func (*MachineContinuation) CallDepth

func (p *MachineContinuation) CallDepth() int

CallDepth returns the depth of the continuation stack. The depth is cached in each frame at creation time, so this is O(1).

func (*MachineContinuation) Copy

func (*MachineContinuation) DeepCopy

DeepCopy creates a deep copy of the entire continuation chain. Each frame in the chain is copied, with parent pointers updated to point to the copied frames. This is needed for composable continuations which must be safely re-invoked multiple times.

func (*MachineContinuation) EnvironmentFrame

func (p *MachineContinuation) EnvironmentFrame() *environment.EnvironmentFrame

func (*MachineContinuation) EqualTo

func (p *MachineContinuation) EqualTo(o values.Value) bool

func (*MachineContinuation) IsVoid

func (p *MachineContinuation) IsVoid() bool

func (*MachineContinuation) MarkChainShared added in v1.4.0

func (p *MachineContinuation) MarkChainShared()

MarkChainShared marks every frame in the continuation chain as shared. Shared frames are not pooled by RestoreAndRelease — their evals are copied instead of transferred, preserving them for re-invocation.

Early-exits when a frame is already shared: all ancestors must already be shared from a prior capture (sharing propagates toward the root).

func (*MachineContinuation) PC

func (p *MachineContinuation) PC() int

func (*MachineContinuation) Parent

func (*MachineContinuation) PromptHandler

func (p *MachineContinuation) PromptHandler() *MachineClosure

func (*MachineContinuation) PromptTag

func (p *MachineContinuation) PromptTag() *PromptTag

func (*MachineContinuation) PushValues

func (p *MachineContinuation) PushValues(v ...values.Value)

PushValues appends values to the continuation's value register. If the register currently holds a single value, it is promoted to the multi-value representation before appending. This promote-then-append pattern avoids losing the existing single value when transitioning to the multi-value path.

func (*MachineContinuation) SchemeString

func (p *MachineContinuation) SchemeString() string

func (*MachineContinuation) SetPC

func (p *MachineContinuation) SetPC(v int)

func (*MachineContinuation) SetPromptHandler

func (p *MachineContinuation) SetPromptHandler(h *MachineClosure)

func (*MachineContinuation) SetPromptTag

func (p *MachineContinuation) SetPromptTag(t *PromptTag)

func (*MachineContinuation) Template

func (p *MachineContinuation) Template() *NativeTemplate

func (*MachineContinuation) ThreadID added in v1.1.0

func (p *MachineContinuation) ThreadID() uint64

type MultipleValues

type MultipleValues []values.Value

MultipleValues represents multiple return values from a function.

func NewMultipleValues

func NewMultipleValues(values ...values.Value) MultipleValues

NewMultipleValues creates a new MultipleValues from the given values.

func (MultipleValues) Copy

func (p MultipleValues) Copy() MultipleValues

Copy creates a copy of the MultipleValues.

func (MultipleValues) EqualTo

func (p MultipleValues) EqualTo(o values.Value) bool

EqualTo checks if the MultipleValues is equal to another value.

func (MultipleValues) IsVoid

func (p MultipleValues) IsVoid() bool

IsVoid returns true if the MultipleValues represents 'void' - either

func (MultipleValues) Len

func (p MultipleValues) Len() int

Len returns the number of values in the MultipleValues.

func (MultipleValues) SchemeString

func (p MultipleValues) SchemeString() string

SchemeString returns the Scheme representation of the MultipleValues.

type NativeTemplate

type NativeTemplate struct {
	// contains filtered or unexported fields
}

func NewEmptyNativeTemplate added in v1.2.0

func NewEmptyNativeTemplate() *NativeTemplate

NewEmptyNativeTemplate creates a new NativeTemplate with default empty parameters. This is used when a template is initialized without any known parameters or operations yet.

func NewNativeTemplate

func NewNativeTemplate(pcnt int, vcnt int, vd bool, operations ...Operation) *NativeTemplate

func (*NativeTemplate) AppendInstruction added in v1.4.0

func (p *NativeTemplate) AppendInstruction(instr Instruction)

AppendInstruction appends a single instruction with no source attribution.

func (*NativeTemplate) AppendInstructionWithSource added in v1.4.0

func (p *NativeTemplate) AppendInstructionWithSource(src *syntax.SourceContext, instr Instruction)

AppendInstructionWithSource appends a single instruction to the integer-dispatch bytecode and tags it with the given source context.

func (*NativeTemplate) AppendOperations

func (p *NativeTemplate) AppendOperations(ops ...Operation)

AppendOperations appends operations with no source attribution (index 0 = nil). Converts operations to instructions using AppendOperationsWithSource.

func (*NativeTemplate) AppendOperationsWithSource added in v1.4.0

func (p *NativeTemplate) AppendOperationsWithSource(src *syntax.SourceContext, ops ...Operation)

AppendOperationsWithSource converts operations to instructions and tags each with the given source. Wave 1-3 operations become direct switch cases; complex operations go through the sideTable and are dispatched via OpComplex. This is a public method for test use.

func (*NativeTemplate) AppendSideTableOp added in v1.4.0

func (p *NativeTemplate) AppendSideTableOp(op InlinedOperation) Instruction

AppendSideTableOp adds a complex operation to the side table and returns an OpComplex instruction that references it.

func (*NativeTemplate) Code added in v1.4.0

func (p *NativeTemplate) Code() []Instruction

Code returns the integer-dispatch bytecode slice.

func (*NativeTemplate) CodeLen added in v1.4.0

func (p *NativeTemplate) CodeLen() int

CodeLen returns the current code[] length (number of instructions emitted).

func (*NativeTemplate) Copy

func (p *NativeTemplate) Copy() *NativeTemplate

func (*NativeTemplate) DeduplicateLiteral

func (p *NativeTemplate) DeduplicateLiteral(v values.Value) values.Value

DeduplicateLiteral deduplicates the given value using the template's literal pool. For composite values (pairs and vectors), all elements are deduplicated recursively. Returns the deduplicated value.

func (*NativeTemplate) EffectiveOperations added in v1.4.0

func (p *NativeTemplate) EffectiveOperations() Operations

EffectiveOperations is an alias for Operations() for backward compatibility. Both return the reconstructed operation sequence from bytecode.

func (*NativeTemplate) EqualTo

func (p *NativeTemplate) EqualTo(o values.Value) bool

func (*NativeTemplate) IsVariadic

func (p *NativeTemplate) IsVariadic() bool

func (*NativeTemplate) IsVoid

func (p *NativeTemplate) IsVoid() bool

func (*NativeTemplate) MaybeAppendLiteral

func (p *NativeTemplate) MaybeAppendLiteral(v values.Value) LiteralIndex

func (*NativeTemplate) Name

func (p *NativeTemplate) Name() string

func (*NativeTemplate) NoCopyApply added in v1.4.0

func (p *NativeTemplate) NoCopyApply() bool

NoCopyApply returns true if Apply can reuse the closure's environment frame instead of copying it. This is safe when the template contains no OpSaveContinuation (which captures mc.env into the continuation chain) and no *OperationMakeClosure (which captures mc.env as a closure parent).

func (*NativeTemplate) Operations

func (p *NativeTemplate) Operations() Operations

Operations reconstructs the operation sequence from the bytecode. Converts Instructions back to Operation values for compatibility with existing code that expects Operations (e.g., tests, EqualTo).

func (*NativeTemplate) ParameterCount

func (p *NativeTemplate) ParameterCount() int

func (*NativeTemplate) PatchInstructionArg added in v1.4.0

func (p *NativeTemplate) PatchInstructionArg(codeIdx int, arg int32)

PatchInstructionArg updates the Arg field of the instruction at code[codeIdx]. Used for patching branch offsets and continuation save offsets after the target PC is known.

func (*NativeTemplate) SchemeString

func (p *NativeTemplate) SchemeString() string

func (*NativeTemplate) SetName

func (p *NativeTemplate) SetName(name string)

func (*NativeTemplate) SideTable added in v1.4.0

func (p *NativeTemplate) SideTable() []InlinedOperation

SideTable returns the complex operations referenced by OpComplex instructions.

func (*NativeTemplate) SourceAt

func (p *NativeTemplate) SourceAt(pc int) *syntax.SourceContext

SourceAt returns the source location for the operation at pc. Returns nil if pc is out of bounds or no source was recorded. O(1) lookup via the parallel sourceRefs array.

func (*NativeTemplate) ValueCount

func (p *NativeTemplate) ValueCount() int

type OpCode added in v1.4.0

type OpCode uint16

OpCode is an integer opcode for the switch-dispatch VM loop. Operations migrated from interface dispatch to integer dispatch get a dedicated OpCode. Complex operations that remain as interface values use OpComplex with a side table index.

const (
	OpInvalid OpCode = iota

	// Wave 1: zero-operand operations
	OpPush
	OpPop
	OpPull
	OpLoadVoid
	OpDrop
	OpPopEnv
	OpApply
	OpRestoreContinuation

	// Wave 2: single-operand operations (Arg = offset, index, or depth)
	OpBranchOnFalseValue
	OpBranch
	OpSaveContinuation
	OpLoadLiteral
	OpLoadGlobal
	OpStoreGlobal
	OpPeekK

	// Wave 3: two-operand operations (Arg = bit-packed slot|depth)
	OpLoadLocal
	OpStoreLocal

	// Fallback: dispatch to sideTable[Arg]
	OpComplex
)

func (OpCode) String added in v1.4.0

func (op OpCode) String() string

String returns the human-readable name of the opcode.

type Operation

type Operation interface {
	values.Value
}

Operation is the base interface for all bytecode operations. Every operation is also a values.Value so it can appear in the literals pool and be printed. Operations that are inlined into the Run() switch loop only need this base interface. Operations dispatched through the side table (OpComplex) must additionally implement InlinedOperation.

type OperationApply

type OperationApply struct {
	OperationBase
}

OperationApply is the bytecode operation that dispatches procedure calls. The compiler emits it after pushing arguments onto the eval stack and placing the callee in the value register. Apply pops all arguments and delegates to MachineContext.ApplyCallable, which handles the four callable types (MachineClosure, CaseLambdaClosure, Parameter, ComposableContinuation).

func NewOperationApply

func NewOperationApply() *OperationApply

NewOperationApply returns a new apply operation.

func (*OperationApply) EqualTo

func (p *OperationApply) EqualTo(o values.Value) bool

EqualTo returns true if o is also an OperationApply (identity by type).

type OperationBase added in v1.3.0

type OperationBase struct {
	// contains filtered or unexported fields
}

OperationBase provides default SchemeString, IsVoid, and String methods for VM operations. Embed as the first field in operation structs. EqualTo is intentionally not provided: Go requires per-type assertions.

func NewOperationBase added in v1.3.0

func NewOperationBase(opName string) OperationBase

NewOperationBase creates an OperationBase with the given Scheme name. The name is used as: "#<" + opName + ">".

func NewOperationBaseWithGoName added in v1.3.0

func NewOperationBaseWithGoName(opName, goName string) OperationBase

NewOperationBaseWithGoName creates an OperationBase with both a Scheme name and a separate Go fmt.Stringer name.

func (OperationBase) IsVoid added in v1.3.0

func (p OperationBase) IsVoid() bool

IsVoid returns false; operations are never void. Unlike other values.Value implementations, this does not handle nil receivers — operations are bytecode instructions constructed by the compiler and stored in NativeTemplate slices; they are never nil.

func (OperationBase) SchemeString added in v1.3.0

func (p OperationBase) SchemeString() string

SchemeString returns the Scheme representation of the operation.

func (OperationBase) String added in v1.3.0

func (p OperationBase) String() string

String returns the Go string representation of the operation.

type OperationBindPatternVars

type OperationBindPatternVars struct {
	OperationBase
	PatternVars []string // Ordered list for consistent indexing
}

OperationBindPatternVars binds pattern variables from the last match into a new local environment frame that is pushed onto the current environment.

This operation creates a new environment frame with local slots for each pattern variable, binds the matched values, and makes this the current environment.

func NewOperationBindPatternVars

func NewOperationBindPatternVars(patternVars map[string]struct{}) *OperationBindPatternVars

func (*OperationBindPatternVars) Apply

func (*OperationBindPatternVars) EqualTo

func (p *OperationBindPatternVars) EqualTo(other values.Value) bool

type OperationBranchOffsetImmediate

type OperationBranchOffsetImmediate struct {
	OperationBase
	Offset int
}

func NewOperationBranchOffsetImmediate

func NewOperationBranchOffsetImmediate(offset int) *OperationBranchOffsetImmediate

func (*OperationBranchOffsetImmediate) EqualTo

func (*OperationBranchOffsetImmediate) SchemeString

func (p *OperationBranchOffsetImmediate) SchemeString() string

SchemeString overrides OperationBase to include offset value.

type OperationBranchOnFalseValueOffsetImmediate added in v1.4.0

type OperationBranchOnFalseValueOffsetImmediate struct {
	OperationBase
	Offset int
}

OperationBranchOnFalseValueOffsetImmediate branches if the value register is #f. This reads directly from the value register instead of popping from the eval stack, eliminating the Push instruction that would otherwise be needed.

Peephole optimization (Aho et al., Compilers §8.9): examines a small window of generated instructions and replaces inefficient patterns. Here, the Push+BranchOnFalse+Pop sequence is replaced with a single BranchOnFalseValue that reads the value register directly. See BIBLIOGRAPHY.md "Peephole Optimization".

func NewOperationBranchOnFalseValueOffsetImmediate added in v1.4.0

func NewOperationBranchOnFalseValueOffsetImmediate(offset int) *OperationBranchOnFalseValueOffsetImmediate

func (*OperationBranchOnFalseValueOffsetImmediate) EqualTo added in v1.4.0

func (*OperationBranchOnFalseValueOffsetImmediate) SchemeString added in v1.4.0

SchemeString overrides OperationBase to include offset value.

type OperationBuildSyntaxList

type OperationBuildSyntaxList struct {
	OperationBase
	Count int
}

OperationBuildSyntaxList builds a syntax list from elements on the eval stack. n elements are popped from the stack (in reverse order) and consed into a list.

func NewOperationBuildSyntaxList

func NewOperationBuildSyntaxList(count int) *OperationBuildSyntaxList

NewOperationBuildSyntaxList creates a new OperationBuildSyntaxList.

func (*OperationBuildSyntaxList) Apply

Apply implements the Operation interface.

func (*OperationBuildSyntaxList) EqualTo

func (p *OperationBuildSyntaxList) EqualTo(other values.Value) bool

type OperationClearSyntaxCaseInput

type OperationClearSyntaxCaseInput struct {
	OperationBase
}

OperationClearSyntaxCaseInput clears the global syntax-case input. This is called at the end of a syntax-case form.

func NewOperationClearSyntaxCaseInput

func NewOperationClearSyntaxCaseInput() *OperationClearSyntaxCaseInput

func (*OperationClearSyntaxCaseInput) Apply

func (*OperationClearSyntaxCaseInput) EqualTo

func (p *OperationClearSyntaxCaseInput) EqualTo(other values.Value) bool

type OperationDrop

type OperationDrop struct {
	OperationBase
}

OperationDrop removes the top value from the eval stack without affecting the value register. This is used when we need to clean up the stack but preserve the current result.

func NewOperationDrop

func NewOperationDrop() *OperationDrop

func (*OperationDrop) EqualTo

func (p *OperationDrop) EqualTo(o values.Value) bool

type OperationForeignFunctionCall

type OperationForeignFunctionCall struct {
	OperationBase
	Function ForeignFunction
}

func NewOperationForeignFunctionCall

func NewOperationForeignFunctionCall(ffn ForeignFunction) *OperationForeignFunctionCall

func (*OperationForeignFunctionCall) Apply

func (*OperationForeignFunctionCall) EqualTo

type OperationLoadGlobalByGlobalIndexLiteralIndexImmediate

type OperationLoadGlobalByGlobalIndexLiteralIndexImmediate struct {
	OperationBase
	LiteralIndex LiteralIndex
}

OperationLoadGlobalByGlobalIndexLiteralIndexImmediate loads a global variable using an index from the literals pool.

func NewOperationLoadGlobalByGlobalIndexLiteralIndexImmediate

func NewOperationLoadGlobalByGlobalIndexLiteralIndexImmediate(li LiteralIndex) *OperationLoadGlobalByGlobalIndexLiteralIndexImmediate

NewOperationLoadGlobalByGlobalIndexLiteralIndexImmediate creates a new global load operation.

func (*OperationLoadGlobalByGlobalIndexLiteralIndexImmediate) EqualTo

EqualTo returns true if both operations have the same literal index.

func (*OperationLoadGlobalByGlobalIndexLiteralIndexImmediate) SchemeString

SchemeString returns the Scheme representation of the operation.

type OperationLoadLiteralByLiteralIndexImmediate

type OperationLoadLiteralByLiteralIndexImmediate struct {
	OperationBase
	LiteralIndex LiteralIndex
}

OperationLoadLiteralByLiteralIndexImmediate loads a literal value from the literals pool.

func NewOperationLoadLiteralByLiteralIndexImmediate

func NewOperationLoadLiteralByLiteralIndexImmediate(li LiteralIndex) *OperationLoadLiteralByLiteralIndexImmediate

NewOperationLoadLiteralByLiteralIndexImmediate creates a new literal load operation.

func (*OperationLoadLiteralByLiteralIndexImmediate) EqualTo

EqualTo returns true if both operations have the same literal index.

func (*OperationLoadLiteralByLiteralIndexImmediate) SchemeString

SchemeString returns the Scheme representation of the operation.

type OperationLoadLocalByLocalIndexImmediate

type OperationLoadLocalByLocalIndexImmediate struct {
	OperationBase
	LocalIndex *environment.LocalIndex
}

func (*OperationLoadLocalByLocalIndexImmediate) EqualTo

func (*OperationLoadLocalByLocalIndexImmediate) SchemeString

type OperationLoadVoid

type OperationLoadVoid struct {
	OperationBase
}

func NewOperationLoadVoid

func NewOperationLoadVoid() *OperationLoadVoid

func (*OperationLoadVoid) EqualTo

func (p *OperationLoadVoid) EqualTo(o values.Value) bool

type OperationMakeCaseLambdaClosure

type OperationMakeCaseLambdaClosure struct {
	OperationBase
	// contains filtered or unexported fields
}

OperationMakeCaseLambdaClosure creates a case-lambda closure from multiple closures. Stack layout (top to bottom): closure_n, closure_n-1, ..., closure_1 The closureCount immediate specifies how many closures to pop.

func NewOperationMakeCaseLambdaClosure

func NewOperationMakeCaseLambdaClosure(closureCount int) *OperationMakeCaseLambdaClosure

func (*OperationMakeCaseLambdaClosure) Apply

func (*OperationMakeCaseLambdaClosure) EqualTo

type OperationMakeClosure

type OperationMakeClosure struct {
	OperationBase
}

func NewOperationMakeClosure

func NewOperationMakeClosure() *OperationMakeClosure

func (*OperationMakeClosure) Apply

func (*OperationMakeClosure) EqualTo

func (p *OperationMakeClosure) EqualTo(o values.Value) bool

type OperationPeekK

type OperationPeekK struct {
	OperationBase
	Depth int
}

func NewOperationPeekK

func NewOperationPeekK(depth int) *OperationPeekK

func (*OperationPeekK) EqualTo

func (p *OperationPeekK) EqualTo(o values.Value) bool

func (*OperationPeekK) SchemeString

func (p *OperationPeekK) SchemeString() string

SchemeString overrides OperationBase to include depth value.

type OperationPop

type OperationPop struct {
	OperationBase
}

func NewOperationPop

func NewOperationPop() *OperationPop

func (*OperationPop) EqualTo

func (p *OperationPop) EqualTo(o values.Value) bool

type OperationPopEnv

type OperationPopEnv struct {
	OperationBase
}

OperationPopEnv unconditionally restores the parent environment. It pops one level from the environment chain (restoring the parent environment).

This is used in syntax-case fender evaluation to restore the environment when the fender returns false, before branching to the next clause.

func NewOperationPopEnv

func NewOperationPopEnv() *OperationPopEnv

func (*OperationPopEnv) EqualTo

func (p *OperationPopEnv) EqualTo(other values.Value) bool

type OperationPopWind

type OperationPopWind struct {
	OperationBase
}

OperationPopWind pops the innermost dynamic-wind frame from the winding stack. This operation does NOT call the after thunk - that is done explicitly in the bytecode stream to ensure proper continuation semantics.

The frame is simply removed from the winding stack. If a continuation captured inside the dynamic extent is later restored, the RestoreWithWinding mechanism will handle running the appropriate before/after thunks.

R7RS §6.10: dynamic-wind establishes a dynamic extent during which the before and after thunks are called whenever control enters or exits.

func NewOperationPopWind

func NewOperationPopWind() *OperationPopWind

func (*OperationPopWind) Apply

func (*OperationPopWind) EqualTo

func (p *OperationPopWind) EqualTo(o values.Value) bool

type OperationPull

type OperationPull struct {
	OperationBase
}

func NewOperationPull

func NewOperationPull() *OperationPull

func (*OperationPull) EqualTo

func (p *OperationPull) EqualTo(o values.Value) bool

type OperationPush

type OperationPush struct {
	OperationBase
}

func NewOperationPush

func NewOperationPush() *OperationPush

func (*OperationPush) EqualTo

func (p *OperationPush) EqualTo(o values.Value) bool

type OperationPushWind

type OperationPushWind struct {
	OperationBase
}

OperationPushWind creates a dynamic-wind frame and pushes it onto the winding stack. It expects the stack to contain [before, thunk, after] where:

  • before is at PeekK(2) - the before thunk
  • thunk is at PeekK(1) - the main thunk (not used by this operation)
  • after is at PeekK(0) - the after thunk

The frame is created from the before and after closures and pushed onto the winding stack. The stack is not modified.

R7RS §6.10: dynamic-wind establishes a dynamic extent during which the before and after thunks are called whenever control enters or exits.

func NewOperationPushWind

func NewOperationPushWind() *OperationPushWind

func (*OperationPushWind) Apply

func (*OperationPushWind) EqualTo

func (p *OperationPushWind) EqualTo(o values.Value) bool

type OperationRestoreContinuation

type OperationRestoreContinuation struct {
	OperationBase
}

func NewOperationRestoreContinuation

func NewOperationRestoreContinuation() *OperationRestoreContinuation

func (*OperationRestoreContinuation) EqualTo

type OperationSaveContinuationOffsetImmediate

type OperationSaveContinuationOffsetImmediate struct {
	OperationBase
	Offset int
}

func NewOperationSaveContinuationOffsetImmediate

func NewOperationSaveContinuationOffsetImmediate(off int) *OperationSaveContinuationOffsetImmediate

func (*OperationSaveContinuationOffsetImmediate) EqualTo

func (*OperationSaveContinuationOffsetImmediate) SchemeString

SchemeString overrides OperationBase to include offset value.

type OperationStoreGlobalByGlobalIndexLiteralIndexImmediate

type OperationStoreGlobalByGlobalIndexLiteralIndexImmediate struct {
	OperationBase
	LiteralIndex LiteralIndex
}

OperationStoreGlobalByGlobalIndexLiteralIndexImmediate stores a value to a global variable using an index from the literals pool.

func NewOperationStoreGlobalByGlobalIndexLiteralIndexImmediate

func NewOperationStoreGlobalByGlobalIndexLiteralIndexImmediate(liti LiteralIndex) *OperationStoreGlobalByGlobalIndexLiteralIndexImmediate

NewOperationStoreGlobalByGlobalIndexLiteralIndexImmediate creates a new global store operation.

func (*OperationStoreGlobalByGlobalIndexLiteralIndexImmediate) EqualTo

func (*OperationStoreGlobalByGlobalIndexLiteralIndexImmediate) SchemeString

SchemeString returns the Scheme representation of the operation.

type OperationStoreLocalByLocalIndexImmediate

type OperationStoreLocalByLocalIndexImmediate struct {
	OperationBase
	LocalIndex *environment.LocalIndex
}

func (*OperationStoreLocalByLocalIndexImmediate) EqualTo

func (*OperationStoreLocalByLocalIndexImmediate) SchemeString

type OperationStoreSyntaxCaseInput

type OperationStoreSyntaxCaseInput struct {
	OperationBase
}

OperationStoreSyntaxCaseInput stores the value register into the per-context syntaxCaseState for use by OperationSyntaxCaseMatch.

func NewOperationStoreSyntaxCaseInput

func NewOperationStoreSyntaxCaseInput() *OperationStoreSyntaxCaseInput

func (*OperationStoreSyntaxCaseInput) Apply

func (*OperationStoreSyntaxCaseInput) EqualTo

func (p *OperationStoreSyntaxCaseInput) EqualTo(other values.Value) bool

type OperationSyntaxCaseMatch

type OperationSyntaxCaseMatch struct {
	OperationBase
}

OperationSyntaxCaseMatch performs pattern matching for syntax-case.

Expects:

  • wrt register: syntaxCaseClause with compiled pattern
  • Top of eval stack: input syntax object

Results:

  • If match succeeds: value register = #t, pattern bindings stored in context
  • If match fails: value register = #f

func NewOperationSyntaxCaseMatch

func NewOperationSyntaxCaseMatch() *OperationSyntaxCaseMatch

func (*OperationSyntaxCaseMatch) Apply

func (*OperationSyntaxCaseMatch) EqualTo

func (p *OperationSyntaxCaseMatch) EqualTo(other values.Value) bool

type OperationSyntaxCaseNoMatch

type OperationSyntaxCaseNoMatch struct {
	OperationBase
}

OperationSyntaxCaseNoMatch is emitted at the end of syntax-case when no clause matches.

func NewOperationSyntaxCaseNoMatch

func NewOperationSyntaxCaseNoMatch() *OperationSyntaxCaseNoMatch

func (*OperationSyntaxCaseNoMatch) Apply

func (*OperationSyntaxCaseNoMatch) EqualTo

func (p *OperationSyntaxCaseNoMatch) EqualTo(other values.Value) bool

type OperationSyntaxRulesTransform

type OperationSyntaxRulesTransform struct {
	OperationBase
}

OperationSyntaxRulesTransform is a VM operation that performs macro expansion.

Execution context:

  • wrt register: contains clausesWrapper with compiled pattern/template pairs
  • Local parameter 0: contains the input form (the macro invocation)

The operation is part of the transformer closure created by CompileSyntaxRules.

func NewOperationSyntaxRulesTransform

func NewOperationSyntaxRulesTransform() *OperationSyntaxRulesTransform

func (*OperationSyntaxRulesTransform) Apply

func (*OperationSyntaxRulesTransform) EqualTo

func (p *OperationSyntaxRulesTransform) EqualTo(other values.Value) bool

type OperationSyntaxTemplateExpand

type OperationSyntaxTemplateExpand struct {
	OperationBase
}

OperationSyntaxTemplateExpand expands a syntax template using the current pattern variable bindings. This is used for templates containing ellipsis, which require runtime expansion rather than compile-time code generation.

The template is stored in the value register (loaded from literals). The result is the expanded syntax object, left in the value register.

func NewOperationSyntaxTemplateExpand

func NewOperationSyntaxTemplateExpand() *OperationSyntaxTemplateExpand

func (*OperationSyntaxTemplateExpand) Apply

func (*OperationSyntaxTemplateExpand) EqualTo

func (p *OperationSyntaxTemplateExpand) EqualTo(other values.Value) bool

type Operations

type Operations []Operation

func NewOperations

func NewOperations(ops ...Operation) Operations

func (Operations) AsList

func (p Operations) AsList() values.Tuple

func (Operations) Copy

func (p Operations) Copy() Operations

func (Operations) EqualTo

func (p Operations) EqualTo(o values.Value) bool

func (Operations) IsVoid

func (p Operations) IsVoid() bool

func (Operations) Len

func (p Operations) Len() int

func (Operations) SchemeString

func (p Operations) SchemeString() string

type Parameter

type Parameter struct {
	// contains filtered or unexported fields
}

Parameter represents an R7RS parameter object. Parameters are dynamically-scoped variables that can be temporarily rebound using parameterize. They act as procedures:

  • (param) returns the current value
  • (param val) sets the current value (after applying converter if present)

func NewParameter

func NewParameter(init values.Value, converter *MachineClosure) *Parameter

NewParameter creates a new parameter with the given initial value and optional converter. The converter should be a procedure that takes one argument and returns the converted value. Pass nil for converter if no conversion is needed.

func (*Parameter) Converter

func (p *Parameter) Converter() *MachineClosure

Converter returns the converter procedure, or nil if none.

func (*Parameter) EqualTo

func (p *Parameter) EqualTo(v values.Value) bool

EqualTo uses identity comparison for parameters. Two parameters are equal only if they are the same object.

func (*Parameter) HasConverter

func (p *Parameter) HasConverter() bool

HasConverter returns true if the parameter has a converter procedure.

func (*Parameter) IsVoid

func (p *Parameter) IsVoid() bool

IsVoid returns true if the parameter is nil.

func (*Parameter) SchemeString

func (p *Parameter) SchemeString() string

SchemeString returns the Scheme representation of the parameter.

func (*Parameter) SetValue

func (p *Parameter) SetValue(v values.Value)

SetValue sets the current value of the parameter. Note: This does NOT apply the converter. The caller is responsible for converting the value before calling SetValue.

func (*Parameter) Value

func (p *Parameter) Value() values.Value

Value returns the current value of the parameter.

type PhaseEntry

type PhaseEntry[F any] struct {
	Name string
	Fn   F
}

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

Expand invokes the primitive expander function.

func (*PrimitiveExpander) IsVoid

func (p *PrimitiveExpander) IsVoid() bool

IsVoid implements values.Value interface.

func (*PrimitiveExpander) Name

func (p *PrimitiveExpander) Name() string

Name returns the name of this primitive expander.

func (*PrimitiveExpander) SchemeString

func (p *PrimitiveExpander) SchemeString() string

SchemeString implements values.Value interface.

type PrimitiveExpanderFunc

type PrimitiveExpanderFunc func(
	etc *ExpanderTimeContinuation,
	ctx context.Context,
	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)
  • ctx: The context for cancellation and deadlines
  • sym: The keyword symbol (e.g., 'if', 'lambda')
  • expr: The expression arguments (everything after the keyword)

Returns the expanded syntax value.

type PromptTag

type PromptTag struct {
	// contains filtered or unexported fields
}

PromptTag is an opaque identity value for delimited continuation prompts. Equality is pointer identity (each tag is unique). Follows the Racket model of continuation prompt tags.

See: Flatt, Yu, Findler, Felleisen "Adding Delimited and Composable Control to a Production Programming Environment" (ICFP 2007).

func NewPromptTag

func NewPromptTag(name string) *PromptTag

NewPromptTag creates a new prompt tag with an optional name for debugging.

func (*PromptTag) EqualTo

func (p *PromptTag) EqualTo(o values.Value) bool

func (*PromptTag) IsVoid

func (p *PromptTag) IsVoid() bool

func (*PromptTag) SchemeString

func (p *PromptTag) SchemeString() string

type SchemeError

type SchemeError struct {
	Message    string
	Source     *syntax.SourceContext // Where error occurred
	StackTrace string                // Formatted stack trace
	Cause      error                 // Underlying error (if any)
}

SchemeError is a runtime error with Scheme-level stack trace.

func NewSchemeError

func NewSchemeError(msg string, source *syntax.SourceContext, stackTrace string) *SchemeError

func NewSchemeErrorWithCause

func NewSchemeErrorWithCause(msg string, source *syntax.SourceContext, stackTrace string, cause error) *SchemeError

func (*SchemeError) EqualTo

func (p *SchemeError) EqualTo(o values.Value) bool

EqualTo compares for equality.

func (*SchemeError) Error

func (p *SchemeError) Error() string

func (*SchemeError) IsVoid

func (p *SchemeError) IsVoid() bool

IsVoid returns false (errors are not void).

func (*SchemeError) SchemeString

func (p *SchemeError) SchemeString() string

SchemeString returns the Scheme representation.

func (*SchemeError) Unwrap

func (p *SchemeError) Unwrap() error

type Stack

type Stack values.Vector

func NewStack

func NewStack(vs ...values.Value) *Stack

NewStack creates a new stack with the given initial values.

func (Stack) AsList

func (p Stack) AsList() values.Tuple

AsList converts the stack to a Scheme list (values.Tuple). The list is in stack order (first pushed = first element).

func (*Stack) Clear

func (p *Stack) Clear()

Clear removes all elements from the stack.

func (Stack) Copy

func (p Stack) Copy() *Stack

Copy creates a shallow copy of the stack.

func (Stack) IsVoid

func (p Stack) IsVoid() bool

IsVoid returns true if the stack is nil.

func (Stack) Len

func (p Stack) Len() int

Len returns the number of elements in the stack.

func (Stack) PeekK

func (p Stack) PeekK(i int) values.Value

PeekK returns the kth value from the top of the stack without removing it. `K` is zero-based, so PeekK(0) returns the top value. `K` is used for methods that need a numeric index.

func (*Stack) Pop

func (p *Stack) Pop() values.Value

Pop removes and returns the top value from the stack.

func (*Stack) PopAll

func (p *Stack) PopAll() []values.Value

PopAll removes and returns all values from the stack. The caller gets exclusive ownership of the returned slice. The stack retains its backing array for reuse (avoids re-allocation on subsequent pushes). References in the retained portion are cleared so the GC can collect the values.

func (*Stack) PopN added in v1.4.0

func (p *Stack) PopN(n int) []values.Value

PopN removes and returns the top n values from the stack. Values are returned in stack order (top-most element last). This is more efficient than calling Pop() n times.

func (*Stack) Pull

func (p *Stack) Pull() values.Value

Pull removes and returns the bottom value from the stack. In the SECD model (Landin 1964), the procedure is evaluated first but needed last. Pull retrieves it from the bottom after all arguments have been pushed on top. See BIBLIOGRAPHY.md "Stack-Based Virtual Machines".

func (*Stack) Push

func (p *Stack) Push(v values.Value)

Push adds a value to the top of the stack.

func (*Stack) PushAll

func (p *Stack) PushAll(vs []values.Value)

PushAll pushes all values from the slice onto the stack.

func (Stack) SchemeString

func (p Stack) SchemeString() string

SchemeString returns a Scheme-like string representation of the stack.

func (Stack) String

func (p Stack) String() string

String returns a string representation of the stack.

type StackFrame

type StackFrame struct {
	FunctionName string                // Function name (or "<anonymous>")
	CallSite     *syntax.SourceContext // Where the call was made
	CurrentLoc   *syntax.SourceContext // Current execution point
}

StackFrame represents one frame in a Scheme stack trace.

func (*StackFrame) String

func (p *StackFrame) String() string

String formats the frame for display.

type StackTrace

type StackTrace []StackFrame

StackTrace is a list of stack frames.

func (StackTrace) String

func (p StackTrace) String() string

String formats the entire stack trace.

type StepMode

type StepMode int

StepMode represents the stepping mode for the debugger.

const (
	StepNone StepMode = iota
	StepInto          // Step to next source location
	StepOver          // Step to next source location in same or parent frame
	StepOut           // Step until current frame returns
)

type SubContextParams added in v1.3.0

type SubContextParams struct {
	Ctx              context.Context
	Env              *environment.EnvironmentFrame
	ParentMC         *MachineContext
	EscapeCont       *MachineContinuation
	ExceptionHandler *ExceptionHandler
	MaxCallDepth     uint64
}

SubContextParams holds the parent state needed to create a thread's sub-context. This is used to avoid race conditions when creating sub-contexts across goroutine boundaries.

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

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 implements values.Value interface.

func (*SyntaxCompiler) Name

func (p *SyntaxCompiler) Name() string

Name returns the name of this syntax compiler.

func (*SyntaxCompiler) SchemeString

func (p *SyntaxCompiler) SchemeString() string

SchemeString implements values.Value interface.

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 special forms like `define`, `lambda`, `if`, `quote`, 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 to ctc.template and return nil on success.

type SyntaxRulesClause

type SyntaxRulesClause struct {
	// contains filtered or unexported fields
}

SyntaxRulesClause represents a single pattern-template pair in syntax-rules.

Per R7RS, a syntax-rules form contains:

(syntax-rules (literal ...) clause ...)
(syntax-rules <ellipsis> (literal ...) clause ...)  ; with custom ellipsis

where each clause is (pattern template).

The pattern is compiled to bytecode for efficient matching. The template is stored as-is and expanded by substituting captured pattern variables.

The macroScope field supports hygiene: when the transformer runs, it creates a fresh "intro scope" that marks all identifiers introduced by the macro. This prevents variable capture between the macro and its use site.

type VMCounters added in v1.1.0

type VMCounters struct {
	OpsExecuted              uint64
	ClosuresApplied          uint64
	EnvsCopied               uint64
	BindingsCopied           uint64
	ContinuationsSaved       uint64
	ContinuationsRestored    uint64
	StackPopAlls             uint64
	StackElementsCopied      uint64
	ForeignCalls             uint64
	SubContextsCreated       uint64
	StackPoolReleases        uint64
	SubContextPoolReleases   uint64
	ContinuationPoolReleases uint64
	SharedFrameRestores      uint64
	KeysShared               uint64
	NoCopyApplies            uint64
	NoCopyBindingsSaved      uint64

	// Stack depth instrumentation (ongoing monitoring; prior cap-tuning investigation
	// showed cap-8 is sufficient for observed workloads)
	StackMaxDepth   uint64
	StackDepth0to2  uint64 // depth 0-2: fits trivially
	StackDepth3to4  uint64 // depth 3-4: typical calls
	StackDepth5to8  uint64 // depth 5-8: fits in pool cap 8
	StackDepth9to16 uint64 // depth 9-16: requires 1 growth from cap 8
	StackDepth17p   uint64 // depth 17+: requires 2+ growths
}

VMCounters holds performance counters for a single MachineContext execution. All counters are plain uint64 — no atomics needed because each MachineContext is single-goroutine. Sub-contexts have their own counters (not aggregated into the parent).

func (*VMCounters) RecordStackDepth added in v1.4.0

func (c *VMCounters) RecordStackDepth(n int)

RecordStackDepth updates the depth histogram and max tracker.

func (VMCounters) String added in v1.1.0

func (c VMCounters) String() string

String returns a tabular summary of all counters.

type WindingStack

type WindingStack []*DynamicWindFrame

WindingStack tracks the current dynamic-wind context. It's a slice of frames from outermost to innermost.

func (WindingStack) Copy

func (p WindingStack) Copy() WindingStack

Copy creates a shallow copy of the winding stack.

func (WindingStack) Depth

func (p WindingStack) Depth() int

Depth returns the number of active dynamic-wind frames.

func (*WindingStack) Pop

func (p *WindingStack) Pop() *DynamicWindFrame

Pop removes the innermost frame from the winding stack.

func (*WindingStack) Push

func (p *WindingStack) Push(frame *DynamicWindFrame)

Push adds a frame to the winding stack.

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL