Fix VM correctness: get nil-safe, scope/context/collect! as primitives

- get primitive returns nil for type mismatches (list+string) instead
  of raising — matches JS/Python behavior, fixes find-nav-match errors
- scope-peek, collect!, collected, clear-collected! registered as real
  primitives in sx_primitives table (not just env bindings) so the CEK
  step-sf-context can find them via get-primitive
- step-sf-context checks scope-peek hashtable BEFORE walking CEK
  continuation — bridges aser's scope-push!/pop! with CEK's context
- context, emit!, emitted added to SPECIAL_FORM_NAMES and handled in
  aser-special (scope operations in aser rendering mode)
- sx-context NativeFn for VM-compiled code paths
- VM execution errors no longer mark functions as permanently failed —
  bytecode is correct, errors are from runtime data
- kbd, samp, var added to HTML_TAGS + sx-browser.js rebuilt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 09:33:18 +00:00
parent a716e3f745
commit 4734d38f3b
7 changed files with 131 additions and 22 deletions

View File

@@ -313,11 +313,11 @@ and vm_call vm f args =
(* Try JIT-compiled path first *)
(match l.l_compiled with
| Some cl when not (is_jit_failed cl) ->
(* Execute cached bytecode; fall back to CEK on VM error *)
(* Execute cached bytecode; fall back to CEK on VM error.
Don't mark as failed — the bytecode is correct, the error
is from runtime data (e.g. type mismatch in get). *)
(try push vm (call_closure cl args vm.globals)
with _ ->
l.l_compiled <- Some jit_failed_sentinel;
push vm (Sx_ref.cek_call f (List args)))
with _ -> push vm (Sx_ref.cek_call f (List args)))
| Some _ ->
(* Previously failed or skipped — use CEK *)
push vm (Sx_ref.cek_call f (List args))