Transpiler local-ref shadowing fix + foreign test runner bindings

ml-scan-set now checks ml-is-mutable-global? before adding set!/append!
targets to the needs-ref list. Previously, mutable globals like
*bind-tracking* got local `ref Nil` shadows that masked the global _ref,
causing `append!: expected list, got nil` in 43 bind-tracking tests.

Test runner: bind foreign registry functions (foreign-registered?,
foreign-lookup, foreign-names, foreign-register!, foreign-resolve-binding,
foreign-check-args, foreign-build-lambda) + initialize _cek_call_ref for
with-capabilities. 22/24 foreign tests now pass, 8 capabilities tests fixed.

Retranspiled sx_ref.ml — all mutable global shadows eliminated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 18:29:13 +00:00
parent 000f285ae8
commit b61b437ccd
3 changed files with 29 additions and 11 deletions

View File

@@ -628,6 +628,20 @@ let make_test_env () =
bind "io-names" (fun _args -> Sx_ref.io_names ());
bind "io-register!" (fun args -> match args with [String n; spec] -> Sx_ref.io_register_b (String n) spec | _ -> Nil);
(* Foreign registry — spec-level define-foreign populates *foreign-registry*.
Bind accessor functions so test-foreign.sx can inspect the registry. *)
ignore (Sx_types.env_bind env "*foreign-registry*" Sx_ref._foreign_registry_);
bind "foreign-registered?" (fun args -> match args with [String n] -> Sx_ref.foreign_registered_p (String n) | _ -> Bool false);
bind "foreign-lookup" (fun args -> match args with [String n] -> Sx_ref.foreign_lookup (String n) | _ -> Nil);
bind "foreign-names" (fun _args -> Sx_ref.foreign_names ());
bind "foreign-register!" (fun args -> match args with [String n; spec] -> Sx_ref.foreign_register_b (String n) spec | _ -> Nil);
bind "foreign-resolve-binding" (fun args -> match args with [String s] -> Sx_ref.foreign_resolve_binding (String s) | _ -> Nil);
bind "foreign-check-args" (fun args -> match args with [String n; List p; List a] -> Sx_ref.foreign_check_args (String n) (List p) (List a) | _ -> Nil);
bind "foreign-build-lambda" (fun args -> match args with [spec] -> Sx_ref.foreign_build_lambda spec | _ -> Nil);
(* Initialize CEK call forward ref — needed by with-capabilities and foreign-dispatch *)
Sx_types._cek_call_ref := Sx_ref.cek_call;
(* --- Primitives for canonical.sx / content tests --- *)
bind "contains-char?" (fun args ->
match args with

File diff suppressed because one or more lines are too long

View File

@@ -417,11 +417,13 @@
(= (symbol-name head) "set!")
(>= (len node) 2))
(let
((var-name (if (= (type-of (nth node 1)) "symbol") (symbol-name (nth node 1)) (str (nth node 1)))))
((var-name (symbol-name (nth node 1))))
(let
((mangled (ml-mangle var-name)))
(when
(not (some (fn (x) (= x mangled)) result))
(and
(not (ml-is-mutable-global? var-name))
(not (some (fn (x) (= x mangled)) result)))
(append! result mangled))))
(and
(= (type-of head) "symbol")
@@ -433,7 +435,9 @@
(let
((mangled (ml-mangle var-name)))
(when
(not (some (fn (x) (= x mangled)) result))
(and
(not (ml-is-mutable-global? var-name))
(not (some (fn (x) (= x mangled)) result)))
(append! result mangled))))
:else (for-each
(fn (child) (when (list? child) (ml-scan-set child result)))