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:
@@ -1476,19 +1476,29 @@
|
||||
(make-provide-frame name val (rest body) env)
|
||||
kont)))))))
|
||||
|
||||
;; context: walk kont for nearest ProvideFrame with matching name
|
||||
;; context: check hashtable scope stacks first (set by aser's scope-push!),
|
||||
;; then walk kont for nearest ProvideFrame with matching name.
|
||||
;; The hashtable check is needed because aser renders scopes via scope-push!/pop!
|
||||
;; but inner eval-expr calls (e.g. inside (str ...)) use the CEK continuation.
|
||||
(define step-sf-context
|
||||
(fn (args env kont)
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(default-val (if (>= (len args) 2)
|
||||
(trampoline (eval-expr (nth args 1) env))
|
||||
nil))
|
||||
(frame (kont-find-provide kont name)))
|
||||
(if frame
|
||||
(make-cek-value (get frame "value") env kont)
|
||||
(if (>= (len args) 2)
|
||||
(make-cek-value default-val env kont)
|
||||
(error (str "No provider for: " name)))))))
|
||||
nil)))
|
||||
;; Check hashtable scope stacks first (aser rendering path)
|
||||
(let ((stack-val (if (primitive? "scope-peek")
|
||||
((get-primitive "scope-peek") name)
|
||||
nil)))
|
||||
(if (not (nil? stack-val))
|
||||
(make-cek-value stack-val env kont)
|
||||
;; Fall back to continuation-based lookup
|
||||
(let ((frame (kont-find-provide kont name)))
|
||||
(if frame
|
||||
(make-cek-value (get frame "value") env kont)
|
||||
(if (>= (len args) 2)
|
||||
(make-cek-value default-val env kont)
|
||||
(error (str "No provider for: " name))))))))))
|
||||
|
||||
;; emit!: walk kont for nearest ScopeAccFrame, append value
|
||||
(define step-sf-emit
|
||||
|
||||
Reference in New Issue
Block a user