Documentation
¶
Overview ¶
Package ivm implements a stack-based instruction VM for the English language. It compiles AST programs to flat instruction sequences (chunks) and executes them with a register-free, stack-based dispatch loop.
Compared with the tree-walk evaluator in the vm package, the instruction VM:
- Avoids the overhead of virtual method dispatch on each AST node
- Produces compact binary bytecode that is faster to load than serialised AST
- Makes future optimisations (constant folding, dead-code elimination) easier
File layout:
ivm.go – package doc, public entry points (Compile, Execute) opcode.go – Opcode type and opcode constants chunk.go – Chunk (instruction stream + constant pool + name pool) compiler.go – Compiler: walks the AST and emits instructions machine.go – Machine: runs a Chunk using a value stack encoding.go – Binary serialisation / deserialisation of Chunks
Index ¶
- Constants
- Variables
- func Decompile(chunk *Chunk) string
- func EncodeChunk(chunk *Chunk) ([]byte, error)
- func EncodeFile(chunk *Chunk) ([]byte, error)
- func EncodeFileWithSource(chunk *Chunk, source string) ([]byte, error)
- func Execute(chunk *Chunk, builtin BuiltinFunc, predefined map[string]interface{}) (interface{}, error)
- func Listing(chunk *Chunk, title string, useColor bool) string
- func OpName(op Opcode) string
- type BinOp
- type BuiltinFunc
- type Chunk
- type Compiler
- type FieldDef
- type FuncChunk
- type Instruction
- type Machine
- type Opcode
- type ReferenceValue
- type StructDef
- type StructInstance
- type UnaryOp
Constants ¶
const InstructionFormatVersion uint8 = 3
InstructionFormatVersion is the bytecode format version for instruction-based .101 files.
Variables ¶
var MagicBytes = []byte{0x10, 0x1E, 0x4E, 0x47}
Magic bytes and version for .101 instruction-format files.
Functions ¶
func EncodeChunk ¶
EncodeChunk serialises a Chunk to binary (without file header).
func EncodeFile ¶
EncodeFile serialises chunk with magic header + version byte.
func EncodeFileWithSource ¶
EncodeFileWithSource serialises chunk with magic header + version byte and appends the original source code as a trailing section so the file can be transpiled to Python without the original .abc file. The trailer format is: [uint32-LE source_len][source UTF-8 bytes]. If source is empty the trailer is omitted and the output is identical to EncodeFile.
func Execute ¶
func Execute(chunk *Chunk, builtin BuiltinFunc, predefined map[string]interface{}) (interface{}, error)
Execute runs a compiled Chunk and returns the last value (or nil). builtin is the stdlib function dispatcher. predefined is a map of pre-defined constant values (e.g. math.Pi).
Types ¶
type BuiltinFunc ¶
BuiltinFunc is the stdlib function dispatcher.
type Chunk ¶
type Chunk struct {
Constants []interface{} // number (float64), string, bool, nil
Names []string // variable/function names
Code []Instruction
Funcs []*FuncChunk // user-defined function sub-chunks
StructDefs []*StructDef // struct type definitions
}
Chunk is a compiled instruction stream together with its supporting data pools.
func DecodeChunk ¶
DecodeChunk deserialises a Chunk from raw binary (without file header).
func DecodeFile ¶
DecodeFile verifies magic + version and deserialises the chunk. Any embedded source trailer is silently ignored; use DecodeFileAll to retrieve it.
func DecodeFileAll ¶
DecodeFileAll verifies magic + version, deserialises the chunk, and returns any embedded source code. The returned source is empty when the file was produced without a source trailer (e.g. compiled with an older version of the tool).
func (*Chunk) AddConst ¶
AddConst appends a constant to the pool and returns its index. Constants are NOT deduplicated so every literal gets its own slot.
func (*Chunk) AddName ¶
AddName appends a name to the pool, deduplicating by value, and returns the index.
func (*Chunk) CurrentPos ¶
CurrentPos returns the index of the next instruction to be emitted. Used to record jump source positions for later patching.
type Compiler ¶
type Compiler struct {
// contains filtered or unexported fields
}
Compiler walks an AST and emits instructions into a Chunk.
type FieldDef ¶
type FieldDef struct {
Name string
TypeName string
DefaultExprChunk *Chunk // compiled default-value expression, or nil
}
FieldDef describes a single struct field.
type Instruction ¶
Instruction is a single VM instruction: an opcode plus a 32-bit operand.
type Machine ¶
type Machine struct {
// contains filtered or unexported fields
}
Machine executes a compiled Chunk.
type Opcode ¶
type Opcode byte
Opcode is a single-byte instruction code.
const ( // ── Constants ───────────────────────────────────────────────────────── OP_LOAD_CONST Opcode = iota // push constants[operand] OP_LOAD_NOTHING // push nil // ── Variables ───────────────────────────────────────────────────────── OP_LOAD_VAR // push env[names[operand]] OP_STORE_VAR // env.Set(names[operand], pop()) OP_DEFINE_VAR // env.Define(names[operand], pop(), false) OP_DEFINE_CONST // env.Define(names[operand], pop(), true) OP_DEFINE_TYPED // pop value, pop type_name_str; env.DefineTyped(names[operand], type, val, false) OP_DEFINE_TYPED_CONST // pop value, pop type_name_str; env.DefineTyped(names[operand], type, val, true) OP_TOGGLE_VAR // toggle boolean at names[operand] // ── Arithmetic / comparison ──────────────────────────────────────────── OP_BINARY_OP // binary operation; operand encodes BinOp OP_UNARY_OP // unary operation; operand encodes UnaryOp // ── Control flow ────────────────────────────────────────────────────── OP_JUMP // jump to operand (absolute) OP_JUMP_IF_FALSE // pop condition; jump to operand if false/error OP_JUMP_IF_TRUE // pop condition; jump to operand if true // ── Scope ───────────────────────────────────────────────────────────── OP_PUSH_SCOPE // push a new child environment OP_POP_SCOPE // restore parent environment // ── Functions ───────────────────────────────────────────────────────── OP_DEFINE_FUNC // define function; operand = func chunk index in chunk.Funcs OP_CALL // call function; operand = argc<<16 | name_idx OP_CALL_METHOD // call method; operand = argc<<16 | method_name_idx; object on stack below args OP_RETURN // return top of stack (or nil if stack empty) // ── Output ──────────────────────────────────────────────────────────── OP_PRINT // print; operand = count<<1 | newline_flag // ── Collections ─────────────────────────────────────────────────────── OP_BUILD_LIST // build list; operand = element count OP_BUILD_RANGE // build range; pop end, pop start; push list OP_BUILD_ARRAY // build typed array; operand = element count; pop type name string after elements OP_BUILD_LOOKUP // push empty lookup table OP_INDEX_GET // pop index, pop list; push list[index] OP_INDEX_SET // operand = list name index; pop value, pop index; list[index] = value OP_LENGTH // pop value; push length // ── Lookup table ────────────────────────────────────────────────────── OP_LOOKUP_GET // pop key, pop table; push table[key] OP_LOOKUP_SET // operand = table name index; pop value, pop key; table[key] = value OP_LOOKUP_HAS // pop key, pop table; push bool (key in table) // ── Type operations ─────────────────────────────────────────────────── OP_TYPEOF // pop value; push type name string OP_CAST // operand = type name index; pop value; push cast(value, type) OP_NIL_CHECK // operand: 1=is_something, 0=is_nothing; pop value; push bool OP_ERROR_TYPE_CHECK // operand = type name index; pop value; push bool // ── Input ───────────────────────────────────────────────────────────── OP_ASK // operand: 1=has_prompt, 0=no_prompt; [pop prompt;] push input line // ── Location ────────────────────────────────────────────────────────── OP_LOCATION // operand = name index; push address string // ── Struct ──────────────────────────────────────────────────────────── OP_DEFINE_STRUCT // operand = struct def index in chunk.StructDefs OP_NEW_STRUCT // operand = field_count<<16 | struct_name_idx; pop field values; push struct instance OP_GET_FIELD // operand = field name index; pop object; push field value OP_SET_FIELD // operand = field_name_idx; pop value, then load object by name (object_name in next operand via names); simpler: pop value, pop object; set field // ── Error handling ──────────────────────────────────────────────────── OP_RAISE // operand = type_name_idx (0 = generic/RuntimeError); pop message OP_TRY_BEGIN // operand = catch offset; push try frame OP_TRY_END // pop try frame; operand = end offset (jump past catch+finally) OP_CATCH // operand = error_var_name_idx; bind error var (type check moved to handleError) // OP_TRY_SET_ERRORTYPE sets the error-type filter on the top try frame. // operand = nameIdx+1 (0 means catch-all / no filter). // Emitted immediately after OP_TRY_BEGIN when the catch clause has a type filter. OP_TRY_SET_ERRORTYPE // OP_TRY_SET_FINALLY records the bytecode offset where the finally body starts. // operand = finally_offset. Emitted after OP_TRY_BEGIN (and optional OP_TRY_SET_ERRORTYPE). // When set, handleError will jump to this offset (instead of the catch handler) on a type // mismatch, run the finally body, and then re-raise via OP_RERAISE_PENDING. OP_TRY_SET_FINALLY // OP_RERAISE_PENDING re-raises frame.pendingError if it is set. // Emitted at the end of every finally body so that a type-mismatch error gets // re-propagated after the finally block finishes. OP_RERAISE_PENDING // ── Error type declaration ──────────────────────────────────────────── OP_DEFINE_ERROR_TYPE // operand = name_idx<<16 | parent_name_idx (0 = no parent) // ── Reference / copy ────────────────────────────────────────────────── OP_MAKE_REFERENCE // operand = name index; push reference value OP_MAKE_COPY // pop value; push deep copy // ── Swap ────────────────────────────────────────────────────────────── OP_SWAP_VARS // operand = name1_idx<<16 | name2_idx // ── Import ──────────────────────────────────────────────────────────── OP_IMPORT // operand = flags (importAll<<2 | isSafe<<1 | hasItems); top of stack = path string // ── Line tracking ───────────────────────────────────────────────────── OP_SET_LINE // operand = line number // ── Stack management ────────────────────────────────────────────────── OP_POP // discard top of stack )
type ReferenceValue ¶
type ReferenceValue struct {
Name string
Env *ivmEnv
}
ReferenceValue holds a reference to a named variable in a specific scope.
type StructInstance ¶
StructInstance is the ivm runtime representation of a struct instance. Field values are mutable through the pointer.