vm

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 4, 2026 License: BSD-3-Clause Imports: 16 Imported by: 0

README

vm

vm is a bytecode based stack machine.

The purpose of vm is to provide a simple, fast, embeddable and portable Go execution environment.

graph LR
s[ ] --> |source| a(scanner)
--> |tokens| b(parser)
--> |AST| c(codegen)
--> |bytecode| d[vm]
subgraph vm
    d
end
style s height:0px;

The bytecode consists of a dozen of instructions, each taking 0 or 1 immediate argument (non-immediate arguments are only passed through the stack). Only a few operators for a few types are implemented. I expect to have 1 instruction per operator per numerical type, all with the same pattern, which would be generated from a template. Estimate is around 20 operators and 10 numerical types, so around 200 instructions in final.

Structurally, the vm implements logical and arithmetic operators, condional jumps for if, for and switch control flow, and function call, return and frame management.

the memory state of the vm is a slice of ([]Value), where Value is similar to a reflect.Value, containing pointers to value data and type.

The whole vm is coded in a single function of 80 lines with no dependencies. The size will grow as we add missing instructions, but the code complexity will remain the same.

the vm1 package is totally standalone and could be used for any purpose outside of mvm and/or gno.

Instructions

Opcode Parameters Stack (before : after) Description
Get local, index : v Get value at address and push it on the stack
Set local, index v : Pop stack and set value at address
Add a b : c Pop a, b and push (a+b)

Memory addresses passed to instructions are computed from a tuple of integers: local and index. local can be 0 or 1. if 0, index is the offset from the start of memory, else index is the offset from the frame pointer (fp register).

Documentation

Overview

Package vm implement a stack based virtual machine.

Index

Constants

View Source
const (
	Global = 0
	Local  = 1
)

Memory attributes.

View Source
const CallSpreadFlag int32 = 1 << 15

CallSpreadFlag is set in the B operand of Call to indicate a spread call (f(s...)), so the VM uses reflect.CallSlice instead of reflect.Call for native variadic functions.

Variables

View Source
var AnyRtype = reflect.TypeOf((*any)(nil)).Elem()

AnyRtype is the reflect.Type for the empty interface (any).

View Source
var Bridges = map[string]reflect.Type{}

Bridges maps interface method names to their bridge pointer types. Each bridge type is a struct with a Fn field and a pointer-receiver method that delegates to Fn. Populated at init time by stdlib (or any compiled package binding). The VM uses these to build wrapper types that make interpreted values satisfy Go interfaces at the native call boundary.

View Source
var CompositeBridges = map[[2]string]reflect.Type{}

