Bytecode VM v3
Bytecode VM v3
Implement a stack-based virtual machine with closures, arrays, maps, indexing, and mark-sweep GC.
API
func NewVM() *VM
func (vm *VM) Run(bc Bytecode) (Value, error)
func (vm *VM) GC()
func (vm *VM) HeapCount() int
Run should execute bc.Main. It should start from a clean VM state (fresh stack and environment).
Bytecode types
Use the provided types:
BytecodewithMain []InstrandFunctions []FunctionFunctionwithID,Name,Params, andCode []InstrInstrwithOp,Int, andStr
Value types
Use the provided Value struct with kinds:
- number
- string
- bool
- nil
- array
- map
- closure
Arrays, maps, and closures are heap objects managed by GC.
Runtime rules
Truthiness
falseandnilare falsey- everything else is truthy
Arithmetic / comparison
+ - * /work on numbers+also supports string concatenation when both operands are strings< <= > >=work on numbers==/!=compare by type and value (arrays/maps/closures compare by identity)
Type mismatches should return a non-nil error.
Variables and scopes
DEFINE_VAR/DEFINE_CONSTcreate bindings in the current scopeSTOREupdates the nearest existing binding (error if const)LOADreads the nearest existing bindingENTER_SCOPE/EXIT_SCOPEpush and pop scope frames
Functions and closures
MAKE_CLOSURE <id>captures the current environment and pushes a closure value.CALL <arity>pops arguments and a callee. The callee must be a closure.- Create a new environment for each call with parent = closure environment.
- Bind parameters left-to-right.
- If a function returns without
RETURN, its result isnil.
Arrays and maps
MAKE_ARRAY <n>popsnvalues and creates an array (preserve order).MAKE_MAP <n>pops2nvalues (key then value) and creates a map.- Map keys must be
number,string,bool, ornil. - Pairs are evaluated left-to-right; for duplicate keys, the last source pair supplies the stored value. Reverse stack popping must preserve that policy.
Indexing
GET_INDEXpops index and target:- array: index must be number, in range
- map: key must be hashable, missing key returns
nil
SET_INDEXpops value, index, target:- array: index must be number, in range
- map: key must be hashable, sets or overwrites
Program result
After executing Main, return the top of the stack if present; otherwise return nil.
GC
Implement mark-sweep GC over heap objects.
- Roots include the value stack and all reachable environments.
- Trace array elements, map values, and closure environment chains. Map keys are primitive
hashKeyrecords and contain no references to VM heap objects. Function IDs and bytecode are not GC heap objects. - Closures keep their captured environments alive. Mark an object before traversing its children; track visited environments to terminate cycles.
- Clear marks on survivors after each sweep. The global environment remains a root after
Run; locals in exited scopes require another reachable path. HeapCountreturns the number of heap objects currently tracked. Unreachable allocations remain counted until collection.
Before implementation
Use the module’s worked reconstruction and independent debugging lab to predict an intermediate artifact first. Preserve one failing counterexample while implementing the stated API. The lesson’s transfer task uses a fresh case after the guided trace.
Run tests to see results
No issues detected