Compile to Bytecode
Compile to Bytecode
Lower a Program AST into stack-based bytecode.
This is the compiler step that produces a separate executable artifact. The VM will consume this bytecode later.
Function signature
func Compile(prog *Program) Bytecode
Bytecode types
Use the provided types:
BytecodewithMain []InstrandFunctions []FunctionFunctionwithName,Params, andCode []InstrInstrwithOp,Int, andStr
Int is used for numeric literals, jump targets, and arity. Str is used for names and string literals.
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
Statements
let/var: evaluate init (or push nil), thenDEFINE_VAR <name>const: evaluate init, thenDEFINE_CONST <name>- assignment: evaluate expr, then
STORE <name> - 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
- Each function declaration becomes a
FunctioninBytecode.Functions. - Function bodies are compiled like statement lists (no extra scope wrapper).
- If the last instruction is not
RETURN, appendPUSH_NIL+RETURN. - Top-level statements compile into
Bytecode.Main.
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