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

@@ -637,12 +637,24 @@ let run_spec_tests env test_files =
Printf.printf "\nLoading test framework...\n%!";
load_and_eval framework_path;
(* Load compiler + VM spec for test-vm.sx *)
let spec_dir = Filename.concat project_dir "spec" in
List.iter (fun name ->
let path = Filename.concat spec_dir name in
if Sys.file_exists path then begin
Printf.printf "Loading %s...\n%!" name;
(try load_and_eval path
with e -> Printf.eprintf "Warning: %s: %s\n%!" name (Printexc.to_string e))
end
) ["bytecode.sx"; "compiler.sx"; "vm.sx"];
(* Determine test files *)
let files = if test_files = [] then begin
let entries = Sys.readdir spec_tests_dir in
Array.sort String.compare entries;
let requires_full = ["test-continuations.sx"; "test-types.sx"; "test-freeze.sx";
"test-continuations-advanced.sx"; "test-signals-advanced.sx"] in
"test-continuations-advanced.sx"; "test-signals-advanced.sx";
"test-vm.sx"] in
Array.to_list entries
|> List.filter (fun f ->
String.length f > 5 &&