vm-ext: phase B — extension registry module
sx_vm_extension.ml: handler type, extensible extension_state variant, EXTENSION first-class module signature. sx_vm_extensions.ml: register / dispatch / id_of_name / state_of_extension. install_dispatch () runs at module init, swapping Phase A's stub for the real registry. Rejects out-of-range opcode IDs (must be 200-247), duplicate IDs, duplicate names, and duplicate extension names. Tests: 9 new foundation cases — lookup hits/misses, end-to-end VM dispatch including opcode composition, all four rejection paths. +9 pass vs Phase A baseline, no regressions across 11 conformance suites.
This commit is contained in:
48
hosts/ocaml/lib/sx_vm_extension.ml
Normal file
48
hosts/ocaml/lib/sx_vm_extension.ml
Normal file
@@ -0,0 +1,48 @@
|
||||
(** {1 VM extension interface}
|
||||
|
||||
Type definitions for VM bytecode extensions. See
|
||||
[plans/sx-vm-opcode-extension.md].
|
||||
|
||||
An extension is a first-class module of type [EXTENSION]: it has a
|
||||
stable [name], an [init] that returns its private state, and an
|
||||
[opcodes] function that lists the opcodes it provides.
|
||||
|
||||
Opcode handlers receive the live [vm] and the active [frame]. They
|
||||
read operands via [Sx_vm.read_u8] / [read_u16], manipulate the stack
|
||||
via [push] / [pop] / [peek], and update the frame's [ip] as needed. *)
|
||||
|
||||
(** A handler for an extension opcode. Reads operands from bytecode,
|
||||
manipulates the VM stack, updates the frame's instruction pointer.
|
||||
May raise exceptions (which propagate via the existing VM error path). *)
|
||||
type handler = Sx_vm.vm -> Sx_vm.frame -> unit
|
||||
|
||||
(** State an extension carries alongside the VM. Opaque to the VM core;
|
||||
extensions extend this with their own constructor and cast as needed.
|
||||
|
||||
Extensible variant — extensions add cases:
|
||||
{[
|
||||
type Sx_vm_extension.extension_state +=
|
||||
| ErlangState of erlang_scheduler
|
||||
]} *)
|
||||
type extension_state = ..
|
||||
|
||||
(** An extension is a first-class module of this signature. *)
|
||||
module type EXTENSION = sig
|
||||
(** Stable name for this extension (e.g. ["erlang"], ["guest_vm"]).
|
||||
Used as the lookup key in the registry and as the prefix for opcode
|
||||
names ([erlang.OP_PATTERN_TUPLE_2] etc). *)
|
||||
val name : string
|
||||
|
||||
(** Initialize per-instance state. Called once when [register] is
|
||||
invoked on this extension. *)
|
||||
val init : unit -> extension_state
|
||||
|
||||
(** Opcodes this extension provides. Each is
|
||||
[(opcode_id, opcode_name, handler)].
|
||||
|
||||
[opcode_id] must be in the range 200-247 (the extension partition;
|
||||
see the partition comment at the top of [Sx_vm]'s dispatch loop).
|
||||
Conflicts with already-registered opcodes cause [register] to
|
||||
fail. *)
|
||||
val opcodes : extension_state -> (int * string * handler) list
|
||||
end
|
||||
Reference in New Issue
Block a user