## PR-06 — Control flow opcodes: jumps, conditional branches, structured “if” **Why:** `if` must be predictable and verifier-safe. ### Scope * Implement opcodes: * `JMP ` * `JMP_IF_TRUE ` * `JMP_IF_FALSE ` * Verifier rules: * targets must be valid instruction boundaries * stack height at join points must match ### Tests * nested if * if with empty branches * branch join mismatch rejected ### Acceptance * Control flow is safe; no implicit stack juggling. --- ## PR-07 — Calling convention v0: CALL / RET / multi-slot returns **Why:** Without a correct call model, PBS isn’t executable. ### Scope * Introduce `CALL ` * caller pushes args (slots) * callee frame allocates locals * Introduce `RET` * callee must leave exactly `return_slots` on operand stack at `RET` * VM pops frame and transfers return slots to caller * Define return mechanics for `void` (`return_slots=0`) ### Deliverables * `FunctionTable` indexing and bounds checks * Deterministic traps: * `TRAP_INVALID_FUNC` * `TRAP_BAD_RET_SLOTS` ### Tests * `fn add(a:int,b:int):int { return a+b; }` * multi-slot return (e.g., `Pad` flattened) * void call ### Acceptance * Calls are stable and stack-clean. --- ## PR-08 — Host syscalls v0: stable ABI, multi-slot args/returns **Why:** PBS relies on deterministic syscalls; ABI must be frozen and enforced. ### Scope * Unify syscall invocation opcode: * `SYSCALL ` * Runtime validates: * pops `arg_slots` * pushes `ret_slots` * Implement/confirm: * `GfxClear565 (0x1010)` * `InputPadSnapshot (0x2010)` * `InputTouchSnapshot (0x2011)` ### Deliverables * A `SyscallRegistry` mapping id -> handler + signature * Deterministic traps: * `TRAP_INVALID_SYSCALL` * `TRAP_SYSCALL_SIG_MISMATCH` ### Tests * syscall isolated tests * wrong signature traps ### Acceptance * Syscalls are “industrial”: typed by signature, deterministic, no host surprises. --- ## PR-09 — Debug info v0: spans, symbols, and traceable traps **Why:** Industrial debugging requires actionable failures. ### Scope * Add optional debug section: * per-instruction span table (`pc -> (file_id, start, end)`) * function names * Enhance trap payload with debug span (if present) ### Tests * trap includes span when debug present * trap still works without debug ### Acceptance * You can pinpoint “where” a trap happened reliably. --- ## PR-10 — Program image + linker: imports/exports resolved before VM run **Why:** Imports are compile-time, but we need an industrial linking model for multi-module PBS. ### Scope * Define in bytecode: * `exports`: symbol -> func_id/service entry (as needed) * `imports`: symbol refs -> relocation slots * Implement a **linker** that: * builds a `ProgramImage` from N modules * resolves imports to exports * produces a single final `FunctionTable` and code blob ### Notes * VM **does not** do name lookup at runtime. * Linking errors are deterministic: `LINK_UNRESOLVED_SYMBOL`, `LINK_DUP_EXPORT`, etc. ### Tests * two-module link success * unresolved import fails * duplicate export fails ### Acceptance * Multi-module PBS works; “import” is operationalized correctly. --- ## PR-11 — Canonical integration cartridge + golden bytecode snapshots **Why:** One cartridge must be the unbreakable reference. ### Scope * Create `CartridgeCanonical.pbs` that covers: * locals * arithmetic * if * function call * syscall clear * input snapshot * Add `golden` artifacts: * canonical AST JSON (frontend) * IR Core (optional) * IR VM / bytecode dump * expected VM trace (optional) ### Tests * CI runs cartridge and checks: * no traps * deterministic output state ### Acceptance * This cartridge is the “VM heartbeat test”. --- ## PR-12 — VM test harness: stepper, trace, and property tests **Why:** Industrial quality means test tooling, not just “it runs”. ### Scope * Add `VmRunner` test harness: * step limit * deterministic trace of stack deltas * snapshot of locals * Add property tests (lightweight): * stack never underflows in verified programs * verified programs never jump out of bounds ### Acceptance * Debugging is fast, and regressions are caught. --- ## PR-13 — Optional: Refactor Value representation (tagged slots) for clarity **Why:** If current `Value` representation is the source of complexity/bugs, refactor now. ### Scope (only if needed) * Make `Slot` explicit: * `Slot::I32`, `Slot::I64`, `Slot::U32`, `Slot::Bool`, `Slot::ConstId`, `Slot::GateId`, `Slot::Unit` * Multi-slot types become sequences of slots. ### Acceptance * Simpler, more verifiable runtime. --- ## Definition of Done (DoD) for PBS v0 “minimum executable” A single canonical cartridge runs end-to-end: * `let` declarations (locals) * arithmetic (+, -, *, /, %, comparisons) * `if/else` control flow * `when` expression (if present in lowering) * function calls with params + returns (including `void`) * multiple return slots (flattened structs / hardware value types) * host syscalls (e.g., `GfxClear565`, `InputPadSnapshot`, `InputTouchSnapshot`) * deterministic traps (OOB bounded, invalid local, invalid call target, stack underflow)