vm

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package vm executes compiled Kukel programs on a stack machine.

Each call has a frame. A frame's slots (parameters, locals, hidden slots) sit on the value stack at frame.base, followed by its operand stack. The callee value sits just below the slots.

Index

Constants

View Source
const MaxFrames = 10000

MaxFrames bounds the call depth; deeper recursion is a stack overflow.

Variables

This section is empty.

Functions

This section is empty.

Types

type Builtins

type Builtins func(name string) (*value.BuiltinObj, bool)

Builtins resolves built-in functions by name.

type Canceller added in v0.2.0

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

Canceller stops a running program from another goroutine. Cancellers form a tree: cancelling one cancels the ones made from it (Child).

func NewCanceller added in v0.2.1

func NewCanceller() *Canceller

NewCanceller makes a Canceller that nothing has cancelled yet.

func (*Canceller) Cancel added in v0.2.0

func (c *Canceller) Cancel(reason error)

Cancel makes the programs that use c (and its children) stop at their next step with a CancelledError that try cannot catch; Go functions that wait (sleep, receive) return at once. It may be called from any goroutine, and more than once.

func (*Canceller) Child added in v0.2.1

func (c *Canceller) Child() *Canceller

Child makes a Canceller that is cancelled when c is (at once if c already is).

func (*Canceller) Keep added in v0.2.1

func (c *Canceller) Keep()

Keep marks c as used by a worker (see Release).

func (*Canceller) Release added in v0.2.1

func (c *Canceller) Release(child *Canceller)

Release forgets child (made by Child) when it is no longer needed, unless workers use it: they must still be cancelled with c.

type DebugFrame added in v0.15.0

type DebugFrame struct {
	Func *bytecode.Function
	Line int              // the line it is at (where it called the next frame)
	This *value.ObjectObj // the object of a member function call, or nil
}

DebugFrame is a call the program is in, for the debugger.

type DebugVar added in v0.15.0

type DebugVar struct {
	Name  string
	Value value.Value
}

DebugVar is a variable of a frame: a parameter, local or captured one.

type RuntimeError

type RuntimeError struct {
	Value value.Value  // the thrown Error object (nil for the step limit, cancellation, exit)
	Kind  string       // its kind (never "": an empty kind becomes the class name)
	Msg   string       // its message ("" without one)
	Trace []TraceEntry // innermost call first
	Fatal bool         // try cannot catch it (exit, the step limit, cancellation)
	Exit  *int         // set by exit(code): not an error, the program ends
}

RuntimeError is a thrown exception: the thrown value and the stack trace at the throw. It is what Run returns for an exception nobody caught.

func (*RuntimeError) Error

func (e *RuntimeError) Error() string

Error returns the message and the stack trace. Long traces (deep recursion) show only the first and last traceEnds calls.

type TraceEntry

type TraceEntry struct {
	Func string
	File string
	Line int
}

TraceEntry is one line of a stack trace.

type VM

type VM struct {

	// StepLimit, when positive, stops the program with a fatal error after
	// that many backward jumps, calls of Kukel functions and thrown
	// exceptions: for tests, and for Go programs that run untrusted code
	// (the kukel package resets the count for every call from Go).
	StepLimit int

	// Debug, when set, runs at every BREAK instruction: at the start of each
	// source line of code that the debugger made a copy of (Debuggable).
	// The VM's frames are then as at the start of that line (Frames). An
	// error stops the program (a fatal one, such as exit, ends it).
	Debug func(vm *VM) error
	// contains filtered or unexported fields
}

VM runs one program.

func New

func New(prog *bytecode.Program, builtins Builtins, stdout io.Writer, stdin io.Reader) (*VM, error)

New prepares prog for running: it binds the functions and built-ins to their global slots.

func NewWith added in v0.2.0

func NewWith(prog *bytecode.Program, builtins Builtins, config *native.Config, stdout io.Writer, stdin io.Reader) (*VM, error)

NewWith is New for a program limited by config (see native.Config): it refuses a program that uses a built-in or module config does not allow.

func (*VM) BuiltinLookup added in v0.2.0

func (vm *VM) BuiltinLookup() Builtins

