SX VM extensions
Each *.ml file here is a VM extension — a first-class OCaml module that
registers specialized bytecode opcodes with Sx_vm_extensions. See
plans/sx-vm-opcode-extension.md
for the design.
Pattern
(* lib/extensions/myport.ml *)
open Sx_types
type Sx_vm_extension.extension_state += MyportState of { ... }
module M : Sx_vm_extension.EXTENSION = struct
let name = "myport"
let init () = MyportState { ... }
let opcodes _st = [
(id, "myport.OP_NAME", handler);
...
]
end
let register () = Sx_vm_extensions.register (module M)
Then call Myport.register () once at startup from any binary that
should have the extension loaded.
Opcode-ID allocation
Range 200-247 (per Sx_vm_extensions.extension_min /
extension_max). Conventions:
| Range | Use |
|---|---|
| 200-209 | reserved for lib/guest/vm/ shared opcodes (chiselled out on 2nd use) |
| 210-219 | inline test extensions defined in bin/run_tests.ml |
| 220-229 | this directory's test_ext (the canonical template) |
| 230-247 | first-come-first-served by language ports (Erlang first) |
When a port claims a contiguous block, document it in the table above. The registry rejects collisions at startup with a loud error — there is no silent shadowing.
Naming
Always prefix opcode names with the extension name plus a dot:
myport.OP_<NAME>. The prefix is a hard convention so that multiple
extensions can share the global opcode-name namespace cleanly.
State
extension_state is an extensible variant. Add your case (e.g.
MyportState of { ... }) at the top of your file, return it from
init, and pattern-match it inside your handlers. Other extensions
cannot see your state — the variant case is private to your module.
Testing
test_ext.ml is the canonical worked example. bin/run_tests.ml
calls Test_ext.register (), then drives bytecode that exercises the
opcodes end-to-end (push, double, dispatch, disassemble, invocation
counter). Mirror this shape when adding a real port's extension.
Build wiring
lib/dune has (include_subdirs unqualified), so any .ml you drop
in here is automatically part of the sx library. Module name follows
the filename verbatim (test_ext.ml → Test_ext).