Wire transpiled VM as active execute_module — 2644 tests pass

The transpiled VM (sx_vm_ref.ml, from lib/vm.sx) is now the ACTIVE
bytecode execution engine. sx_server.ml and sx_browser.ml call
Sx_vm_ref.execute_module instead of Sx_vm.execute_module.

Results:
- OCaml tests: 2644 passed, 0 failed
- WASM tests: 32 passed, 0 failed
- Browser: zero errors, zero warnings, islands hydrate
- Server: pages render, JIT compiles, all routes work

The VM logic now lives in ONE place: lib/vm.sx (SX).
OCaml gets it via transpilation (bootstrap_vm.py).
JS/browser gets it via bytecode compilation (compile-modules.js).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 13:34:11 +00:00
parent 54ee673050
commit e46cdf3d4d
15 changed files with 5278 additions and 2729 deletions

View File

@@ -292,7 +292,7 @@ let api_eval_vm src_js =
| None -> env_get global_env "compile-module" in
let code_val = Sx_ref.trampoline (Sx_runtime.sx_call compile_fn [List exprs]) in
let code = Sx_vm.code_from_value code_val in
let result = Sx_vm.execute_module code _vm_globals in
let result = Sx_vm_ref.execute_module code _vm_globals in
(* Sync VM globals → CEK env so subsequent eval() calls see defines *)
Hashtbl.iter (fun name v ->
let id = intern name in
@@ -380,45 +380,44 @@ let sync_vm_to_env () =
end
) _vm_globals
(** Recursive suspension handler: resumes VM, catches further suspensions,
resolves imports locally when possible, otherwise returns JS suspension
objects that the platform's while loop can process. *)
let rec resume_with_suspensions vm result =
try
let v = Sx_vm.resume_vm vm result in
sync_vm_to_env ();
value_to_js v
with Sx_vm.VmSuspended (request, vm2) ->
handle_suspension request vm2
and handle_suspension request vm =
let op = match request with
| Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | _ -> "")
| _ -> "" in
if op = "import" then
match handle_import_suspension request with
| Some result ->
(* Library already loaded — resume and handle further suspensions *)
resume_with_suspensions vm result
| None ->
(* Library not loaded — return suspension to JS for async fetch *)
Js.Unsafe.inject (make_js_suspension request (fun _result ->
resume_with_suspensions vm Nil))
else
Js.Unsafe.inject (make_js_suspension request (fun result ->
resume_with_suspensions vm result))
let api_load_module module_js =
try
let code_val = js_to_value module_js in
let code = Sx_vm.code_from_value code_val in
let _result = Sx_vm.execute_module code _vm_globals in
let _result = Sx_vm_ref.execute_module code _vm_globals in
sync_vm_to_env ();
Js.Unsafe.inject (Hashtbl.length _vm_globals)
with
| Sx_vm.VmSuspended (request, vm) ->
(* VM hit OP_PERFORM — check if we can resolve locally *)
let op = match request with
| Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | _ -> "")
| _ -> "" in
if op = "import" then
match handle_import_suspension request with
| Some result ->
(* Library already loaded — resume VM and continue *)
(try
let final = Sx_vm.resume_vm vm result in
sync_vm_to_env ();
Js.Unsafe.inject (value_to_js final)
with Sx_vm.VmSuspended (req2, vm2) ->
make_js_suspension req2 (fun result ->
let v = Sx_vm.resume_vm vm2 result in
sync_vm_to_env ();
value_to_js v))
| None ->
(* Library not loaded — return suspension to JS for async fetch *)
make_js_suspension request (fun result ->
ignore result;
(* After JS loads the library file, resume the VM *)
let v = Sx_vm.resume_vm vm Nil in
sync_vm_to_env ();
value_to_js v)
else
make_js_suspension request (fun result ->
let v = Sx_vm.resume_vm vm result in
sync_vm_to_env ();
value_to_js v)
handle_suspension request vm
| Eval_error msg -> Js.Unsafe.inject (Js.string ("Error: " ^ msg))
| exn -> Js.Unsafe.inject (Js.string ("Error: " ^ Printexc.to_string exn))
@@ -629,7 +628,7 @@ let () =
in
let module_val = convert_code code_form in
let code = Sx_vm.code_from_value module_val in
let _result = Sx_vm.execute_module code _vm_globals in
let _result = Sx_vm_ref.execute_module code _vm_globals in
sync_vm_to_env ();
Number (float_of_int (Hashtbl.length _vm_globals))
| _ -> raise (Eval_error "load-sxbc: expected (sxbc version hash (code ...))"));