plans/sx-vm-opcode-extension.md ports over from loops/erlang (f6a68656)
with the opcode partition adjusted to match real VM usage: 1-199 core
(current ceiling 175 = OP_DEC), 200-247 extensions, 248-255 reserved.
plans/agent-briefings/sx-vm-extensions-loop.md captures the per-fire
workflow and ground rules.
87 lines
3.8 KiB
Markdown
87 lines
3.8 KiB
Markdown
# sx-vm-extensions loop agent
|
|
|
|
Role: drives `plans/sx-vm-opcode-extension.md` to completion. One phase per
|
|
fire (A → B → C → D → E). Bounded loop — after Phase E acceptance, the loop
|
|
is done.
|
|
|
|
```
|
|
description: sx-vm-extensions queue loop
|
|
subagent_type: general-purpose
|
|
run_in_background: true
|
|
isolation: worktree (already on loops/sx-vm-extensions)
|
|
```
|
|
|
|
## What this loop is for
|
|
|
|
Mechanism in `hosts/ocaml/lib/` that lets language ports register specialized
|
|
bytecode opcodes without modifying the SX VM core. Direct prerequisite for
|
|
**erlang-on-sx Phase 9** (the BEAM analog) and a structural enabler for any
|
|
future language port that wants performance-critical opcodes.
|
|
|
|
## The queue
|
|
|
|
Per `plans/sx-vm-opcode-extension.md`, in order:
|
|
|
|
- **Phase A** — Opcode ID partition + dispatch fallthrough in `sx_vm.ml`.
|
|
Add `Invalid_opcode of int` exception, `extension_dispatch_ref`, the
|
|
`| op when op >= 200 -> !extension_dispatch_ref op vm frame` arm, and a
|
|
partition comment near the opcode list.
|
|
- **Phase B** — Extension registry module (`sx_vm_extensions.ml`).
|
|
`register`, `dispatch`, `id_of_name`, `state_of_extension`. Wire dispatch
|
|
into Phase A's ref at module init.
|
|
- **Phase C** — Compiler-side opcode lookup primitive (`extension-opcode-id`).
|
|
- **Phase D** — Test extension at `hosts/ocaml/lib/extensions/test_ext.ml`,
|
|
end-to-end SX → bytecode → VM dispatch flow.
|
|
- **Phase E** — JIT awareness: extension opcodes mark a lambda as
|
|
interpret-only.
|
|
|
|
## Per-fire workflow (hard)
|
|
|
|
1. Read `plans/sx-vm-opcode-extension.md` — find the first un-ticked phase.
|
|
2. Implement the phase (only files in `hosts/ocaml/**` and the plan file).
|
|
3. Build via `sx_build target=ocaml`.
|
|
4. Run regression: every existing language-port conformance suite plus
|
|
the OCaml unit tests. The list lives at `lib/<lang>/conformance.sh` —
|
|
13 suites at last count (apl, common-lisp, datalog, erlang, forth, guest,
|
|
haskell, js, lua, ocaml, prolog, smalltalk, tcl).
|
|
5. If green, commit (short factual message — `vm-ext: phase A — dispatch
|
|
fallthrough` style).
|
|
6. Tick the `[ ]` for the completed phase in the plan, append one dated
|
|
line to the Progress log (newest first).
|
|
7. Stop. Wait for the next fire.
|
|
|
|
## Ground rules (hard)
|
|
|
|
- **Scope:** only `hosts/ocaml/**` and `plans/sx-vm-opcode-extension.md`.
|
|
Do **not** edit `lib/<lang>/**`, `spec/**`, `shared/**`, or any other
|
|
language port's tests.
|
|
- **One phase per fire.** Don't combine phases even if a phase looks small.
|
|
The point of the loop is incremental commits.
|
|
- **Commit locally only.** Do **not** push. Do **not** touch `main`.
|
|
- **Worktree:** you are on `loops/sx-vm-extensions` in
|
|
`/root/rose-ash-loops/sx-vm-extensions`.
|
|
- **OCaml SX VM gotchas:**
|
|
- `vm` and `frame` types are defined in `sx_vm.ml`, not `sx_types.ml`.
|
|
Forward refs (like the existing `jit_compile_ref` pattern) are how
|
|
sibling modules avoid circular dependency.
|
|
- Current core opcode ceiling is 175 (OP_DEC). The extension threshold
|
|
is 200, leaving 24 spare slots for future core opcodes.
|
|
- JIT compilation is lazy per-lambda. See `project_jit_compilation.md`
|
|
in memory for the cache + sentinel pattern.
|
|
- **SX edits:** `sx-tree` MCP tools only (none expected for this loop, but
|
|
if needed).
|
|
- **OCaml edits:** Edit/Write tools are fine — these aren't `.sx` files.
|
|
|
|
## Done condition
|
|
|
|
Phase E acceptance: all 13 (or however many exist at the time) language-port
|
|
conformance suites pass, OCaml unit tests pass, the test extension from
|
|
Phase D demonstrates end-to-end flow including JIT routing. Loop is
|
|
complete; mark and stop.
|
|
|
|
## After acceptance
|
|
|
|
Hand off to the Erlang loop: `hosts/ocaml/lib/extensions/erlang.ml` becomes
|
|
the first real consumer, written against this mechanism instead of the
|
|
Phase 9b stub dispatcher in `lib/erlang/vm/dispatcher.sx`.
|