VM spec in SX + 72 tests passing on both JS and OCaml

spec/vm.sx — bytecode VM written in SX (the spec):
  - Stack-based interpreter for bytecode from compiler.sx
  - 24 opcodes: constants, variables (local/upvalue/global), control flow,
    function calls (with TCO), closures with upvalue capture, collections,
    string concat, define
  - Upvalue cells for shared mutable closure variables
  - Call dispatch: vm-closure (fast path), native-fn, CEK fallback
  - Platform interface: 7 primitives (vm-stack-*, call-primitive, cek-call,
    get-primitive, env-parent)

spec/tests/test-vm.sx — 72 tests exercising compile→bytecode→VM pipeline:
  constants, arithmetic, comparison, control flow (if/when/cond/case/and/or),
  let bindings, lambda, closures, upvalue mutation, TCO (10K iterations),
  collections, strings, define, letrec, quasiquote, threading, integration
  (fibonacci, recursive map/filter/reduce, compose)

spec/compiler.sx — fix :else keyword detection in case/cond compilation
  (was comparing Keyword object to evaluated string, now checks type)

Platform primitives added (JS + OCaml):
  make-vm-stack, vm-stack-get, vm-stack-set!, vm-stack-length, vm-stack-copy!,
  primitive?, get-primitive, call-primitive, set-nth! (JS)

Test runners updated to load bytecode.sx + compiler.sx + vm.sx for --full.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 01:20:00 +00:00
parent 5270d2e956
commit 23c8b97cb1
8 changed files with 1169 additions and 7 deletions

View File

@@ -558,7 +558,8 @@
(let ((test (first args))
(body (nth args 1))
(rest-clauses (if (> (len args) 2) (slice args 2) (list))))
(if (or (= test :else) (= test true))
(if (or (and (= (type-of test) "keyword") (= (keyword-name test) "else"))
(= test true))
;; else clause — just compile the body
(compile-expr em body scope tail?)
(do
@@ -590,7 +591,8 @@
(let ((test (first clauses))
(body (nth clauses 1))
(rest-clauses (if (> (len clauses) 2) (slice clauses 2) (list))))
(if (or (= test :else) (= test true))
(if (or (and (= (type-of test) "keyword") (= (keyword-name test) "else"))
(= test true))
(do (emit-op em 5) ;; POP match-val
(compile-expr em body scope tail?))
(do