Compile to Bytecode v3
Compile to Bytecode v3
Lower a v3 Program AST into stack-based bytecode with closures, arrays, maps, and indexing.
Function signature
func Compile(prog *Program) Bytecode
Bytecode types
Use the provided types:
BytecodewithMain []InstrandFunctions []FunctionFunctionwithID,Name,Params, andCode []InstrInstrwithOp,Int, andStr
Int is used for numbers, jump targets, and arity. Str is used for string literals and variable names.
Instruction rules
Literals / variables
- number:
PUSH_NUM <int> - string:
PUSH_STR <string> - bool:
PUSH_BOOL <0|1> - nil:
PUSH_NIL - identifier:
LOAD <name>
Unary / binary
- unary
-:NEG - unary
!:NOT + - * / == != < <= > >=map to their matching opcodes
Arrays / maps / indexing
- array literal: push each element, then
MAKE_ARRAY <count> - map literal: push key then value for each pair, then
MAKE_MAP <count> - index expression: push target, push index,
GET_INDEX
Statements
let/var: evaluate init (or push nil), thenDEFINE_VAR <name>const: evaluate init, thenDEFINE_CONST <name>- assignment to identifier: evaluate expr, then
STORE <name> - assignment to index: push target, index, value, then
SET_INDEX - expression statement: evaluate expr, then
POP - block:
ENTER_SCOPE, compile statements,EXIT_SCOPE - return: evaluate expr (or push nil), then
RETURN
Control flow
if:- compile condition
JUMP_IF_FALSE <else>- compile then-block
JUMP <end>- compile else-block (if any)
while:- loop start label
- compile condition
JUMP_IF_FALSE <end>- compile body
JUMP <start>
Jumps use absolute instruction indexes in the current code slice.
Functions and closures
- Each
fnstatement creates aFunctionwith a uniqueID. - In the surrounding code, emit
MAKE_CLOSURE <id>thenDEFINE_CONST <name>. - Functions can be nested; compile them where they appear.
- Function bodies are compiled like statement lists (no extra scope wrapper).
- If the last instruction is not
RETURN, appendPUSH_NIL+RETURN.
Calls
- Compile the callee expression, then each argument, then emit
CALL <arity>.
Notes
- Assume the AST is already valid.
- Keep the compiler readable and straightforward.
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