From 7a4a6c8a85d9cc931a7aa570794d971d3975335b Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 30 Mar 2026 09:14:09 +0000 Subject: [PATCH] Fix WASM stack overflow: make cek_run iterative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CEK evaluator's cek_run was recursive (calls itself via cek_step). Native OCaml handles deep recursion but wasm_of_ocaml compiles to JS which has ~10K frame stack limit. Complex expressions (bytecode compiler) exceeded this, causing "Maximum call stack size exceeded" in all WASM bytecode compilation. Replace recursive cek_run with iterative while loop — same semantics, zero stack growth. Fixes sx_build_bytecode and browser-side evaluation. Co-Authored-By: Claude Opus 4.6 (1M context) --- hosts/ocaml/lib/sx_ref.ml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hosts/ocaml/lib/sx_ref.ml b/hosts/ocaml/lib/sx_ref.ml index aedf1284..b187a008 100644 --- a/hosts/ocaml/lib/sx_ref.ml +++ b/hosts/ocaml/lib/sx_ref.ml @@ -374,11 +374,16 @@ and expand_macro mac raw_args env = (* cek-run *) and cek_run state = - (if sx_truthy ((cek_terminal_p (state))) then (cek_value (state)) else - try cek_run ((cek_step (state))) - with Eval_error msg -> - (if !_last_error_kont = Nil then _last_error_kont := cek_kont state); - raise (Eval_error msg)) + (* Iterative loop — no stack growth. Essential for WASM where JS stack is limited. *) + let s = ref state in + (try + while not (match cek_terminal_p !s with Bool true -> true | _ -> false) do + s := cek_step !s + done; + cek_value !s + with Eval_error msg -> + (if !_last_error_kont = Nil then _last_error_kont := cek_kont !s); + raise (Eval_error msg)) (* cek-step *) and cek_step state =