(** {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