erlang: Phase 9c — OP_PERFORM / OP_HANDLE stubs (+9 vm tests)

This commit is contained in:
2026-05-14 21:08:12 +00:00
parent 25924d6212
commit 528b24a1cd
5 changed files with 104 additions and 6 deletions

View File

@@ -80,6 +80,44 @@
(error (str "Erlang VM: unknown opcode name '" name "'"))
((get entry :handler) operands)))))
;; ── Phase 9c — effect opcodes (perform / handle) ────────────────
;; Stub algebraic-effects-style operators. OP_PERFORM raises a tagged
;; exception; OP_HANDLE wraps a thunk in `guard` and catches matching
;; effects, passing the args to the handler. The real specialization
;; (constant-time effect dispatch, single-shot vs multi-shot continuations)
;; lands when 9a integrates.
(define er-vm-effect-marker?
(fn (c effect-name)
(and (= (type-of c) "dict")
(= (get c :tag) "vm-effect")
(= (get c :effect) effect-name))))
(define er-vm-op-perform
(fn (operands)
(raise {:tag "vm-effect" :effect (nth operands 0) :args (nth operands 1)})))
(define er-vm-op-handle
(fn (operands)
(let ((thunk (nth operands 0))
(effect-name (nth operands 1))
(handler (nth operands 2))
(result (list nil))
(caught (list false))
(rethrow (list nil)))
(guard
(c
(:else
(cond
(er-vm-effect-marker? c effect-name)
(do (set-nth! caught 0 true)
(set-nth! result 0 (handler (get c :args))))
:else (set-nth! rethrow 0 c))))
(set-nth! result 0 (thunk)))
(cond
(not (= (nth rethrow 0) nil)) (raise (nth rethrow 0))
:else (nth result 0)))))
;; ── Phase 9b — pattern-match opcodes ────────────────────────────
;; Each handler takes a list (pattern-ast value env) and returns
;; true/false, mutating env on success (same contract as the
@@ -118,6 +156,8 @@
(nth operands 0)
(nth operands 1)
(nth operands 2))))
(er-vm-register-opcode! 131 "OP_PERFORM" er-vm-op-perform)
(er-vm-register-opcode! 132 "OP_HANDLE" er-vm-op-handle)
(er-mk-atom "ok")))
(er-vm-register-erlang-opcodes!)