erlang: Phase 9e — OP_SPAWN / OP_SEND + VM-process registry (+16 vm tests)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"language": "erlang",
|
||||
"total_pass": 675,
|
||||
"total": 675,
|
||||
"total_pass": 691,
|
||||
"total": 691,
|
||||
"suites": [
|
||||
{"name":"tokenize","pass":62,"total":62,"status":"ok"},
|
||||
{"name":"parse","pass":52,"total":52,"status":"ok"},
|
||||
@@ -13,6 +13,6 @@
|
||||
{"name":"echo","pass":7,"total":7,"status":"ok"},
|
||||
{"name":"fib","pass":8,"total":8,"status":"ok"},
|
||||
{"name":"ffi","pass":14,"total":14,"status":"ok"},
|
||||
{"name":"vm","pass":38,"total":38,"status":"ok"}
|
||||
{"name":"vm","pass":54,"total":54,"status":"ok"}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Erlang-on-SX Scoreboard
|
||||
|
||||
**Total: 675 / 675 tests passing**
|
||||
**Total: 691 / 691 tests passing**
|
||||
|
||||
| | Suite | Pass | Total |
|
||||
|---|---|---|---|
|
||||
@@ -14,7 +14,7 @@
|
||||
| ✅ | echo | 7 | 7 |
|
||||
| ✅ | fib | 8 | 8 |
|
||||
| ✅ | ffi | 14 | 14 |
|
||||
| ✅ | vm | 38 | 38 |
|
||||
| ✅ | vm | 54 | 54 |
|
||||
|
||||
|
||||
Generated by `lib/erlang/conformance.sh`.
|
||||
|
||||
@@ -251,4 +251,57 @@
|
||||
(er-vm-test "scan binds first match's var"
|
||||
(get er-vm-r4-env "X") 1)
|
||||
|
||||
|
||||
;; ── Phase 9e — OP_SPAWN / OP_SEND ───────────────────────────────
|
||||
(er-vm-procs-reset!)
|
||||
|
||||
(er-vm-test "spawn opcode by id"
|
||||
(get (er-vm-lookup-opcode-by-id 134) :name) "OP_SPAWN")
|
||||
(er-vm-test "send opcode by id"
|
||||
(get (er-vm-lookup-opcode-by-id 135) :name) "OP_SEND")
|
||||
|
||||
(define er-vm-fn (fn () "body"))
|
||||
(define er-vm-p1 (er-vm-dispatch 134 (list er-vm-fn (list))))
|
||||
(define er-vm-p2 (er-vm-dispatch 134 (list er-vm-fn (list "arg"))))
|
||||
(er-vm-test "spawn returns pid 0 first"
|
||||
er-vm-p1 0)
|
||||
(er-vm-test "spawn returns pid 1 second"
|
||||
er-vm-p2 1)
|
||||
(er-vm-test "proc count is 2"
|
||||
(er-vm-proc-count) 2)
|
||||
(er-vm-test "spawned proc state runnable"
|
||||
(er-vm-proc-state er-vm-p1) "runnable")
|
||||
(er-vm-test "spawned proc mailbox empty"
|
||||
(len (er-vm-proc-mailbox er-vm-p1)) 0)
|
||||
(er-vm-test "spawned proc has 8 registers"
|
||||
(len (get (er-vm-proc-get er-vm-p1) :registers)) 8)
|
||||
|
||||
;; OP_SEND appends to target's mailbox, preserves arrival order.
|
||||
(er-vm-test "send returns true on valid pid"
|
||||
(er-vm-dispatch 135 (list er-vm-p1 "msg1")) true)
|
||||
(er-vm-dispatch 135 (list er-vm-p1 "msg2")
|
||||
)
|
||||
(er-vm-dispatch 135 (list er-vm-p1 "msg3"))
|
||||
(er-vm-test "mailbox length after 3 sends"
|
||||
(len (er-vm-proc-mailbox er-vm-p1)) 3)
|
||||
(er-vm-test "mailbox preserves order — first"
|
||||
(nth (er-vm-proc-mailbox er-vm-p1) 0) "msg1")
|
||||
(er-vm-test "mailbox preserves order — last"
|
||||
(nth (er-vm-proc-mailbox er-vm-p1) 2) "msg3")
|
||||
|
||||
;; send to nonexistent pid returns false (doesn't crash)
|
||||
(er-vm-test "send to unknown pid is false"
|
||||
(er-vm-dispatch 135 (list 99999 "x")) false)
|
||||
|
||||
;; Isolation: msgs to p1 don't appear in p2's mailbox
|
||||
(er-vm-test "isolation — p2 mailbox empty"
|
||||
(len (er-vm-proc-mailbox er-vm-p2)) 0)
|
||||
|
||||
;; reset clears
|
||||
(er-vm-procs-reset!)
|
||||
(er-vm-test "reset clears procs"
|
||||
(er-vm-proc-count) 0)
|
||||
(er-vm-test "reset resets pid counter"
|
||||
(er-vm-dispatch 134 (list er-vm-fn (list))) 0)
|
||||
|
||||
(define er-vm-test-summary (str "vm " er-vm-test-pass "/" er-vm-test-count))
|
||||
|
||||
@@ -161,6 +161,63 @@
|
||||
(fn (operands)
|
||||
(er-vm-receive-scan-loop (nth operands 0) (nth operands 1) (nth operands 2) 0)))
|
||||
|
||||
;; ── Phase 9e — spawn / send + lightweight scheduler ─────────────
|
||||
;; Stub register-machine process layout for the eventual fast scheduler.
|
||||
;; A VM-process is `{:id :registers :mailbox :state :initial-fn :initial-args}`.
|
||||
;; Registers is a vector (SX list, mutated via set-nth!) — fixed slot count
|
||||
;; per process so cells don't grow during execution. Mailbox is an SX list.
|
||||
;; State is one of "runnable" / "waiting" / "dead". This sits PARALLEL to
|
||||
;; the existing `er-scheduler` (which is the language-level scheduler) —
|
||||
;; the VM scheduler will eventually take over once 9a integrates and
|
||||
;; bytecode-compiled Erlang runs against it.
|
||||
|
||||
(define er-vm-procs (list {}))
|
||||
(define er-vm-procs-get (fn () (nth er-vm-procs 0)))
|
||||
(define er-vm-procs-reset!
|
||||
(fn () (do (set-nth! er-vm-procs 0 {}) (set-nth! er-vm-next-pid 0 0))))
|
||||
|
||||
(define er-vm-next-pid (list 0))
|
||||
|
||||
(define er-vm-proc-new!
|
||||
(fn (initial-fn initial-args)
|
||||
(let ((pid (nth er-vm-next-pid 0)))
|
||||
(set-nth! er-vm-next-pid 0 (+ pid 1))
|
||||
(let ((proc
|
||||
{:id pid
|
||||
:registers (list nil nil nil nil nil nil nil nil)
|
||||
:mailbox (list)
|
||||
:state "runnable"
|
||||
:initial-fn initial-fn
|
||||
:initial-args initial-args}))
|
||||
(dict-set! (er-vm-procs-get) (str pid) proc)
|
||||
pid))))
|
||||
|
||||
(define er-vm-proc-get (fn (pid) (get (er-vm-procs-get) (str pid))))
|
||||
|
||||
(define er-vm-proc-send!
|
||||
(fn (pid msg)
|
||||
(let ((proc (er-vm-proc-get pid)))
|
||||
(cond
|
||||
(= proc nil) false
|
||||
:else
|
||||
(do
|
||||
(dict-set! proc :mailbox (append (get proc :mailbox) (list msg)))
|
||||
(when (= (get proc :state) "waiting")
|
||||
(dict-set! proc :state "runnable"))
|
||||
true)))))
|
||||
|
||||
(define er-vm-proc-mailbox (fn (pid) (get (er-vm-proc-get pid) :mailbox)))
|
||||
(define er-vm-proc-state (fn (pid) (get (er-vm-proc-get pid) :state)))
|
||||
(define er-vm-proc-count (fn () (len (keys (er-vm-procs-get)))))
|
||||
|
||||
(define er-vm-op-spawn
|
||||
(fn (operands)
|
||||
(er-vm-proc-new! (nth operands 0) (nth operands 1))))
|
||||
|
||||
(define er-vm-op-send
|
||||
(fn (operands)
|
||||
(er-vm-proc-send! (nth operands 0) (nth operands 1))))
|
||||
|
||||
;; ── 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
|
||||
@@ -202,6 +259,8 @@
|
||||
(er-vm-register-opcode! 131 "OP_PERFORM" er-vm-op-perform)
|
||||
(er-vm-register-opcode! 132 "OP_HANDLE" er-vm-op-handle)
|
||||
(er-vm-register-opcode! 133 "OP_RECEIVE_SCAN" er-vm-op-receive-scan)
|
||||
(er-vm-register-opcode! 134 "OP_SPAWN" er-vm-op-spawn)
|
||||
(er-vm-register-opcode! 135 "OP_SEND" er-vm-op-send)
|
||||
(er-mk-atom "ok")))
|
||||
|
||||
(er-vm-register-erlang-opcodes!)
|
||||
|
||||
Reference in New Issue
Block a user