Unify CALL_PRIM dispatch: vm_globals as single source of truth
Seed all primitives into vm_globals as NativeFn values at init. CALL_PRIM now looks up vm.globals only (not the separate primitives table). This means OP_DEFINE and registerNative naturally override primitives — browser.sx's (define set-cookie ...) now takes effect. The primitives Hashtbl remains for the compiler's primitive? predicate but has no runtime dispatch role. Tests: 2435 pass / 64 fail (pre-existing), vs 1718/771 baseline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -680,6 +680,14 @@ let () =
|
|||||||
if env.parent = None then
|
if env.parent = None then
|
||||||
Hashtbl.replace _shared_vm_globals name v)
|
Hashtbl.replace _shared_vm_globals name v)
|
||||||
|
|
||||||
|
(* Seed _shared_vm_globals with all primitives as NativeFn values.
|
||||||
|
Makes vm_globals the single source of truth for CALL_PRIM dispatch. *)
|
||||||
|
let () =
|
||||||
|
Hashtbl.iter (fun name fn ->
|
||||||
|
if not (Hashtbl.mem _shared_vm_globals name) then
|
||||||
|
Hashtbl.replace _shared_vm_globals name (NativeFn (name, fn))
|
||||||
|
) Sx_primitives.primitives
|
||||||
|
|
||||||
let make_server_env () =
|
let make_server_env () =
|
||||||
let env = make_env () in
|
let env = make_env () in
|
||||||
Sx_render.setup_render_env env;
|
Sx_render.setup_render_env env;
|
||||||
|
|||||||
@@ -857,6 +857,15 @@ let () =
|
|||||||
|
|
||||||
let () = ignore (env_bind global_env "enable-jit!" (NativeFn ("enable-jit!", fun _ -> _jit_enabled := true; Nil)))
|
let () = ignore (env_bind global_env "enable-jit!" (NativeFn ("enable-jit!", fun _ -> _jit_enabled := true; Nil)))
|
||||||
|
|
||||||
|
(* Seed _vm_globals with all primitives as NativeFn values.
|
||||||
|
This makes _vm_globals the single source of truth for CALL_PRIM dispatch.
|
||||||
|
OP_DEFINE and registerNative naturally override entries here. *)
|
||||||
|
let () =
|
||||||
|
Hashtbl.iter (fun name fn ->
|
||||||
|
if not (Hashtbl.mem _vm_globals name) then
|
||||||
|
Hashtbl.replace _vm_globals name (NativeFn (name, fn))
|
||||||
|
) Sx_primitives.primitives
|
||||||
|
|
||||||
(* ================================================================== *)
|
(* ================================================================== *)
|
||||||
(* Register global SxKernel object *)
|
(* Register global SxKernel object *)
|
||||||
(* ================================================================== *)
|
(* ================================================================== *)
|
||||||
|
|||||||
@@ -387,11 +387,10 @@ and run vm =
|
|||||||
| _ -> v) args in
|
| _ -> v) args in
|
||||||
let result =
|
let result =
|
||||||
try
|
try
|
||||||
(* Check primitives FIRST (native implementations of map/filter/etc.),
|
(* Single lookup: vm.globals is the sole source of truth.
|
||||||
then globals (which may have ho_via_cek wrappers that route
|
Primitives are seeded into vm.globals at init as NativeFn values.
|
||||||
through the CEK — these can't call VM closures). *)
|
OP_DEFINE and registerNative naturally override them. *)
|
||||||
let fn_val = try Sx_primitives.get_primitive name with _ ->
|
let fn_val = try Hashtbl.find vm.globals name with Not_found ->
|
||||||
try Hashtbl.find vm.globals name with Not_found ->
|
|
||||||
raise (Eval_error ("VM: unknown primitive " ^ name))
|
raise (Eval_error ("VM: unknown primitive " ^ name))
|
||||||
in
|
in
|
||||||
(match fn_val with
|
(match fn_val with
|
||||||
|
|||||||
Reference in New Issue
Block a user