Fix process-bindings scope loss and async-invoke arity, bootstrap async adapter
Two bugs fixed:
1. process-bindings used merge(env) which returns {} for Env objects
(Env is not a dict subclass). Changed to env-extend in render.sx
and adapter-async.sx. This caused "Undefined symbol: theme" etc.
2. async-aser-eval-call passed evaled-args list to async-invoke(&rest),
double-wrapping it. Changed to inline apply + coroutine check.
Also: bootstrap define-async into sx_ref.py (Phase 6), replace ~1000 LOC
hand-written async_eval_ref.py with 24-line thin re-export shim.
Test runner now uses Env (not flat dict) for render envs to catch scope bugs.
8 new regression tests (4 scope chain, 2 native callable arity, 2 render).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -450,7 +450,9 @@
|
||||
|
||||
(define-async async-process-bindings
|
||||
(fn (bindings env ctx)
|
||||
(let ((local (merge env)))
|
||||
;; env-extend (not merge) — Env is not a dict subclass, so merge()
|
||||
;; returns an empty dict, losing all parent scope bindings.
|
||||
(let ((local (env-extend env)))
|
||||
(if (and (= (type-of bindings) "list") (not (empty? bindings)))
|
||||
(if (= (type-of (first bindings)) "list")
|
||||
;; Scheme-style: ((name val) ...)
|
||||
@@ -669,7 +671,10 @@
|
||||
(evaled-args (async-eval-args args env ctx)))
|
||||
(cond
|
||||
(and (callable? f) (not (lambda? f)) (not (component? f)))
|
||||
(async-invoke f evaled-args)
|
||||
;; apply directly — async-invoke takes &rest so passing a list
|
||||
;; would wrap it in another list
|
||||
(let ((r (apply f evaled-args)))
|
||||
(if (async-coroutine? r) (async-await! r) r))
|
||||
(lambda? f)
|
||||
(let ((local (env-merge (lambda-closure f) env)))
|
||||
(for-each-indexed
|
||||
@@ -1166,19 +1171,20 @@
|
||||
|
||||
(define-async async-eval-slot-inner
|
||||
(fn (expr env ctx)
|
||||
(let ((result
|
||||
(if (and (list? expr) (not (empty? expr)))
|
||||
(let ((head (first expr)))
|
||||
(if (and (= (type-of head) "symbol")
|
||||
(starts-with? (symbol-name head) "~"))
|
||||
(let ((name (symbol-name head))
|
||||
(val (if (env-has? env name) (env-get env name) nil)))
|
||||
(if (component? val)
|
||||
(async-aser-component val (rest expr) env ctx)
|
||||
;; Islands and unknown components — fall through to aser
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx)))
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx)))
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx))))
|
||||
;; NOTE: Uses statement-form let + set! to avoid expression-context
|
||||
;; let (IIFE lambdas) which can't contain await in Python.
|
||||
(let ((result nil))
|
||||
(if (and (list? expr) (not (empty? expr)))
|
||||
(let ((head (first expr)))
|
||||
(if (and (= (type-of head) "symbol")
|
||||
(starts-with? (symbol-name head) "~"))
|
||||
(let ((name (symbol-name head))
|
||||
(val (if (env-has? env name) (env-get env name) nil)))
|
||||
(if (component? val)
|
||||
(set! result (async-aser-component val (rest expr) env ctx))
|
||||
(set! result (async-maybe-expand-result (async-aser expr env ctx) env ctx))))
|
||||
(set! result (async-maybe-expand-result (async-aser expr env ctx) env ctx))))
|
||||
(set! result (async-maybe-expand-result (async-aser expr env ctx) env ctx)))
|
||||
;; Normalize result to SxExpr
|
||||
(if (sx-expr? result)
|
||||
result
|
||||
|
||||
Reference in New Issue
Block a user