Unify scoped effects: scope as general primitive, provide as sugar
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 12m54s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 12m54s
- Add `scope` special form to eval.sx: (scope name body...) or (scope name :value v body...) — general dynamic scope primitive - `provide` becomes sugar: (provide name value body...) calls scope - Rename provide-push!/provide-pop! to scope-push!/scope-pop! throughout all adapters (async, dom, html, sx) and platform implementations - Update boundary.sx: Tier 5 now "Scoped effects" with scope-push!/ scope-pop! as primary, provide-push!/provide-pop! as aliases - Add scope form handling to async adapter and aser wire format - Update sx-browser.js, sx_ref.py (bootstrapped output) - Add scopes.sx docs page, update provide/spreads/demo docs - Update nav-data, page-functions, docs page definitions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -162,6 +162,7 @@
|
||||
(= name "reset") (sf-reset args env)
|
||||
(= name "shift") (sf-shift args env)
|
||||
(= name "dynamic-wind") (sf-dynamic-wind args env)
|
||||
(= name "scope") (sf-scope args env)
|
||||
(= name "provide") (sf-provide args env)
|
||||
|
||||
;; Higher-order forms
|
||||
@@ -951,11 +952,35 @@
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 6a2. provide — render-time dynamic scope
|
||||
;; 6a2. scope — unified render-time dynamic scope primitive
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; (provide name value body...) — push a named scope with value and empty
|
||||
;; accumulator, evaluate body, pop scope. Returns last body result.
|
||||
;; (scope name body...) or (scope name :value v body...)
|
||||
;; Push a named scope with optional value and empty accumulator,
|
||||
;; evaluate body, pop scope. Returns last body result.
|
||||
;;
|
||||
;; `provide` is sugar: (provide name value body...) = (scope name :value value body...)
|
||||
|
||||
(define sf-scope
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(rest (slice args 1))
|
||||
(val nil)
|
||||
(body-exprs nil))
|
||||
;; Check for :value keyword
|
||||
(if (and (>= (len rest) 2) (= (type-of (first rest)) "keyword") (= (keyword-name (first rest)) "value"))
|
||||
(do (set! val (trampoline (eval-expr (nth rest 1) env)))
|
||||
(set! body-exprs (slice rest 2)))
|
||||
(set! body-exprs rest))
|
||||
(scope-push! name val)
|
||||
(let ((result nil))
|
||||
(for-each (fn (e) (set! result (trampoline (eval-expr e env)))) body-exprs)
|
||||
(scope-pop! name)
|
||||
result))))
|
||||
|
||||
|
||||
;; provide — sugar for scope with a value
|
||||
;; (provide name value body...) → (scope name :value value body...)
|
||||
|
||||
(define sf-provide
|
||||
(fn ((args :as list) (env :as dict))
|
||||
@@ -963,9 +988,9 @@
|
||||
(val (trampoline (eval-expr (nth args 1) env)))
|
||||
(body-exprs (slice args 2))
|
||||
(result nil))
|
||||
(provide-push! name val)
|
||||
(scope-push! name val)
|
||||
(for-each (fn (e) (set! result (trampoline (eval-expr e env)))) body-exprs)
|
||||
(provide-pop! name)
|
||||
(scope-pop! name)
|
||||
result)))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user