v3 Bytecode: Closures and Indexing
- Derive stack operands for closures, collections, and indexing.
- Separate function IDs from slice positions and runtime closure instances.
- Preserve source evaluation order through reverse stack consumption.
1 / 6
For let a=[4,5]; a[1]=9; let x=a[1];:
PUSH_NUM 4
PUSH_NUM 5
MAKE_ARRAY 2
DEFINE_VAR a
LOAD a
PUSH_NUM 1
PUSH_NUM 9
SET_INDEX
LOAD a
PUSH_NUM 1
GET_INDEX
DEFINE_VAR x
MAKE_ARRAY consumes two values and pushes one object while preserving element order. SET_INDEX consumes value 9, index 1, then the array target; it mutates the object and pushes nothing. GET_INDEX consumes target/index and pushes the element. Both statements restore the original stack height.
A code generator emits SET_INDEX and then POP for the assignment a[0]=2;. Another uses a function’s slice position as its ID after compiling a nested declaration. Diagnose both failures.
Lower make()[idx()] = value(); and annotate the evaluation order without executing the calls. Then compile a function containing one nested function and compare reserved IDs with function-table order.
Carry exact stack contracts into the v3 VM. Save a container assignment, a closure call, and a nested-function ID example for BC2 round-trip tests.