BuiltinLookup is how the VM found its built-ins (New's builtins).

func (*VM) Call

func (vm *VM) Call(fn value.Value, args []value.Value) (value.Value, error)

Call calls fn from a built-in (sort's comparator, for example). The built-in's own arguments stay on the stack below the new call.

func (*VM) Cancellable added in v0.2.0

func (vm *VM) Cancellable() *Canceller

Cancellable makes the program cancellable from now on with the returned Canceller (replacing an earlier one). Workers started afterwards share it: cancelling the program cancels them too.

func (*VM) CloseOutput added in v0.2.1

func (vm *VM) CloseOutput()

CloseOutput flushes the output shared with workers (ShareOutput) and drops what they write later. Run does it when main returns.

func (*VM) Config added in v0.2.0

func (vm *VM) Config() *native.Config

Config is what the program may use (nil: everything).

func (*VM) CurrentCanceller added in v0.2.0

func (vm *VM) CurrentCanceller() *Canceller

CurrentCanceller is the VM's Canceller, or nil.

func (*VM) Done added in v0.2.0

func (vm *VM) Done() <-chan struct{}

Done implements value.Env: closed when the program is cancelled (nil if it cannot be).

func (*VM) Err added in v0.2.0

func (vm *VM) Err() error

Err implements value.Env: the error for a cancelled program, else nil.

func (*VM) Extend added in v0.7.0

func (vm *VM) Extend(prog *bytecode.Program) error

Extend continues with prog, a program that adds to the VM's program (compiler.Session): globals, classes and functions after the ones the VM has, and member functions defined since for the classes it has. The values of the globals stay.

func (*VM) Frames added in v0.15.0

func (vm *VM) Frames() []DebugFrame

Frames gives the calls the program is in, outermost first; the last is the one at the BREAK the debug hook was called for.

func (*VM) Global added in v0.2.0

func (vm *VM) Global(name string) (value.Value, bool)

Global returns the value of the global called name: a top-level name of the program ("main"), or a module's ("util::f", "json::encode").

func (*VM) Init added in v0.2.0

func (vm *VM) Init() error

Init runs the global initializers, the first time only. If they throw an exception, every later Init gives the same error: the globals are not usable. If the step limit or a cancellation stopped them, the next Init runs them again from the start.

func (*VM) Local added in v0.2.0

func (vm *VM) Local(key any, init func() any) any

Local implements value.Env.

func (*VM) Program added in v0.2.0

func (vm *VM) Program() *bytecode.Program

Program is the program the VM runs.

func (*VM) Rand

func (vm *VM) Rand() *rand.Rand

func (*VM) ResetSteps added in v0.2.0

func (vm *VM) ResetSteps()

ResetSteps starts counting steps for StepLimit from zero again.

func (*VM) Run

func (vm *VM) Run(args []string) (int, error)

Run runs the global initializers, then main(args). It returns main's result as the exit code (an int result; anything else is 0).

When main returns, the program ends: if workers share the output (ShareOutput), it is flushed and closed, so that workers still running cannot write any more.

func (*VM) SetStderr

func (vm *VM) SetStderr(w io.Writer)

SetStderr sets where eprint writes.

func (*VM) ShareCanceller added in v0.2.0

func (vm *VM) ShareCanceller(c *Canceller)

ShareCanceller makes vm stop when c is cancelled (for a worker).

func (*VM) ShareOutput added in v0.2.0

func (vm *VM) ShareOutput() (stdout, stderr io.Writer)

ShareOutput makes the VM's standard output and error safe to use from several goroutines (workers) and returns them; other VMs can write to them too. Calling it again gives the same writers.

func (*VM) Start added in v0.2.0

func (vm *VM) Start(fn value.Value, args []value.Value) (value.Value, error)

Start runs the global initializers, then calls fn(args...) and gives its result. With fn nil it calls main, with args[0] as its parameter if main has one. exit(code) gives a *RuntimeError with Exit set.

func (*VM) Started

func (vm *VM) Started() time.Time

func (*VM) Stderr

func (vm *VM) Stderr() io.Writer

func (*VM) Stdin

func (vm *VM) Stdin() *bufio.Reader

func (*VM) Stdout

func (vm *VM) Stdout() io.Writer

Stdout, Stderr, Stdin, Call, Rand, Started, Local, Thrown, Done and Err implement value.Env for the built-ins and the native modules.

func (*VM) Thrown added in v0.2.0

func (vm *VM) Thrown(err error) (value.Value, bool)

Thrown implements value.Env.

func (*VM) Vars added in v0.15.0

func (vm *VM) Vars(i int) []DebugVar

Vars gives the variables of frame i (an index into Frames): parameters and locals by their slots (a slot that two blocks share has the name of the later one), then captured variables.

Jump to

Keyboard shortcuts

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