Fix transpiler append! emit for mutable globals + run_with_io error recovery
The transpiler's append! emit path didn't check ml-is-mutable-global?, so (append! *provide-batch-queue* sub) wrote to a dead local variable instead of the global _ref. This caused the combined test suite hang — fire-provide-subscribers was silently broken before the local-ref shadow removal, and now correctly modifies the global batch queue. Also adds run_with_io error-to-raise conversion (kont_has_handler guard) so native Eval_errors can be caught by CEK guard/handler-bind when running through the test runner's IO-aware step loop. 2798/2800 tests pass. 2 foreign-type-checking failures remain: guard can't catch Eval_error from native fns called through cek_run_iterative (the handler dispatch itself uses cek_call which re-enters cek_run_iterative, creating an infinite loop). Fix requires spec-level change: make (error) use CEK raise instead of host-error. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1231,9 +1231,32 @@ let run_spec_tests env test_files =
|
||||
let s = ref state in
|
||||
let is_terminal st = match Sx_ref.cek_terminal_p st with Bool true -> true | _ -> false in
|
||||
let is_suspended st = match Sx_runtime.get_val st (String "phase") with String "io-suspended" -> true | _ -> false in
|
||||
(* Check if kont has any handler frames — pure structural scan *)
|
||||
let kont_has_handler kont =
|
||||
let k = ref kont in
|
||||
let found = ref false in
|
||||
while (match !k with List (_::_) -> true | _ -> false) && not !found do
|
||||
(match !k with
|
||||
| List (frame :: rest) ->
|
||||
(match frame with
|
||||
| CekFrame f when f.cf_type = "handler" -> found := true
|
||||
| _ -> ());
|
||||
k := List rest
|
||||
| _ -> k := List [])
|
||||
done;
|
||||
!found in
|
||||
let rec loop () =
|
||||
while not (is_terminal !s) && not (is_suspended !s) do
|
||||
s := Sx_ref.cek_step !s
|
||||
(try s := Sx_ref.cek_step !s
|
||||
with Eval_error msg ->
|
||||
let kont = Sx_ref.cek_kont !s in
|
||||
if kont_has_handler kont then
|
||||
(* Convert to CEK-level raise so guard/handler-bind can catch it *)
|
||||
let env = Sx_ref.cek_env !s in
|
||||
s := Sx_ref.make_cek_value (String msg) env
|
||||
(Sx_ref.kont_push (Sx_ref.make_raise_eval_frame env (Bool false)) kont)
|
||||
else
|
||||
raise (Eval_error msg))
|
||||
done;
|
||||
if is_suspended !s then begin
|
||||
let request = Sx_runtime.get_val !s (String "request") in
|
||||
|
||||
Reference in New Issue
Block a user