VM global_env sync + isomorphic nav store primitives

Reverse hook syncs VM GLOBAL_SET mutations back to global_env so CEK reads
see JIT-written values. Isomorphic nav: store primitives, event-bridge,
client? predicate. Browser JS and bytecode rebuilt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 15:20:12 +00:00
parent 153f02c672
commit 90918fb2b1
10 changed files with 47 additions and 447 deletions

View File

@@ -223,6 +223,13 @@ let () =
if env == global_env then
Hashtbl.replace _vm_globals name v)
(* Reverse hook: sync VM GLOBAL_SET mutations back to global_env.
Without this, set! inside JIT-compiled functions writes to _vm_globals
but leaves global_env stale — CEK reads then see the old value. *)
let () =
Sx_types._vm_global_set_hook := Some (fun name v ->
Hashtbl.replace global_env.bindings (Sx_types.intern name) v)
(* ================================================================== *)
(* Core API *)
(* ================================================================== *)

File diff suppressed because one or more lines are too long

View File

@@ -50,7 +50,12 @@ let sx_call f args =
Thunk (l.l_body, local)
| Continuation (k, _) ->
k (match args with x :: _ -> x | [] -> Nil)
| _ -> raise (Eval_error ("Not callable: " ^ inspect f))
| _ ->
let nargs = List.length args in
let args_preview = if nargs = 0 then "" else
let s = String.concat ", " (List.map (fun a -> let s = inspect a in if String.length s > 40 then String.sub s 0 40 ^ ".." else s) args) in
" with args=[" ^ s ^ "]" in
raise (Eval_error ("Not callable: " ^ inspect f ^ args_preview))
(* Initialize forward ref so primitives can call SX functions *)
let () = Sx_primitives._sx_call_fn := sx_call

View File

@@ -185,8 +185,18 @@ let make_env () =
let env_extend parent =
{ bindings = Hashtbl.create 16; parent = Some parent }
(* Optional hook: called after every env_bind with (env, name, value).
Used by browser kernel to sync VM globals table. *)
let _env_bind_hook : (env -> string -> value -> unit) option ref = ref None
(* Optional hook: called after VM GLOBAL_SET writes to vm.globals.
Used by browser kernel to sync mutations back to global_env. *)
let _vm_global_set_hook : (string -> value -> unit) option ref = ref None
let env_bind env name v =
Hashtbl.replace env.bindings (intern name) v; Nil
Hashtbl.replace env.bindings (intern name) v;
(match !_env_bind_hook with Some f -> f env name v | None -> ());
Nil
(* Internal: scope-chain lookup with pre-interned ID *)
let rec env_has_id env id =

View File

@@ -303,7 +303,11 @@ and run vm =
in find_env env
| None -> false
in
if not written then Hashtbl.replace vm.globals name (peek vm)
if not written then begin
let v = peek vm in
Hashtbl.replace vm.globals name v;
(match !Sx_types._vm_global_set_hook with Some f -> f name v | None -> ())
end
(* ---- Control flow ---- *)
| 32 (* OP_JUMP *) ->