CEK-safe native call boundary: apply-cek + eval-error? marker

Native functions (NativeFn/VmClosure) called through the CEK evaluator
can now have their Eval_errors caught by guard/handler-bind. The fix is
at the exact OCaml↔CEK boundary in continue-with-call:

- sx_runtime.ml: sx_apply_cek wraps native calls, returns error marker
  dict {__eval_error__: true, message: "..."} instead of raising
- sx_runtime.ml: is_eval_error predicate checks for the marker
- spec/evaluator.sx: continue-with-call callable branch uses apply-cek,
  detects error markers, converts to raise-eval CEK state
- transpiler.sx: apply-cek and eval-error? emit cases added

No mutable flags, no re-entry risk. Errors flow through the CEK handler
chain naturally. 2798/2800 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 19:31:00 +00:00
parent 7f772e0f23
commit 1d68f20a37
4 changed files with 46 additions and 2 deletions

View File

@@ -226,6 +226,8 @@
"register-library"
"sx-call"
"sx-apply"
"apply-cek"
"eval-error?"
"collect!"
"collected"
"clear-collected!"
@@ -798,6 +800,18 @@
" "
(ml-expr-inner (nth args 1) set-vars)
")")
(= op "apply-cek")
(str
"(sx_apply_cek "
(ml-expr-inner (first args) set-vars)
" "
(ml-expr-inner (nth args 1) set-vars)
")")
(= op "eval-error?")
(str
"(Bool (is_eval_error "
(ml-expr-inner (first args) set-vars)
"))")
(= op "for-each")
(ml-emit-for-each args set-vars)
(= op "map")