Documentation
¶
Overview ¶
Package wile provides the public API for embedding the Wile Scheme interpreter.
Basic usage:
engine, err := wile.NewEngine(ctx)
if err != nil {
log.Fatal(err)
}
result, err := engine.Eval(ctx, engine.MustParse(ctx, "(+ 1 2 3)"))
fmt.Println(result) // 6
Profile-based configuration:
engine, err := wile.NewEngine(ctx, wile.WithProfile(wile.Small))
engine, err := wile.NewEngine(ctx,
wile.WithProfile(wile.Console),
wile.WithEnv("APP_MODE", "production"),
)
Sandboxed eval/load (wile-goast pattern):
engine, err := wile.NewEngine(ctx, wile.WithProfile(wile.ConsoleWithLoad))
Ad-hoc extension selection (bypasses profiles):
engine, err := wile.NewEngine(ctx,
wile.WithExtension(io.Extension),
wile.WithExtension(system.Extension),
)
Custom primitives:
engine, _ := wile.NewEngine(ctx)
engine.RegisterPrimitive(wile.PrimitiveSpec{
Name: "my-func",
ParamCount: 1,
Impl: myFuncImpl,
})
Index ¶
- Constants
- Variables
- func IsBoolean(v Value) bool
- func IsIncompleteInput(err error) bool
- func IsList(v Value) bool
- func IsNull(v Value) bool
- func IsNumber(v Value) bool
- func IsPair(v Value) bool
- func IsProcedure(v Value) bool
- func IsString(v Value) bool
- func IsSymbol(v Value) bool
- func NewNamespace(ctx context.Context, opts ...EngineOption) (*environment.Namespace, error)
- func ToGoBool(v Value) (bool, bool)
- func ToGoFloat(v Value) (float64, bool)
- func ToGoInt(v Value) (int64, bool)
- func ToGoString(v Value) (string, bool)
- type BreakpointInfo
- type CallContext
- type CompilationError
- type CompiledCode
- type Debugger
- func (p *Debugger) Breakpoints() []BreakpointInfo
- func (p *Debugger) Continue()
- func (p *Debugger) CurrentState() values.DebugState
- func (p *Debugger) DisableBreakpoint(id int) bool
- func (p *Debugger) EnableBreakpoint(id int) bool
- func (p *Debugger) IsStepping() bool
- func (p *Debugger) OnBreak(fn func(state values.DebugState, bp *BreakpointInfo))
- func (p *Debugger) RemoveBreakpoint(id int) bool
- func (p *Debugger) SetBreakpoint(file string, line, col int) int
- func (p *Debugger) StepInto()
- func (p *Debugger) StepOut()
- func (p *Debugger) StepOver()
- type Engine
- func (p *Engine) AvailableLibraries(ctx context.Context) ([]LibraryName, error)
- func (p *Engine) BoundNames() []string
- func (p *Engine) Call(ctx context.Context, proc Value, args ...Value) (Value, error)
- func (p *Engine) Close() error
- func (p *Engine) Compile(ctx context.Context, expr *Expression) (*CompiledCode, error)
- func (p *Engine) CurrentLoadDirectory() string
- func (p *Engine) CurrentLoadPath() string
- func (p *Engine) Define(name string, value Value) error
- func (p *Engine) DisassembleValue(v Value) (string, error)
- func (p *Engine) Environment() *environment.EnvironmentFrame
- func (p *Engine) Eval(ctx context.Context, expr *Expression) (Value, error)
- func (p *Engine) EvalIn(ctx context.Context, expr *Expression, ns *environment.Namespace) (Value, error)
- func (p *Engine) EvalMultiple(ctx context.Context, code string) (Value, error)
- func (p *Engine) EvalMultipleWithSource(ctx context.Context, code string, source string) (Value, error)
- func (p *Engine) EvalProgram(ctx context.Context, code string, source string) (Value, error)
- func (p *Engine) FormLabel(v Value) string
- func (p *Engine) Get(name string) (Value, bool)
- func (p *Engine) LastCounters() machine.VMCounters
- func (p *Engine) LoadedLibraries() ([]*LibraryInfo, error)
- func (p *Engine) LookupLibrary(parts ...string) (*LibraryInfo, error)
- func (p *Engine) MustParse(ctx context.Context, code string) *Expression
- func (p *Engine) MustParseWithSource(ctx context.Context, code string, source string) *Expression
- func (p *Engine) Namespace() *environment.Namespace
- func (p *Engine) Parse(ctx context.Context, code string) (*Expression, error)
- func (p *Engine) ParseWithSource(ctx context.Context, code string, source string) (*Expression, error)
- func (p *Engine) PopLoadPath()
- func (p *Engine) PushLoadPath(filePath string) error
- func (p *Engine) ReadExpression(ctx context.Context, r io.Reader) (*Expression, error)
- func (p *Engine) ReadExpressions(ctx context.Context, r io.Reader) ([]*Expression, error)
- func (p *Engine) RegisterFunc(name string, fn any) error
- func (p *Engine) RegisterFuncs(funcs map[string]any) error
- func (p *Engine) RegisterPrimitive(spec PrimitiveSpec) error
- func (p *Engine) Registry() *registry.Registry
- func (p *Engine) Run(ctx context.Context, cc *CompiledCode) (Value, error)
- func (p *Engine) SetDebugger(d *Debugger)
- func (p *Engine) UnloadedLibraries(ctx context.Context) []*LibraryInfo
- func (p *Engine) WithLoadPath(filePath string, fn func() error) error
- type EngineOption
- func WithAuthorizer(auth security.Authorizer) EngineOption
- func WithContractEnforcement() EngineOption
- func WithCoverage(c *coverage.Collector) EngineOption
- func WithEnv(key, value string) EngineOption
- func WithEnvMap(m map[string]string) EngineOption
- func WithExtension(ext registry.Extension) EngineOption
- func WithExtensions(exts ...registry.Extension) EngineOption
- func WithImmutableTopLevel() EngineOption
- func WithImportObserver(obs func(LibraryImportEvent)) EngineOption
- func WithInlineThreshold(n int) EngineOption
- func WithLibraryPaths(paths ...string) EngineOption
- func WithLossyConversionsAllowed() EngineOption
- func WithMaxCallDepth(n int) EngineOption
- func WithMaxExpandDepth(n int) EngineOption
- func WithMaxParseDepth(n int) EngineOption
- func WithMaxStackSize(n uint64) EngineOption
- func WithMutableTopLevel() EngineOption
- func WithNamespace(ns *environment.Namespace) EngineOption
- func WithProfile(p Profile) EngineOption
- func WithRegistry(r *registry.Registry) EngineOption
- func WithSandbox(opts ...SandboxOption) EngineOption
- func WithSourceFS(fsys fs.FS) EngineOption
- func WithSourceOS() EngineOption
- func WithoutCore() EngineOption
- type Expression
- type ForeignFunction
- type LibraryImportEvent
- type LibraryInfo
- type LibraryName
- type MachineContext
- type Phase
- type PrimitiveSpec
- type Profile
- type RuntimeError
- type SandboxOption
- type Value
- func Car(v Value) (Value, bool)
- func Cdr(v Value) (Value, bool)
- func NewBigFloat(f *big.Float) Value
- func NewBigFloatFromFloat64(f float64) Value
- func NewBigFloatFromString(s string) Value
- func NewBigInteger(n *big.Int) Value
- func NewBigIntegerFromInt64(n int64) Value
- func NewBigIntegerFromString(s string, base int) Value
- func NewBoolean(b bool) Value
- func NewComplex(v complex128) Value
- func NewComplexFromParts(realPart, imagPart float64) Value
- func NewFloat(f float64) Value
- func NewInteger(n int64) Value
- func NewList(vals ...Value) Value
- func NewRational(num, denom int64) Value
- func NewRationalFromBigInt(num, denom *big.Int) Value
- func NewString(s string) Value
- func NewSymbol(s string) Value
- func NewVector(vals ...Value) Value
- func ToSlice(ctx context.Context, v Value) ([]Value, bool)
- func WrapValue(v values.Value) Value
Examples ¶
Constants ¶
const ( PhaseTemplate = environment.PhaseTemplate PhaseRuntime = environment.PhaseRuntime PhaseExpand = environment.PhaseExpand PhaseCompile = environment.PhaseCompile )
Phase constants for LibraryImportEvent.Phase and other phase-keyed APIs. Re-exported from environment for embedder convenience.
const DefaultMaxCallDepth int = 10000
DefaultMaxCallDepth is the default call depth limit for new engines. At ~500 bytes per frame, 10000 frames ≈ 5MB. Use WithMaxCallDepth(0) to opt out of the limit explicitly; WithMaxCallDepth(n) with n < 0 is clamped to 0 (also unlimited).
Variables ¶
var EmptyList = wrapValue(values.EmptyList)
EmptyList is the empty list.
var ErrEngineClosed = werr.NewStaticError("engine is closed")
ErrEngineClosed is returned when Close is called on an already-closed engine.
var False = wrapValue(values.FalseValue)
False is the #f value.
var StdLibFS fs.FS = stdlib.LibFS
StdLibFS provides the standard Scheme libraries shipped with wile (e.g., (wile algebra), (wile match), etc.) as an embedded filesystem. Library paths resolve as "lib/...". Consumers add it to the engine with WithSourceFS(StdLibFS).
The bytes live in the internal stdlib package's embed (//go:embed lib). Because go:embed forbids "..", this package re-exports stdlib.LibFS rather than embedding the tree a second time; the two share one copy and one shape.
var True = wrapValue(values.TrueValue)
True is the #t value.
var Void = wrapValue(values.Void)
Void is the void value.
Functions ¶
func IsIncompleteInput ¶
IsIncompleteInput reports whether a parse error indicates the input is a valid prefix of an expression that needs more input to complete. This is useful for REPL implementations that accumulate multi-line input.
Detection is structural (errors.Is), not string matching:
- wrapped io.EOF — a truncated token at end of stream;
- io.ErrUnexpectedEOF — the parser ran out of input inside a form (wrapMidParseEOF; covers unclosed lists/vectors/block comments);
- werr.ErrIncompleteInput — the tokenizer hit EOF inside an unterminated string or extended symbol;
- parser.ErrUnknownTokenType — a partial token from premature EOF.
Returns false for nil and bare io.EOF (a clean end of stream).
func IsPair ¶
IsPair returns true if v is a non-empty pair (cons cell). EmptyList is not a *Pair (it's a separate type), so the type assertion handles the distinction without an explicit IsEmptyList check.
func IsProcedure ¶
IsProcedure returns true if v is a callable procedure (lambda, foreign closure, case-lambda, parameter, or composable continuation).
func NewNamespace ¶
func NewNamespace(ctx context.Context, opts ...EngineOption) (*environment.Namespace, error)
NewNamespace creates a fully initialized namespace with a registry, base environment bindings, syntax compilers, expanders, and bootstrap macros. The namespace can be passed to NewEngine via WithNamespace.
Options are shared with NewEngine: WithExtension, WithRegistry, WithoutCore, WithAuthorizer all work. Engine-specific options (WithMaxCallDepth, WithLibraryPaths, etc.) are accepted but ignored.
Example:
ns, err := wile.NewNamespace(ctx,
wile.WithExtension(math.Extension),
wile.WithAuthorizer(security.ReadOnly()),
)
eng, err := wile.NewEngine(ctx, wile.WithNamespace(ns))
func ToGoBool ¶
ToGoBool extracts a Go bool from a Scheme boolean value. Returns (false, false) if v is not a boolean.
func ToGoFloat ¶
ToGoFloat extracts a float64 from an inexact real value. Returns (0, false) if v is not a Float.
func ToGoInt ¶
ToGoInt extracts an int64 from an exact integer value. Returns (0, false) if v is not an exact integer or does not fit in int64.
func ToGoString ¶
ToGoString extracts the Go string from a Scheme string value. Returns ("", false) if v is not a string.
Types ¶
type BreakpointInfo ¶
BreakpointInfo holds read-only breakpoint state for display.
type CallContext ¶
type CallContext = machine.CallContext
CallContext is the extension-facing subset of MachineContext. This is a re-export of machine.CallContext for convenience.
type CompilationError ¶
type CompilationError struct {
Message string
Source string // formatted source location ("file:line:col"), empty if unavailable
Cause error
}
CompilationError wraps errors from parsing, expanding, or compiling Scheme code.
Source ¶
Source provides the source location ("file:line:col") where the error occurred, when available. Compilation errors from the core compiler include source locations; parse errors and some edge cases may have an empty Source.
func (*CompilationError) Error ¶
func (p *CompilationError) Error() string
func (*CompilationError) Unwrap ¶
func (p *CompilationError) Unwrap() error
type CompiledCode ¶
type CompiledCode struct {
// contains filtered or unexported fields
}
CompiledCode represents compiled Scheme code ready for execution.
CompiledCode captures the environment from the Engine that compiled it and always executes using that captured environment, regardless of which Engine is used to run it. Using a different Engine instance affects only that Engine's own bookkeeping (for example, evaluation counters), not the environment bindings or symbol interning.
CompiledCode can be run multiple times. It is not safe for concurrent execution (the underlying Engine is not goroutine-safe).
func (*CompiledCode) String ¶
func (p *CompiledCode) String() string
String returns a string representation of the compiled code.
type Debugger ¶
type Debugger struct {
// contains filtered or unexported fields
}
Debugger controls breakpoints and stepping for an Engine. It wraps the internal machine.Debugger to avoid exposing VM types.
func (*Debugger) Breakpoints ¶
func (p *Debugger) Breakpoints() []BreakpointInfo
Breakpoints returns all breakpoints.
func (*Debugger) CurrentState ¶
func (p *Debugger) CurrentState() values.DebugState
CurrentState returns the DebugState from the most recent break, or nil if no break has occurred.
func (*Debugger) DisableBreakpoint ¶
DisableBreakpoint disables a breakpoint by ID.
func (*Debugger) EnableBreakpoint ¶
EnableBreakpoint enables a breakpoint by ID.
func (*Debugger) IsStepping ¶
IsStepping returns true if the debugger is in step mode.
func (*Debugger) OnBreak ¶
func (p *Debugger) OnBreak(fn func(state values.DebugState, bp *BreakpointInfo))
OnBreak sets the callback invoked when a breakpoint is hit or a step completes. The DebugState provides source location and stack trace access without exposing VM internals.
func (*Debugger) RemoveBreakpoint ¶
RemoveBreakpoint removes a breakpoint by ID.
func (*Debugger) SetBreakpoint ¶
SetBreakpoint adds a breakpoint at the given source location. Returns the breakpoint ID.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is the main entry point for embedding Wile.
An Engine is NOT safe for concurrent use from multiple goroutines. Most methods that parse, compile, or evaluate code mutate the environment. Each goroutine should use its own Engine, or synchronize externally.
SRFI-18 threads within a single Engine are safe — the VM handles thread coordination internally.
func NewEngine ¶
func NewEngine(ctx context.Context, opts ...EngineOption) (*Engine, error)
NewEngine creates a new Wile engine. By default, only core primitives are included. Use WithExtension to add optional extensions.
When WithNamespace is used, the engine uses the pre-built namespace and ignores registry/extension/core options (they were applied when the namespace was created). Library paths and other engine-specific options still apply.
Initialization Order Invariant ¶
NewEngine performs 6 initialization steps that MUST execute in this order. Each step depends on prior steps; reordering causes silent failures or panics.
- Config — build engineConfig from options
- Registry — buildRegistry(cfg): register core + extension primitives
- Namespace — NewNamespace() + SetRegistry + SetAuthorizer
- Bootstrap — applyBaseEnvironment: bind primitives, syntax compilers, expanders, bootstrap macros (uses EmbedFileResolver, NOT the runtime file resolver)
- File resolver — env.SetFileResolver: runtime include/load resolver. Must come AFTER bootstrap (step 4) so bootstrap uses its own EmbedFileResolver, not the runtime resolver.
- Library system — setupLibrarySystem: search paths, extension libraries, library env factory. Requires file resolver (step 5) and bootstrap macros (step 4) for define-library parsing.
The WithNamespace path (pre-built namespace) skips steps 2-5 and trusts that the caller bootstrapped correctly. NewNamespace() performs steps 2-4.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := engine.Eval(ctx, engine.MustParse(ctx, "(+ 1 2 3)"))
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: 6
Example (WithExtension) ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/internal/extensions/io"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
_, err := wile.NewEngine(context.Background(),
wile.WithExtension(io.Extension),
)
if err != nil {
log.Fatal(err)
}
fmt.Println("engine created with I/O extension")
}
Output: engine created with I/O extension
func (*Engine) AvailableLibraries ¶
func (p *Engine) AvailableLibraries(ctx context.Context) ([]LibraryName, error)
AvailableLibraries returns all importable library names by combining filesystem discovery with registry-known libraries (synthetic extensions). Returns a sorted, deduplicated list. If the library system is not enabled (no WithLibraryPaths call), returns an empty list.
func (*Engine) BoundNames ¶
BoundNames returns a sorted, deduplicated list of every binding name visible in the engine across all phases (runtime, expand, compile) and the sealed base. It includes macro and special-form keywords, not only runtime value bindings, so it is broader than the (environment-bound-names) primitive — it is the set a REPL wants for tab completion. Returns nil if the engine has no namespace.
This is the stable, typed alternative to walking Environment().Namespace() phase frames directly.
func (*Engine) Call ¶
Call invokes a Scheme procedure with arguments. Supports lambdas, foreign closures, case-lambdas, and parameters. Composable continuations cannot be called from Go (they require the VM winding stack) and return an error.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
// Define a Scheme function.
ctx := context.Background()
_, err = engine.EvalMultiple(ctx, `
(define (square x) (* x x))
`)
if err != nil {
log.Fatal(err)
}
// Retrieve and call it from Go.
proc, ok := engine.Get("square")
if !ok {
log.Fatal("square not found")
}
result, err := engine.Call(ctx, proc, wile.NewInteger(12))
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: 144
func (*Engine) Close ¶
Close releases resources held by closeable extensions. Extensions that implement registry.Closeable have their Close method called. Errors from individual closers are collected and returned via errors.Join. Calling Close on an already-closed engine returns ErrEngineClosed.
func (*Engine) Compile ¶
func (p *Engine) Compile(ctx context.Context, expr *Expression) (*CompiledCode, error)
Compile compiles a parsed expression without executing. The result can be executed later with Engine.Run.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
// Define a variable, then compile an expression that uses it.
ctx := context.Background()
_, err = engine.Eval(ctx, engine.MustParse(ctx, "(define x 0)"))
if err != nil {
log.Fatal(err)
}
compiled, err := engine.Compile(context.Background(), engine.MustParse(context.Background(), "(* x x)"))
if err != nil {
log.Fatal(err)
}
// Run the same compiled code with different values of x.
for _, n := range []int64{3, 5, 7} {
err = engine.Define("x", wile.NewInteger(n))
if err != nil {
log.Fatal(err)
}
result, err := engine.Run(ctx, compiled)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
}
Output: 9 25 49
func (*Engine) CurrentLoadDirectory ¶
CurrentLoadDirectory returns the directory of the file currently being loaded, or empty string if no file is being loaded.
func (*Engine) CurrentLoadPath ¶
CurrentLoadPath returns the path of the file currently being loaded, or empty string if no file is being loaded.
func (*Engine) Define ¶
Define binds a value to a name in the top-level environment.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
err = engine.Define("width", wile.NewInteger(800))
if err != nil {
log.Fatal(err)
}
err = engine.Define("height", wile.NewInteger(600))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := engine.Eval(ctx, engine.MustParse(ctx, "(* width height)"))
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: 480000
func (*Engine) DisassembleValue ¶
DisassembleValue returns the formatted disassembly of a callable value. For compiled closures, shows bytecode instructions. For case-lambda, shows each clause separately. For foreign closures, shows name, arity, and documentation. Returns an error for non-procedure values.
func (*Engine) Environment ¶
func (p *Engine) Environment() *environment.EnvironmentFrame
Environment returns the underlying environment frame.
This is an advanced escape hatch: it exposes the internal environment.EnvironmentFrame type for white-box embedders that need direct access to phase frames, the namespace, or the sealed base. That type is internal and may change between minor versions, so it is not part of the stable API surface. Prefer the typed Engine methods (Get, Define, LoadedLibraries, …) where they suffice.
func (*Engine) Eval ¶
Eval compiles and executes a parsed expression, returning the result. Use Engine.Parse to obtain an Expression from source code. For evaluating multi-expression strings, use Engine.EvalMultiple.
func (*Engine) EvalIn ¶
func (p *Engine) EvalIn(ctx context.Context, expr *Expression, ns *environment.Namespace) (Value, error)
EvalIn compiles and executes a parsed expression in the given namespace, rather than the engine's own namespace.
The target namespace's authorizer governs security checks during execution. If the target namespace has no authorizer, the engine's authorizer is propagated to it before evaluation.
func (*Engine) EvalMultiple ¶
EvalMultiple evaluates multiple expressions, returning the last result.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := engine.EvalMultiple(ctx, `
(define x 10)
(define y 20)
(+ x y)
`)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: 30
func (*Engine) EvalMultipleWithSource ¶
func (p *Engine) EvalMultipleWithSource(ctx context.Context, code string, source string) (Value, error)
EvalMultipleWithSource evaluates multiple expressions, returning the last result. The source parameter identifies where the code came from (e.g. a filename) and appears in error messages and stack traces.
Each top-level form is compiled and run independently, so a forward reference between two separate defines — (define (f) (g)) before (define (g) ...) — fails to compile. Use Engine.EvalProgram for whole-program/file semantics where all top-level defines are mutually visible.
func (*Engine) EvalProgram ¶
EvalProgram evaluates code as a single compilation unit: it parses every top-level form, splices them into one (begin form ...), and compiles that as a unit so all top-level defines are mutually visible — a (define (f) (g)) may precede (define (g) ...). This is the forward-reference behavior of loading a file, and the recommended entry point for evaluating a whole program or script. source labels the code in diagnostics; pass "" if none.
It contrasts with Engine.EvalMultiple, which compiles and runs each top-level form independently. The (begin ...) wrapper is built structurally rather than by concatenating source text, so every form keeps its own source location.
func (*Engine) FormLabel ¶
FormLabel returns a human-readable type label for a value: "primitive" for foreign (Go-implemented) closures, "procedure" for compiled Scheme closures, "" for non-callable values (including typed nils).
func (*Engine) LastCounters ¶
func (p *Engine) LastCounters() machine.VMCounters
LastCounters returns the VM performance counters from the most recent Run or Eval call. Sub-context counters are not aggregated.
func (*Engine) LoadedLibraries ¶
func (p *Engine) LoadedLibraries() ([]*LibraryInfo, error)
LoadedLibraries returns metadata for all currently loaded libraries, sorted by name. Returns (nil, nil) if no library registry is configured.
func (*Engine) LookupLibrary ¶
func (p *Engine) LookupLibrary(parts ...string) (*LibraryInfo, error)
LookupLibrary returns info for a loaded library identified by its name parts (e.g., "scheme", "base"). Returns (nil, nil) if no library registry is configured. Returns a non-nil error if the registry has an unexpected type.
func (*Engine) MustParse ¶
func (p *Engine) MustParse(ctx context.Context, code string) *Expression
MustParse is like Parse but panics on error.
func (*Engine) MustParseWithSource ¶
MustParseWithSource is like ParseWithSource but panics on error.
func (*Engine) Namespace ¶
func (p *Engine) Namespace() *environment.Namespace
Namespace returns the Namespace for advanced use. This provides access to per-instance symbol interning and phase management.
Like Environment, this is an advanced escape hatch exposing an internal type (environment.Namespace) that may change between minor versions; it is not part of the stable API surface.
func (*Engine) Parse ¶
Parse parses a single Scheme expression from code.
Parse returns a CompilationError if the input is empty, malformed, or contains more than one expression.
func (*Engine) ParseWithSource ¶
func (p *Engine) ParseWithSource(ctx context.Context, code string, source string) (*Expression, error)
ParseWithSource parses a single Scheme expression from code. The source parameter identifies where the code came from (e.g. a filename) and appears in error messages.
func (*Engine) PopLoadPath ¶
func (p *Engine) PopLoadPath()
PopLoadPath removes the top path from the load path stack. Does nothing if the stack is empty.
Advanced embedders who need fine-grained control can use Push/Pop directly, but most should use WithLoadPath for automatic cleanup.
func (*Engine) PushLoadPath ¶
PushLoadPath pushes a path onto the load path stack. Returns an error if the path is empty. Returns nil (no-op) if the stack is not configured — path tracking requires SetLoadPathStack on the Namespace.
Advanced embedders who need fine-grained control can use Push/Pop directly, but most should use WithLoadPath for automatic cleanup.
func (*Engine) ReadExpression ¶
ReadExpression reads a single complete expression from r.
Unlike Engine.Parse, ReadExpression does not require the reader to contain exactly one expression — it reads the first complete expression and stops. Trailing input in the reader is ignored (the reader position advances past the consumed expression).
Use IsIncompleteInput to check whether a returned error indicates the input is a valid prefix of an expression that needs more input to complete. This is the intended pattern for REPL implementations:
expr, err := eng.ReadExpression(ctx, r)
if err != nil {
if wile.IsIncompleteInput(err) {
// prompt for more input
}
// real parse error
}
func (*Engine) ReadExpressions ¶
ReadExpressions parses every complete expression available in r, in order, reusing a single parser so the tokenizer's one-rune lookahead is preserved across forms (a fresh parser per form would drop the inter-form delimiter).
On clean end-of-input it returns the parsed expressions and a nil error. If the input ends partway through an expression, it returns the complete expressions parsed so far together with an error satisfying IsIncompleteInput — the REPL uses that signal to keep accumulating lines. A genuine syntax error is returned wrapped, with the expressions parsed before it.
Unlike ReadExpression (exactly one form) this is the multi-form read the REPL needs to evaluate every expression on a pasted or piped line rather than silently dropping all but the first.
func (*Engine) RegisterFunc ¶
RegisterFunc registers a Go function as a Scheme primitive using natural Go signatures.
Reflection-based FFI bridging: pre-computes argument and return converters at registration time using Go's reflect package. Each call uses the cached converters to translate between Scheme values and Go types, avoiding per-call reflection overhead. See BIBLIOGRAPHY.md "Reflection-Based FFI Bridging".
Supported Types ¶
Parameter types: int64, int, float64, string, bool, []byte, []T (typed slices), map[K]V, structs (exported fields), func(...) (callbacks), Value, and context.Context (first param only).
Return types: int64, int, float64, string, bool, []byte, []T, map[K]V, structs, Value, error (last return only), and void.
Variadic Functions ¶
Variadic Go functions are supported. The variadic parameter receives all excess arguments from Scheme, converted element-by-element.
Context Forwarding ¶
If the first parameter is context.Context, the VM's context is forwarded automatically and does not count toward the Scheme parameter count.
Callbacks ¶
Callback parameters (func types) receive a Go closure that invokes a Scheme procedure through a VM sub-context. Callbacks must be called synchronously during the registered function's execution. Storing a callback for later invocation or calling it from another goroutine is unsafe — the closure captures VM state that is not goroutine-safe.
Returns an error wrapping werr.ErrFFIRegistration if fn is not a function or uses unsupported types.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
// Register a Go function with a natural signature — no MachineContext needed.
err = engine.RegisterFunc("double", func(n int64) int64 {
return n * 2
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := engine.Eval(ctx, engine.MustParse(ctx, "(map double '(1 2 3 4 5))"))
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: (2 4 6 8 10)
func (*Engine) RegisterFuncs ¶
RegisterFuncs registers multiple Go functions as Scheme primitives. Each key in the map is the Scheme name; each value must be a Go function with a signature supported by [RegisterFunc].
Registration stops on the first error. The error message includes the binding name that failed first. When multiple functions are invalid, the particular binding that fails first is non-deterministic because Go map iteration order is unspecified. Functions registered before the failure remain registered.
func (*Engine) RegisterPrimitive ¶
func (p *Engine) RegisterPrimitive(spec PrimitiveSpec) error
RegisterPrimitive adds a Go function as a Scheme primitive.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/aalpar/wile/pkg/wile"
"github.com/aalpar/wile/values"
)
func main() {
engine, err := wile.NewEngine(context.Background())
if err != nil {
log.Fatal(err)
}
// Register a Go function that doubles an integer.
err = engine.RegisterPrimitive(wile.PrimitiveSpec{
Name: "double",
ParamCount: 1,
Impl: func(mc wile.CallContext) error {
n := mc.Arg(0).(*values.Integer).Value
mc.SetValue(values.NewInteger(n * 2))
return nil
},
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
result, err := engine.Eval(ctx, engine.MustParse(ctx, "(double 21)"))
if err != nil {
log.Fatal(err)
}
fmt.Println(result.SchemeString())
}
Output: 42
func (*Engine) Registry ¶
Registry returns a clone of the engine's registry. The returned registry can be filtered with Without, WithoutCategory, or WithoutBindings and passed to NewEngine via WithRegistry to create a restricted engine.
func (*Engine) SetDebugger ¶
SetDebugger attaches a debugger to the engine. Subsequent Engine.Run calls will execute with the debugger active, enabling breakpoints and stepping. Pass nil to detach the debugger.
func (*Engine) UnloadedLibraries ¶
func (p *Engine) UnloadedLibraries(ctx context.Context) []*LibraryInfo
UnloadedLibraries returns metadata for libraries discoverable via the file resolver but not yet imported. Returns nil if no resolver is available. Thread-safe via lazy initialization with retry on failure.
func (*Engine) WithLoadPath ¶
WithLoadPath executes fn with filePath pushed onto the load path stack. This is the recommended API for embedders — it guarantees balanced push/pop via defer even if fn panics or returns an error.
Returns an error if filePath is empty.
Example:
err := engine.WithLoadPath("/app/scripts/main.scm", func() error {
_, err := engine.EvalMultiple(ctx, "(load \"helper.scm\")") // resolves relative to /app/scripts/
return err
})
type EngineOption ¶
type EngineOption func(*engineConfig)
EngineOption configures an Engine.
func WithAuthorizer ¶
func WithAuthorizer(auth security.Authorizer) EngineOption
WithAuthorizer sets the Authorizer for the engine. The authorizer is injected into every context passed to Eval, Compile, Run, and Call, gating runtime primitives and compile-time code loading.
An explicit WithAuthorizer takes precedence over any profile's built-in authorizer regardless of option order: WithAuthorizer(a) and WithProfile(p) resolve to a (then intersected with any WithSandbox layer) no matter which is written first. Passing nil is meaningful — it opens the engine, overriding a profile authorizer (symmetric with WithEnvMap(nil)).
Without this option, all operations are allowed (open by default) unless a profile or sandbox supplies an authorizer. The authorizer is immutable after engine construction.
Example:
eng, err := wile.NewEngine(ctx,
wile.WithAuthorizer(security.ReadOnly()),
)
func WithContractEnforcement ¶
func WithContractEnforcement() EngineOption
WithContractEnforcement enables runtime type validation for primitives that declare ParamTypes contracts. When enabled, each contracted primitive validates its arguments against declared types before calling the implementation and returns a typed error on mismatch.
Disabled by default. Intended as a correctness-verification aid for extension authors — production extensions should perform their own argument checks (e.g., via helpers.RequireArg) rather than depend on this option, since enabling it adds a per-call validator invocation.
func WithCoverage ¶
func WithCoverage(c *coverage.Collector) EngineOption
WithCoverage enables Scheme-side line coverage collection. After each compilation, the engine registers the resulting top-level template and every sub-template reachable via its literals pool with the given collector. Per-s-expression execution is then aggregated into the collector's Entries.
Zero hot-path cost when not set (nil check in VM dispatch).
func WithEnv ¶
func WithEnv(key, value string) EngineOption
WithEnv adds a single virtual environment variable. When any virtual env var is set, the envvars extension reads from the virtual map instead of os.Getenv.
func WithEnvMap ¶
func WithEnvMap(m map[string]string) EngineOption
WithEnvMap sets the complete virtual environment variable map. Replaces any previously set virtual env vars.
Passing nil clears the virtual env map so envvars primitives fall back to os.Getenv (still gated by the authorizer). This is symmetric with WithAuthorizer(nil): the zero value means "no restriction", not "empty sandbox". To explicitly sandbox with no visible env, pass an empty map.
Note: when combined with WithProfile(Console) or WithProfile(ConsoleWithLoad), option order matters. WithProfile fills in an empty map only if envMap is currently nil; a later WithEnvMap(nil) re-nils it and opens the sandbox.
func WithExtension ¶
func WithExtension(ext registry.Extension) EngineOption
WithExtension adds an extension to the engine.
func WithExtensions ¶
func WithExtensions(exts ...registry.Extension) EngineOption
WithExtensions adds multiple extensions to the engine.
func WithImmutableTopLevel ¶
func WithImmutableTopLevel() EngineOption
WithImmutableTopLevel selects top-level-define immutability in the user program. A top-level define that is defined-once and never set! within its compilation unit is marked rebind-stable (BindingMeta.Stable), and a subsequent set! of such a binding is rejected with ErrImmutableBinding. This is now the DEFAULT (newEngineConfig); the option remains as an explicit, redundant selector for source compatibility.
This is a documented deviation from strict R7RS §4.1.6/§5.3 (which permit top-level set!/redefinition); it unlocks the frame-reclamation optimizer's top-level payoff (sibling escape-gated plan) — the "compile for speed" contract used by sealed-module Schemes. Use WithMutableTopLevel() to opt out.
Enforcement is scoped to the engine's own user runtime global (the layered-environment sealed-base carve): a re-define of a sealed primitive/stdlib name is a child-frame shadow rather than a rejected rebind, and user-loaded LIBRARIES stay mutable — a library's cross-form (define x)/(set! x) is permitted. See docs/reference/r7rs-differences.md.
func WithImportObserver ¶
func WithImportObserver(obs func(LibraryImportEvent)) EngineOption
WithImportObserver sets a callback that is invoked each time a library is imported. The observer is read-only — it cannot influence the import. Requires WithLibraryPaths to be effective (no libraries loaded without it).
func WithInlineThreshold ¶
func WithInlineThreshold(n int) EngineOption
WithInlineThreshold sets the maximum body length (in top-level expressions) for procedure inlining. Procedures with bodies longer than this threshold are not inlined. A value of 0 disables inlining entirely. When not called, the engine uses compilation.DefaultInlineThreshold (5).
func WithLibraryPaths ¶
func WithLibraryPaths(paths ...string) EngineOption
WithLibraryPaths enables the R7RS library system (define-library / import) and configures directories to search for .sld library files.
Without this option, (import ...) raises a configuration error.
Paths are searched in order: user-supplied paths first, then the defaults ("." and "./stdlib/lib"). An empty call WithLibraryPaths() enables library support with defaults only.
Example:
eng, err := wile.NewEngine(ctx,
wile.WithLibraryPaths("/app/libs", "./vendor"),
)
// search order: /app/libs, ./vendor, ., ./stdlib/lib
func WithLossyConversionsAllowed ¶
func WithLossyConversionsAllowed() EngineOption
WithLossyConversionsAllowed permits FFI converters to silently truncate when converting Scheme numerics to fixed-precision Go types (float64, complex128). When set, *BigFloat with magnitude exceeding float64 range converts to ±math.Inf(0) without error; *Rational with non-representable denominators rounds via (*big.Rat).Float64 with the loss bit discarded; *BigComplex imaginary/real components each may truncate independently.
Default (option not set): the FFI converter returns werr.ErrLossyConversion (wrapped, with direction info) when any precision loss would occur. This is the "fail loud" discipline — opt-in is required to suppress.
The option is per-engine; the flag is captured into each FFI closure at RegisterFunc time, so calling WithLossyConversionsAllowed after some functions have already registered does NOT change their behavior.
func WithMaxCallDepth ¶
func WithMaxCallDepth(n int) EngineOption
WithMaxCallDepth sets the maximum recursion depth for the VM. When the continuation stack exceeds this depth, ErrCallDepthExceeded is returned. A value of 0 means unlimited (no depth check). Negative values are clamped to 0 and therefore also mean unlimited (matches WithInlineThreshold). When not called, the engine uses DefaultMaxCallDepth (10000).
func WithMaxExpandDepth ¶
func WithMaxExpandDepth(n int) EngineOption
WithMaxExpandDepth sets the maximum structural recursion depth the macro expander will accept. The parser already bounds nesting in textual input (see WithMaxParseDepth); this bounds programmatically-constructed deep syntax — macro output, datum->syntax, and quasiquote — which reaches the expander without passing through the parser. When expansion nests deeper, ErrExpandDepthExceeded is returned instead of crashing with a fatal Go stack overflow. A value of 0 means unlimited (negative values are clamped to 0). When not called, the expander uses DefaultMaxExpandDepth (50000).
Scope: this bound applies to expansion of top-level program text run through the engine. Expansion triggered from within running Scheme — (eval ...), (load ...), (compile ...), (expand ...) — always uses DefaultMaxExpandDepth regardless of this option, because the primitive layer has no channel to the engine's configured value. Those paths are still protected from the fatal stack overflow (by the default); they are simply not retunable per-engine.
func WithMaxParseDepth ¶
func WithMaxParseDepth(n int) EngineOption
WithMaxParseDepth sets the maximum structural nesting depth the parser will accept. When input nests deeper, ErrParseDepthExceeded is returned instead of crashing with a fatal Go stack overflow. A value of 0 means unlimited (negative values are clamped to 0). When not called, the parser uses DefaultMaxParseDepth (10000).
Scope: this bound is threaded onto the engine's own parse entry points — Parse, ParseWithSource, ReadExpression, ReadExpressions, EvalMultiple, EvalProgram, and file/-e execution. Parsing triggered from within running Scheme — (read ...), (read-syntax ...), (eval ...), (compile ...) — uses DefaultMaxParseDepth regardless of this option, because the primitive layer has no channel to the engine's configured value (mirrors WithMaxExpandDepth). Those paths are still protected from the fatal stack overflow by the default; they are simply not retunable per-engine.
func WithMaxStackSize ¶
func WithMaxStackSize(n uint64) EngineOption
WithMaxStackSize sets the maximum eval stack size for the VM. When the eval stack exceeds this size, ErrStackOverflow is returned. This is opt-in: a value of 0 means unlimited (no stack size check). There is no default — when not called, the stack is unlimited.
func WithMutableTopLevel ¶
func WithMutableTopLevel() EngineOption
WithMutableTopLevel selects strict R7RS mutable/redefinable top-level bindings, the inverse of WithImmutableTopLevel. It exists as an explicit opt-out so callers can request mutable semantics independent of the engine default (which Phase 4 of the layered-environment work flips to immutable). Opting out forfeits the frame-reclaim GC win for user recursion.
func WithNamespace ¶
func WithNamespace(ns *environment.Namespace) EngineOption
WithNamespace uses a pre-built namespace instead of building one from extension options. When set, registry/extension/core options are ignored by NewEngine (they were already applied when the namespace was created).
This enables sharing a namespace across engines or pre-configuring namespaces with specific capabilities.
func WithProfile ¶
func WithProfile(p Profile) EngineOption
WithProfile configures the engine with the named profile's extensions and authorization constraints. WithProfile is additive: it appends the profile's extensions to any already configured via WithExtension/WithExtensions, and records the profile's authorizer only if one is defined. An explicit WithAuthorizer always takes precedence over the profile's authorizer regardless of option order (see resolveAuthorizer), so profile and authorizer options compose commutatively.
Across multiple WithProfile calls the last profile that defines an authorizer wins; a later profile with no authorizer (e.g. Tiny, Small, KitchenSink) does not clear an earlier one. This fails safe — a prior restriction is retained rather than silently dropped.
Per-profile envMap behavior (all five current profiles):
- Tiny: envMap untouched; profile registers no extensions, so envvars primitives are absent.
- Console: allocates empty envMap when unset; sandboxes to the virtual map (no os.Getenv fallthrough).
- ConsoleWithLoad: same as Console (empty envMap when unset).
- Small: envMap untouched. envvars primitives are registered and fall through to os.Getenv when envMap is nil, gated by the authorizer (if any).
- KitchenSink: same fallthrough behavior as Small.
When WithEnv/WithEnvMap is combined with WithProfile(Console*), the caller-supplied contents are preserved: WithProfile only allocates an empty map when none is set. Option order matters — a later WithEnvMap(nil) re-nils the map and opens the sandbox.
func WithRegistry ¶
func WithRegistry(r *registry.Registry) EngineOption
WithRegistry uses a custom registry instead of the default. When set, core primitives are NOT automatically added.
func WithSandbox ¶
func WithSandbox(opts ...SandboxOption) EngineOption
WithSandbox layers a restrictive authorizer on top of any profile. File reads and stats are allowed; file writes and deletes are denied. Environment variable reads are prefix-filtered (default "WILE_"). Code loading and process execution are denied.
The sandbox layer is always intersected (most-restrictive-wins, via security.All) on top of whatever base authorizer the profile and/or WithAuthorizer resolve to. This holds regardless of option order — the composition is performed once at engine construction by resolveAuthorizer, so WithSandbox may appear before or after WithProfile/WithAuthorizer.
Multiple WithSandbox calls accumulate: each layer is intersected with the previously recorded sandbox authorizer, so restrictions only ever tighten (a second call cannot silently widen the first). Intersection is order- independent for the allow/deny decision.
func WithSourceFS ¶
func WithSourceFS(fsys fs.FS) EngineOption
WithSourceFS adds a virtual filesystem layer to the source file resolver chain. Multiple calls add layers searched in call order. When no resolver options are used, the engine defaults to the OS filesystem. Once any resolver option is used (WithSourceFS or WithSourceOS), only the explicitly configured resolvers are active.
Bootstrap macros are unaffected — they always load from the embedded bootstrap filesystem.
Example:
//go:embed scheme
var schemeFS embed.FS
eng, err := wile.NewEngine(ctx,
wile.WithSourceFS(schemeFS), // searched first
wile.WithSourceOS(), // OS filesystem searched last
)
func WithSourceOS ¶
func WithSourceOS() EngineOption
WithSourceOS adds the OS filesystem to the source file resolver chain. This is typically called last so that virtual filesystems are searched first. When no resolver options are used, the engine defaults to the OS filesystem; WithSourceOS is only needed when building an explicit chain with WithSourceFS.
Example:
eng, err := wile.NewEngine(ctx,
wile.WithSourceFS(embedFS), // virtual FS first
wile.WithSourceOS(), // OS fallback last
)
func WithoutCore ¶
func WithoutCore() EngineOption
WithoutCore creates an engine with an empty registry — no core primitives (arithmetic, pairs, control flow, etc.) are added. Extensions added via WithExtension are still applied.
This is useful for building minimal engines where only specific extensions are needed, or for testing extension isolation.
type Expression ¶
type Expression struct {
// contains filtered or unexported fields
}
Expression represents a single parsed Scheme expression.
Expression wraps a syntax value produced by the parser, before any macro expansion or compilation. It captures the source name (if any) for use in error messages.
Expression is not safe for concurrent use.
func (*Expression) Source ¶
func (p *Expression) Source() string
Source returns the source name associated with this expression. Returns the empty string if no source was specified at parse time.
func (*Expression) String ¶
func (p *Expression) String() string
String returns a string representation of the expression.
type ForeignFunction ¶
type ForeignFunction = machine.ForeignFunction
ForeignFunction is the signature for primitive implementations. This is a re-export of machine.ForeignFunction for convenience.
type LibraryImportEvent ¶
type LibraryImportEvent = compilation.LibraryImportEvent
LibraryImportEvent records what happened when a library was imported. See compilation.LibraryImportEvent for field documentation.
type LibraryInfo ¶
type LibraryInfo struct {
Name string // Scheme representation, e.g. "(scheme base)"
Description string
SourceFile string
Exports []string // sorted export names
}
LibraryInfo holds read-only metadata about a Scheme library.
type LibraryName ¶
type LibraryName struct {
Parts []string
}
LibraryName identifies an R7RS library by its structured name parts. For example, the library (scheme base) has Parts ["scheme", "base"].
LibraryName is the public projection of the engine's internal library identifier: it carries the parts without exposing the machine/compilation type in the API surface. The Parts slice is owned by the caller (a fresh copy per value), so mutating it cannot affect engine state.
func (LibraryName) String ¶
func (p LibraryName) String() string
String returns the Scheme representation of the library name, e.g. "(scheme base)".
type MachineContext ¶
type MachineContext = machine.MachineContext
MachineContext provides access to the VM during primitive execution. This is a re-export of machine.MachineContext for convenience.
type Phase ¶
type Phase = environment.Phase
Phase is a typed enum identifying a stage of compilation/evaluation. Re-exported from environment for embedder convenience; use the PhaseRuntime/PhaseExpand/PhaseCompile/PhaseTemplate constants below.
type PrimitiveSpec ¶
type PrimitiveSpec = registry.PrimitiveSpec
PrimitiveSpec defines a primitive to be registered. This is a re-export of registry.PrimitiveSpec for convenience.
type Profile ¶
type Profile int
Profile identifies a named environment configuration. Each profile defines which extensions are loaded and what authorization constraints apply.
const ( // Tiny is a pure computational Scheme -- core primitives only. // No I/O, no filesystem, no threads. The lowest common denominator: // every other profile is a superset of Tiny. Tiny Profile = iota // Console adds I/O and sandboxed file access to Tiny. // All port primitives work. File operations restricted to /tmp. // stdin/stdout/stderr available. Environment variables read from // virtual env map only (no os.Getenv fallthrough). Console // ConsoleWithLoad is Console plus the eval extension, with an // authorizer that allows `code:load` under /tmp (in addition to // file r/w/d under /tmp). Enables (eval ...) and (load ...) within // the same /tmp security envelope. Process execution still denied. // Primary consumer: wile-goast and similar embedders that stage // Scheme files into /tmp and load them. ConsoleWithLoad // Small is R7RS-small complete -- all 16 (scheme ...) libraries. // Includes file I/O, system interface. No threads, no Go interop. Small // KitchenSink includes every available extension: threads, Go interop, // process execution, namespace manipulation. KitchenSink )
type RuntimeError ¶
type RuntimeError struct {
Message string
Cause error
Condition Value // non-nil when Scheme raise produced the error; nil for VM/primitive errors
Source string // formatted source location ("file:line:col"), empty if unavailable
StackTrace string // formatted VM stack trace, empty if unavailable
}
RuntimeError wraps errors from executing Scheme code.
Condition ¶
When the error originated from a Scheme raise or raise-continuable, Condition holds the raised value and RuntimeError.IsSchemeException returns true. When the error originated from Go code (VM errors, primitive failures, type mismatches), Condition is nil.
Source and Stack Trace ¶
Source and StackTrace provide the source location and VM stack trace at the point of the error. Both are empty strings when per-operation source tracking is unavailable.
Cause ¶
Cause may contain internal machine types. Callers should treat it as an opaque error suitable for logging and errors.Is/errors.As matching, not for direct type inspection.
func (*RuntimeError) Error ¶
func (p *RuntimeError) Error() string
func (*RuntimeError) IsSchemeException ¶
func (p *RuntimeError) IsSchemeException() bool
IsSchemeException reports whether this error originated from a Scheme raise or raise-continuable expression. When true, Condition holds the raised value.
func (*RuntimeError) Unwrap ¶
func (p *RuntimeError) Unwrap() error
type SandboxOption ¶
type SandboxOption func(*sandboxConfig)
SandboxOption configures the sandbox modifier.
func SandboxEnvPrefix ¶
func SandboxEnvPrefix(prefix string) SandboxOption
SandboxEnvPrefix sets the environment variable prefix that the sandbox allows reading. Default is "WILE_".
type Value ¶
type Value interface {
// SchemeString returns the Scheme representation.
SchemeString() string
// IsVoid returns true if this is the void value.
IsVoid() bool
// Internal returns the underlying values.Value for advanced use.
// This is exported for use by testing packages and advanced embedding scenarios.
Internal() values.Value
// contains filtered or unexported methods
}
Value represents a Scheme value in the public API.
func Car ¶
Car returns the car of a pair or other Tuple type. Returns (value, true) on success, or (nil, false) if v is not a non-empty Tuple.
func Cdr ¶
Cdr returns the cdr of a pair or other Tuple type. Returns (value, true) on success, or (nil, false) if v is not a non-empty Tuple.
func NewBigFloat ¶
NewBigFloat creates a big float value from a big.Float.
func NewBigFloatFromFloat64 ¶
NewBigFloatFromFloat64 creates a big float value from a float64.
func NewBigFloatFromString ¶
NewBigFloatFromString creates a big float from a string. Returns nil if the string is not a valid float.
func NewBigInteger ¶
NewBigInteger creates a big integer value from a big.Int.
func NewBigIntegerFromInt64 ¶
NewBigIntegerFromInt64 creates a big integer value from an int64.
func NewBigIntegerFromString ¶
NewBigIntegerFromString creates a big integer from a string in the given base. Returns nil if the string is not a valid integer.
func NewComplex ¶
func NewComplex(v complex128) Value
NewComplex creates a Scheme complex number from a Go complex128.
func NewComplexFromParts ¶
NewComplexFromParts creates a Scheme complex number from real and imaginary parts.
func NewRational ¶
NewRational creates a Scheme exact rational number.
func NewRationalFromBigInt ¶
NewRationalFromBigInt creates a Scheme exact rational from big.Int numerator and denominator.