CompositeBridges maps sorted pairs of method names to composite bridge pointer types that implement both methods. Used to preserve additional interface capabilities when wrapping for a single-method target interface (e.g. wrapping a Reader+WriterTo value for an io.Reader parameter keeps the WriterTo capability so io.Copy's internal type assertion succeeds).

View Source
var DisplayBridges = map[string]bool{}

DisplayBridges is the subset of Bridges that should be used when the target type is interface{}/any. These are "display" methods (String, Error, GoString, etc.) that change how the value appears in fmt output. Behavioral methods (Write, Read, Close) are NOT in this set because wrapping a value as e.g. BridgeWrite for an interface{} parameter changes its identity without benefit.

View Source
var InterfaceBridges = map[reflect.Type]reflect.Type{}

InterfaceBridges maps Go interface types to bridge pointer types that implement all methods of the interface. Each bridge struct has fields named Fn<MethodName> for each method. Used for multi-method interfaces like heap.Interface or sort.Interface.

View Source
var NumKindOffset [reflect.Float64 + 1]int

NumKindOffset maps a reflect.Kind to a 0-based offset into per-type opcode blocks. Returns -1 for non-numeric kinds.

View Source
var OpaqueRtype = reflect.TypeFor[Opaque]()

OpaqueRtype is the reflect.Type for Opaque.

View Source
var ValBridgeTypes = map[reflect.Type]bool{}

ValBridgeTypes is the set of bridge pointer types that carry a Val field holding the original concrete value. Populated at init time by stdlib.

Functions

func DumpFrame

func DumpFrame(w io.Writer, mem []Value, code Code, fp, sp, narg, nret int, di *DebugInfo)

DumpFrame decodes and pretty-prints the call frame at the given fp. di is optional (may be nil); when set, slots are annotated with variable names.

func DumpFrameStderr

func DumpFrameStderr(mem []Value, code Code, fp, sp, narg, nret int, di *DebugInfo)

DumpFrameStderr is a convenience wrapper that prints to stderr.

func RegisterArgProxy

func RegisterArgProxy(fn any, arg int, factory ProxyFactory)

RegisterArgProxy installs a ProxyFactory for argument arg of the native function fn. arg is zero-based. reflect.ValueOf(fn).Pointer() is used as the key. For methods, use RegisterArgProxyMethod instead.

func RegisterArgProxyMethod

func RegisterArgProxyMethod(recvInstance any, methodName string, arg int, factory ProxyFactory)

RegisterArgProxyMethod installs a ProxyFactory for argument arg of the named method on recvInstance's type. arg is the zero-based index into the explicit (non-receiver) argument list. recvInstance may be a typed-nil pointer (e.g. (*Encoder)(nil)); only its type is used.

func Vstring

func Vstring(lv []Value) string

Vstring returns the string representation of a list of values.

Types

type Closure

type Closure struct {
	Code int      // code address (same as the plain-int function value)
	Heap []*Value // heap-allocated cells, one per captured variable
}

Closure bundles a function code address with its captured variables.

type Code

type Code []Instruction

Code represents the virtual machine byte code.

type DebugInfo

type DebugInfo struct {
	Sources scan.Sources          // source position registry (multi-file / REPL)
	Labels  map[int]string        // code address -> label/function name
	Globals map[int]string        // data index -> symbol name
	Locals  map[string][]LocalVar // function name -> local variable list
}

DebugInfo holds symbolic information for annotating debug output. Built by the compiler from the symbol table and source registry.

func NewDebugInfo

func NewDebugInfo() *DebugInfo

NewDebugInfo returns an empty DebugInfo ready to be populated.

func (*DebugInfo) LocalName

func (d *DebugInfo) LocalName(funcName string, offset int) string

LocalName returns the variable name for a local slot offset within func funcName.

func (*DebugInfo) PosToLine

func (d *DebugInfo) PosToLine(pos Pos) string

PosToLine converts a global byte offset to a human-readable location string. Returns "" if no sources are registered or pos is out of range.

type EmbeddedField

type EmbeddedField struct {
	FieldIdx int   // index of this field in the parent struct
	Type     *Type // mvm type of the embedded field (shares identity with symbol table)
}

EmbeddedField records a mvm embedded field within a struct type.

type Iface

type Iface struct {
	Typ *Type // concrete mvm type (carries Name for method lookup)
	Val Value // the concrete value
}

Iface represents a boxed interface value at runtime. It preserves the concrete mvm type identity for dynamic method dispatch.

type IfaceMethod

type IfaceMethod struct {
	Name  string
	ID    int          // global method ID; -1 = not yet assigned
	Rtype reflect.Type // method signature (with receiver as 1st param); nil if unknown
}

IfaceMethod describes a method required by an interface type.

type Instruction

type Instruction struct {
	Op   Op
	A, B int32
	Pos  Pos
}

Instruction represents a virtual machine bytecode instruction (16 bytes). Fields A, B hold up to 2 immediate operands (0 when unused).

func (Instruction) String

func (i Instruction) String() (s string)

type LocalVar

type LocalVar struct {
	Offset int    // offset from fp (1-based, as in Get Local N)
	Name   string // variable name (short, without scope prefix)
}

LocalVar describes a local variable within a function frame.

type Machine

type Machine struct {
	MethodNames []string // names by global method ID
	// contains filtered or unexported fields
}

Machine is a stack-based virtual machine that executes bytecode instructions.

func NewMachine

func NewMachine() *Machine

NewMachine returns a pointer on a new Machine.

func (*Machine) CallFunc

func (m *Machine) CallFunc(fval Value, funcType reflect.Type, args []reflect.Value) ([]reflect.Value, error)

CallFunc executes a mvm function value with the given arguments and returns the results. It saves and restores all execution state so it can be called from native Go callbacks (reflect.MakeFunc wrappers) even while Run is in progress (single-threaded re-entrancy).

func (*Machine) DumpCallStack

func (m *Machine) DumpCallStack(w io.Writer, di *DebugInfo)

DumpCallStack walks the frame pointer chain and prints every frame.

func (*Machine) DumpCallStackStderr

func (m *Machine) DumpCallStackStderr(di *DebugInfo)

DumpCallStackStderr is a convenience wrapper that prints to stderr.

func (*Machine) MakeMethodCallable

func (m *Machine) MakeMethodCallable(ifc Iface, method Method) Value

MakeMethodCallable returns a mvm func Value suitable for Machine.CallFunc. The receiver cell is constructed with method.Path applied.

func (*Machine) MethodByName

func (m *Machine) MethodByName(t *Type, name string) (Method, bool)

MethodByName returns the first resolved method named `name` reachable from t. For pointer types, methods declared on the element type are also searched (mvm registers methods on the base type T, not *T). Struct-field *Type shallow copies preserve a Base back-pointer to the source type so methods registered after the copy was taken (typical when a struct is defined before its methods) remain reachable. Returns (Method, true) on hit.

func (*Machine) Out

func (m *Machine) Out() io.Writer

Out returns the machine's standard output writer.

func (*Machine) PopExit

func (m *Machine) PopExit()

PopExit removes the last machine code instruction if is Exit.

func (*Machine) Push

func (m *Machine) Push(v ...Value) (l int)

Push pushes data values into the machine's global storage. Globals are always loaded via Push before Run is called.

func (*Machine) PushCode

func (m *Machine) PushCode(code ...Instruction) (p int)

PushCode adds instructions to the machine code (with zero source positions).

func (*Machine) Run

func (m *Machine) Run() (err error)

Run runs a program.

func (*Machine) SetDebugIO

func (m *Machine) SetDebugIO(in io.Reader, out io.Writer)

SetDebugIO sets the I/O streams for the interactive debug mode.

func (*Machine) SetDebugInfo

func (m *Machine) SetDebugInfo(fn func() *DebugInfo)

SetDebugInfo registers a function that builds DebugInfo on demand.

func (*Machine) SetIO

func (m *Machine) SetIO(in io.Reader, out, err io.Writer)

SetIO sets the I/O streams for the machine.

func (*Machine) SetIP

func (m *Machine) SetIP(ip int)

SetIP sets the value of machine instruction pointer to given index.

func (*Machine) Top

func (m *Machine) Top() (v Value)

Top returns (but not remove) the value on the top of machine stack.

func (*Machine) TrimStack

func (m *Machine) TrimStack()

TrimStack removes leftover stack values from a previous Run. Call before pushing new global data on re-entry.

type Method

type Method struct {
	Index      int   // data index of code address (-1 if unset or EmbedIface)
	Path       []int // field index path to embedded receiver (nil = direct, []int{} = deref only)
	EmbedIface bool  // Path leads to an embedded interface field; dispatch through it
	PtrRecv    bool  // true if the method has a pointer receiver (e.g. *T)
}

Method records a method's code location and receiver path for interface dispatch.

func (Method) IsResolved

func (m Method) IsResolved() bool

IsResolved reports whether this method slot has been populated with either a compiled code address or an embedded-interface dispatch entry.

type MvmFunc

type MvmFunc struct {
	Val Value         // mvm func (int code addr or Closure)
	GF  reflect.Value // reflect.MakeFunc wrapper for native Go callbacks
}

MvmFunc bundles a mvm func value with its native Go reflect.MakeFunc wrapper. Stored when a mvm func is assigned to a struct field of func type: GF is callable from native Go (HTTP handlers, callbacks, etc.); Val is the original mvm func dispatched directly by the VM.

type Op

type Op int32

Op is a VM opcode (bytecode instruction).

const (
	// Instruction effect on stack: values consumed -- values produced.
	Nop          Op = iota // --
	Addr                   // a -- &a ;
	AddrLocal              // -- &local ; push pointer to mem[fp-1+$1]; promotes slot to addressable storage on first use so writes via the pointer propagate back
	Append                 // slice [v0..vn-1] -- slice' ; append $0 values to slice
	AppendSlice            // slice [v0..vn-1] -- slice' ; pack $0 values into []T, reflect.AppendSlice; elem type at mem[$1]; $0=0 means spread mode: append(a, b...)
	Call                   // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...); B bit 15 = spread flag
	CallImm                // [a1 .. ai] -- [r1 .. rj] ; $1=dataIdx of func, $2=narg<<16|nret
	Cap                    // -- x ; x = cap(mem[sp-$0])
	Convert                // v -- v' ; v' = convert(v, type at mem[$1]); optional $2 = stack depth offset
	CopySlice              // dst src -- n ; n = copy(dst, src)
	DeferPush              // func [a0..an-1] -- func [a0..an-1] [packed prevHead retIP] ; register deferred call on stack; $0=narg, $1=1 if native
	DeferRet               // -- ; sentinel: restore outer frame after a deferred call returns
	DeleteMap              // map key -- ; delete(map, key)
	Deref                  // x -- *x ;
	DerefSet               // ptr val -- ; *ptr = val
	Equal                  // n1 n2 -- cond ; cond = n1 == n2
	EqualSet               // n1 n2 -- n1 cond ; cond = n1 == n2
	Exit                   // -- ;
	Field                  // s -- f ; f = s.FieldIndex($1, ...)
	FieldFset              // s i v -- s; s.FieldIndex(i) = v
	FieldRefSet            // fref v -- ; fref = v (via setFuncField)
	FieldSet               // s d -- s ; s.FieldIndex($1, ...) = d
	Fnew                   // -- x; x = new mem[$1]
	FnewE                  // -- x; x = new mem[$1].Elem()
	Get                    // addr -- value ; value = mem[addr]
	Grow                   // -- ; sp += $1
	HeapAlloc              // -- &cell ; cell = new(Value), push its pointer
	HeapGet                // -- v    ; v = *State.Heap[$1]
	HeapPtr                // -- &cell ; push State.Heap[$1] itself (transitive capture)
	HeapSet                // v --    ; *State.Heap[$1] = v
	CellGet                // -- v    ; cell = mem[fp-1+$1].(*Value); push *cell
	CellSet                // v --    ; cell = mem[fp-1+$1].(*Value); *cell = v
	IfaceCall              // iface -- closure ; dynamic dispatch method $1 on iface
	IfaceWrap              // v -- iface ; wrap v in Iface{type at $1, v}
	Index                  // a i -- a[i] ;
	IndexAddr              // a i -- &a[i] ; pointer to element
	IndexSet               // a i v -- a; a[i] = v
	Jump                   // -- ; ip += $1
	JumpFalse              // cond -- ; if cond { ip += $1 }
	JumpSetFalse           //
	JumpSetTrue            //
	JumpTrue               // cond -- ; if cond { ip += $1 }
	Len                    // -- x; x = mem[sp-$1]
	MapIndex               // a i -- a[i]
	MapIndexOk             // a i -- v ok ; v, ok = a[i]
	MapSet                 // a i v -- a; a[i] = v
	MkClosure              // code [&c0..&cn-1] -- clo ; clo = Closure{code, heap}
	MkMap                  // -- map ; create map[K]V, key type at mem[$0], val type at mem[$1]
	MkSlice                // [v0..vn-1] -- slice ; collect $0 values into []T, elem type at mem[$1]
	New                    // -- x; mem[fp+$1] = new mem[$2]
	Next                   // -- ; iterator next, set K
	Next0                  // -- ; iterator next, no variable
	Next2                  // -- ; iterator next, set K V
	Not                    // c -- r ; r = !c
	Panic                  // v -- ; pop value, start stack unwinding
	PanicUnwind            // -- ; sentinel: handle panic stack unwinding
	Pop                    // v --
	PtrNew                 // -- ptr ; ptr = new(T), type at mem[$0]
	Pull                   // a -- a s n; pull iterator next and stop function
	Pull2                  // a -- a s n; pull iterator next and stop function
	Push                   // -- v
	Recover                // -- v ; push recovered value (or nil if not panicking in a deferred call)
	Return                 // [r1 .. ri] -- ; exit frame, nret and frameBase from frames
	SetGlobal              // v -- ; mem[$1] = v (globals)
	SetLocal               // v -- ; mem[fp-1+$1] = v
	SetS                   // dest val -- ; dest.Set(val)
	Slice                  // a l h -- a; a = a [l:h]
	Slice3                 // a l h m -- a; a = a[l:h:m]
	Stop                   // -- iterator stop; sp -= 3 + $1
	Swap                   // --
	Trap                   // -- ; pause VM execution and enter debug mode
	TypeAssert             // iface -- v [ok] ; assert iface holds type at mem[$1]; $2=0 panics, $2=1 ok form
	TypeBranch             // iface -- ; pop iface; if iface doesn't hold type at mem[$2] (or $2==-1 for nil), ip += $1
	WrapFunc               // mvmFuncVal -- MvmFunc ; wrap mvm func in reflect.MakeFunc for native callbacks; $0=typeIdx, $1=depth from sp (0=top)

	// Goroutine and channel opcodes.
	GoCall     // f [a1..ai] -- ; spawn goroutine; $0=narg
	GoCallImm  // [a1..ai] -- ; spawn goroutine to known func; $0=dataIdx, $1=narg
	MkChan     // -- ch ; create channel; $0=elemTypeIdx, $1=bufsize (-1=from stack)
	ChanSend   // ch v -- ; send to channel
	ChanRecv   // ch -- v [ok] ; receive from channel; $0=1 for ok-form
	ChanClose  // ch -- ; close channel
	SelectExec // ch0 [v0] .. chN [vN] -- chosenIdx ; $0=metaIdx, $1=ncase; calls reflect.Select

	Print   // [v0..vn-1] -- ; print $0 values to m.out
	Println // [v0..vn-1] -- ; println $0 values to m.out, space-separated, trailing newline

	Min // [v0..vn-1] -- min ; find min of $0 values; $1 = reflect.Kind for dispatch
	Max // [v0..vn-1] -- max ; find max of $0 values; $1 = reflect.Kind for dispatch

	AddStr     // s1 s2 -- s ; s = s1 + s2 (string concatenation)
	GreaterStr // s1 s2 -- cond ; cond = s1 > s2
	LowerStr   // s1 s2 -- cond ; cond = s1 < s2

	AddInt // n1 n2 -- sum
	AddInt8
	AddInt16
	AddInt32
	AddInt64
	AddUint
	AddUint8
	AddUint16
	AddUint32
	AddUint64
	AddFloat32
	AddFloat64

	SubInt // n1 n2 -- diff
	SubInt8
	SubInt16
	SubInt32
	SubInt64
	SubUint
	SubUint8
	SubUint16
	SubUint32
	SubUint64
	SubFloat32
	SubFloat64

	MulInt // n1 n2 -- prod
	MulInt8
	MulInt16
	MulInt32
	MulInt64
	MulUint
	MulUint8
	MulUint16
	MulUint32
	MulUint64
	MulFloat32
	MulFloat64

	NegInt // n -- -n
	NegInt8
	NegInt16
	NegInt32
	NegInt64
	NegUint
	NegUint8
	NegUint16
	NegUint32
	NegUint64
	NegFloat32
	NegFloat64

	GreaterInt // n1 n2 -- cond
	GreaterInt8
	GreaterInt16
	GreaterInt32
	GreaterInt64
	GreaterUint
	GreaterUint8
	GreaterUint16
	GreaterUint32
	GreaterUint64
	GreaterFloat32
	GreaterFloat64

	LowerInt // n1 n2 -- cond
	LowerInt8
	LowerInt16
	LowerInt32
	LowerInt64
	LowerUint
	LowerUint8
	LowerUint16
	LowerUint32
	LowerUint64
	LowerFloat32
	LowerFloat64

	DivInt // n1 n2 -- quot
	DivInt8
	DivInt16
	DivInt32
	DivInt64
	DivUint
	DivUint8
	DivUint16
	DivUint32
	DivUint64
	DivFloat32
	DivFloat64

	RemInt // n1 n2 -- rem (integer only)
	RemInt8
	RemInt16
	RemInt32
	RemInt64
	RemUint
	RemUint8
	RemUint16
	RemUint32
	RemUint64
	RemFloat32 // unused, but keeps NumTypes alignment
	RemFloat64 // unused, but keeps NumTypes alignment

	// Bitwise opcodes (generic, operate on raw uint64 bits).
	BitAnd    // n1 n2 -- n1 & n2
	BitOr     // n1 n2 -- n1 | n2
	BitXor    // n1 n2 -- n1 ^ n2
	BitAndNot // n1 n2 -- n1 &^ n2
	BitShl    // n1 n2 -- n1 << n2
	BitShr    // n1 n2 -- n1 >> n2 (arithmetic for signed)
	BitComp   // n -- ^n

	// Bit manipulation opcodes (32-bit and 64-bit variants).
	Clz32    // n -- count ; count leading zeros (32-bit)
	Clz64    // n -- count ; count leading zeros (64-bit)
	Ctz32    // n -- count ; count trailing zeros (32-bit)
	Ctz64    // n -- count ; count trailing zeros (64-bit)
	Popcnt32 // n -- count ; population count (32-bit)
	Popcnt64 // n -- count ; population count (64-bit)
	Rotl32   // n k -- result ; rotate left (32-bit)
	Rotl64   // n k -- result ; rotate left (64-bit)
	Rotr32   // n k -- result ; rotate right (32-bit)
	Rotr64   // n k -- result ; rotate right (64-bit)

	// Float math opcodes (unary: 1 operand; binary: 2 operands).
	AbsFloat32      // n -- |n|
	AbsFloat64      // n -- |n|
	SqrtFloat32     // n -- sqrt(n)
	SqrtFloat64     // n -- sqrt(n)
	CeilFloat32     // n -- ceil(n)
	CeilFloat64     // n -- ceil(n)
	FloorFloat32    // n -- floor(n)
	FloorFloat64    // n -- floor(n)
	TruncFloat32    // n -- trunc(n)
	TruncFloat64    // n -- trunc(n)
	NearestFloat32  // n -- nearest(n)
	NearestFloat64  // n -- nearest(n)
	MinFloat32      // a b -- min(a,b)
	MinFloat64      // a b -- min(a,b)
	MaxFloat32      // a b -- max(a,b)
	MaxFloat64      // a b -- max(a,b)
	CopysignFloat32 // a b -- copysign(a,b)
	CopysignFloat64 // a b -- copysign(a,b)

	// Immediate operand variants: fold Push+BinOp into one instruction.
	// Arg[0] holds the right-hand constant (int, sign-extended to int64).
	AddIntImm      // n -- n+$1
	SubIntImm      // n -- n-$1
	MulIntImm      // n -- n*$1
	GreaterIntImm  // n -- n>$1  (signed)
	GreaterUintImm // n -- n>$1 (unsigned)
	LowerIntImm    // n -- n<$1  (signed)
	LowerUintImm   // n -- n<$1  (unsigned)

	GetGlobal  // -- value ; value = mem[$1] (global variable, syncs num from ref if needed)
	GetLocal   // -- value ; value = mem[$1+fp-1] (local variable, no scope check)
	NextLocal  // -- ; iterator next, set K (local scope); like Next but scope is always Local
	Next2Local // -- ; iterator next, set K V (local scope); like Next2 but scope is always Local

	// Fused GetLocal + operation superinstructions.
	// $1 = local offset (as in GetLocal), $2 = immediate operand.
	GetLocal2              // -- v1 v2 ; push two locals: mem[$1+fp-1] then mem[$2+fp-1]
	GetLocalAddIntImm      // -- n+$2 ; push local $1 then add immediate $2
	GetLocalSubIntImm      // -- n-$2 ; push local $1 then subtract immediate $2
	GetLocalMulIntImm      // -- n*$2 ; push local $1 then multiply by immediate $2
	GetLocalLowerIntImm    // -- cond ; push local $1 then compare < immediate $2 (signed)
	GetLocalLowerUintImm   // -- cond ; push local $1 then compare < immediate $2 (unsigned)
	GetLocalGreaterIntImm  // -- cond ; push local $1 then compare > immediate $2 (signed)
	GetLocalGreaterUintImm // -- cond ; push local $1 then compare > immediate $2 (unsigned)
	GetLocalReturn         // -- ; push local $1 then return (nret/frameBase from frame)

	// Fused compare + conditional-jump superinstructions.
	// Only LowerInt variants are needed, compiler rewrites Greater comparisons
	// using the identity: (a > imm) same as !(a < imm+1).
	LowerIntImmJumpFalse         // n -- ; if n >= $2 { ip += $1 } ; sp--
	LowerIntImmJumpTrue          // n -- ; if n < $2 { ip += $1 } ; sp--
	GetLocalLowerIntImmJumpFalse // -- ; if local >= imm { ip += $1 } ; $2 = localOff<<16 | imm&0xFFFF
	GetLocalLowerIntImmJumpTrue  // -- ; if local < imm { ip += $1 } ; $2 = localOff<<16 | imm&0xFFFF
)

Byte-code instruction set.

func (Op) String

func (i Op) String() string

type Opaque

type Opaque struct{}

Opaque stands in for an external type which could not be resolved at parse time.

type Pos

type Pos int32

Pos is the source code position of instruction.

type ProxyFactory

type ProxyFactory func(m *Machine, ifc Iface) reflect.Value

ProxyFactory builds a pointer-to-struct that wraps a mvm Iface and re-enters mvm. Used at native-call boundaries to hand a stdlib shadow package (e.g. jsonx) a proxy whose methods (MarshalJSON, UnmarshalJSON, etc.) dispatch back into the interpreter with full Iface metadata.

type SelectCaseInfo

type SelectCaseInfo struct {
	Dir    reflect.SelectDir // SelectSend, SelectRecv, or SelectDefault
	Slot   int               // local/global index for received value (-1 if unused)
	OkSlot int               // local/global index for ok bool (-1 if unused)
	Local  bool              // true if slots are local (frame-relative), false for global
}

SelectCaseInfo describes one case of a select statement.

type SelectMeta

type SelectMeta struct {
	Cases    []SelectCaseInfo
	TotalPop int // precomputed number of stack slots consumed by channel/value entries
}

SelectMeta holds metadata for a select statement, stored in the data section.

type Type

type Type struct {
	PkgPath      string
	Name         string
	Rtype        reflect.Type
	Placeholder  bool            // true for forward-declared struct placeholders until SetFields is called
	IfaceMethods []IfaceMethod   // non-nil for interface types: required method signatures
	TypeElems    []TypeElem      // non-nil for constraint interfaces: union members (e.g. cmp.Ordered)
	Methods      []Method        // concrete types: methods[methodID] = code location + receiver path
	Embedded     []EmbeddedField // mvm types of anonymous (embedded) fields, for promoted method lookup
	Params       []*Type         // mvm-level parameter types for func types (nil for non-func or if unknown)
	Returns      []*Type         // mvm-level return types for func types (nil for non-func or if unknown)
	Fields       []*Type         // mvm-level field types for struct types, parallel to reflect visible fields
	ElemType     *Type           // mvm-level element type for map/slice/array/pointer/chan types
	KeyType      *Type           // mvm-level key type for map types; nil for non-maps or native-built maps
	// Base points at the source *Type that struct-field shallow copies
	// were derived from. Methods registered on the source after the copy
	// was taken (normal for mvm, which parses struct types before
	// method declarations) remain reachable through Base.
	Base *Type
}

Type is the representation of a runtime type.

func ArrayOf

func ArrayOf(length int, t *Type) *Type

ArrayOf returns the array type with the given length and element type.

func ChanOf

func ChanOf(dir reflect.ChanDir, elem *Type) *Type

ChanOf returns the channel type with the given direction and element type.

func FuncOf

func FuncOf(arg, ret []*Type, variadic bool) *Type

FuncOf returns the function type with the given argument and result types.

func MapOf

func MapOf(k, e *Type) *Type

MapOf returns the map type with the given key and element types.

func NewStructType

func NewStructType() *Type

NewStructType creates a forward-declared struct type. Register it in the symbol table, then call SetFields to finalize.

func PointerTo

func PointerTo(t *Type) *Type

PointerTo returns the pointer type with element t.

func SliceOf

func SliceOf(t *Type) *Type

SliceOf returns the slice type with the given element type.

func StructOf

func StructOf(fields []*Type, embedded []EmbeddedField, tags []string) *Type

StructOf returns the struct type with the given field types, embedded field info, and tags.

func TypeOf

func TypeOf(v any) *Type

TypeOf returns the runtime type of v.

func (*Type) Elem

func (t *Type) Elem() *Type

Elem returns a type's element type, preserving mvm-level info (e.g. IfaceMethods).

func (*Type) EnsureIfaceMethods

func (t *Type) EnsureIfaceMethods()

EnsureIfaceMethods populates IfaceMethods from the reflect method set if not already set. This covers native interface types (e.g. io.Reader) whose method sets were not explicitly enumerated at parse time.

func (*Type) FieldIndex

func (t *Type) FieldIndex(name string) []int

FieldIndex returns the index of struct field name.

func (*Type) FieldLookup

func (t *Type) FieldLookup(name string) ([]int, *Type)

FieldLookup returns the index path and type of struct field name in a single pass.

func (*Type) FieldType

func (t *Type) FieldType(name string) *Type

FieldType returns the type of struct field name, using mvm-level info when available.

func (*Type) Implements

func (t *Type) Implements(iface *Type) bool

Implements reports whether the concrete type t satisfies interface iface. iface.IfaceMethods must have IDs populated (by the compiler) before calling this.

func (*Type) IsInterface

func (t *Type) IsInterface() bool

IsInterface reports whether t represents an interface type.

func (*Type) IsPtr

func (t *Type) IsPtr() bool

IsPtr returns true if type t is of pointer kind.

func (*Type) Key

func (t *Type) Key() *Type

Key returns a map type's key type.

func (*Type) MissingMethod

func (t *Type) MissingMethod(rt reflect.Type) string

MissingMethod returns the name of the first method required by interface type t that native reflect type rt does not have. Returns "" if all methods are present or t has no IfaceMethods.

func (*Type) NativeImplements

func (t *Type) NativeImplements(rt reflect.Type) bool

NativeImplements reports whether native reflect type rt has all the methods required by interface type t.

func (*Type) Out

func (t *Type) Out(i int) *Type

Out returns the type's i'th output parameter.

func (*Type) ReturnType

func (t *Type) ReturnType(i int) *Type

ReturnType returns the mvm-level i'th return type if known, else falls back to Out(i).

func (*Type) SameAs

func (t *Type) SameAs(u *Type) bool

SameAs reports whether t and u represent the same concrete type.

func (*Type) SetFields

func (t *Type) SetFields(src *Type)

SetFields finalizes a forward-declared struct type using src's definition. It patches the internal reflect.Type in place so that any derived types (e.g., pointer types created via PointerTo) automatically see the real layout.

func (*Type) String

func (t *Type) String() string

type TypeElem

type TypeElem struct {
	Approx bool
	Type   *Type
}

TypeElem describes one member of a constraint interface's type-element union, e.g. for "type Ordered interface { ~int | ~string }" the type elements are TypeElem{Approx: true, Type: intType}, TypeElem{Approx: true, Type: stringType}. Approx encodes the "~" prefix (any type whose underlying type is Type).

type Value

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

Value is the VM runtime value. Numeric types (bool, int*, uint*, float*) store their value inline in num. ref carries reflect.Zero(t) for type metadata on numeric types. Composite types (string, slice, map, struct, ptr, func, interface) use ref.

func FromReflect

func FromReflect(rv reflect.Value) Value

FromReflect wraps a reflect.Value into a Value.

func NewValue

func NewValue(typ reflect.Type, arg ...int) Value

NewValue returns a zero value for the specified reflect.Type.

func TypeValue

func TypeValue(typ reflect.Type) Value

TypeValue returns a zero value for use as a type descriptor in the data table. Preserves the exact reflect.Type for all kinds so opcodes like MkChan can recover it via ref.Type().

func ValueOf

func ValueOf(v any) Value

ValueOf returns the runtime value of v.

func (Value) Addr

func (v Value) Addr() reflect.Value

Addr returns a pointer value representing the address of v.

func (Value) Bool

func (v Value) Bool() bool

Bool returns v's value as bool.

func (Value) CanAddr

func (v Value) CanAddr() bool

CanAddr reports whether the value is addressable.

func (Value) CanInt

func (v Value) CanInt() bool

CanInt reports whether Int can be called without panicking.

func (Value) CopyArray

func (v Value) CopyArray() Value

CopyArray returns a Value holding a copy of the array in v, so that range iterates over a snapshot (Go spec: range over array uses a copy).

func (Value) Elem

func (v Value) Elem() reflect.Value

Elem returns the value that the interface v contains or the pointer v points to.

func (Value) Equal

func (v Value) Equal(u Value) bool

Equal reports whether v is equal to u.

func (Value) Field

func (v Value) Field(i int) reflect.Value

Field returns v's i'th field.

func (Value) FieldByIndex

func (v Value) FieldByIndex(index []int) reflect.Value

FieldByIndex returns the nested field corresponding to index.

func (Value) Float

func (v Value) Float() float64

Float returns v's value as float64.

func (Value) IfaceVal

func (v Value) IfaceVal() Iface

IfaceVal extracts the Iface from a boxed interface value.

func (Value) Index

func (v Value) Index(i int) reflect.Value

Index returns v's i'th element.

func (Value) Int

func (v Value) Int() int64

Int returns v's value as int64.

func (Value) Interface

func (v Value) Interface() any

Interface returns v's value as interface{}.

func (Value) IsIface

func (v Value) IsIface() bool

IsIface reports whether v holds a boxed interface value.

func (Value) IsValid

func (v Value) IsValid() bool

IsValid reports whether v represents a value (ref is set).

func (Value) Kind

func (v Value) Kind() reflect.Kind

Kind returns the reflect.Kind of the value.

func (Value) Len

func (v Value) Len() int

Len returns v's length.

func (Value) MapIndex

func (v Value) MapIndex(key reflect.Value) reflect.Value

MapIndex returns the value associated with key in the map v.

func (Value) Reflect

func (v Value) Reflect() reflect.Value

Reflect reconstructs a reflect.Value from an inline numeric Value. For composite types, returns ref directly. This may allocate for numeric types; use only at reflect boundaries.

func (Value) Seq

func (v Value) Seq() iter.Seq[reflect.Value]

Seq returns a range-over iterator for the value v.

func (Value) Seq2

func (v Value) Seq2() iter.Seq2[reflect.Value, reflect.Value]

Seq2 returns a range-over-2 iterator for the value v.

func (Value) Set

func (v Value) Set(x reflect.Value)

Set assigns x to the value v.

func (Value) SetMapIndex

func (v Value) SetMapIndex(key, elem reflect.Value)

SetMapIndex sets the element associated with key in the map v.

func (Value) Slice

func (v Value) Slice(i, j int) reflect.Value

Slice returns v[i:j].

func (Value) Slice3

func (v Value) Slice3(i, j, k int) reflect.Value

Slice3 returns v[i:j:k].

func (Value) Type

func (v Value) Type() reflect.Type

Type returns the reflect.Type of the value.

func (Value) Uint

func (v Value) Uint() uint64

Uint returns v's value as uint64.

func (Value) UnwrapType

func (v Value) UnwrapType() (reflect.Type, bool)

UnwrapType checks if v encodes a stdlib type as (*T)(nil). If so, it returns the underlying reflect.Type and true.

Jump to

Keyboard shortcuts

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