Unify scoped effects: scope as general primitive, provide as sugar
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:
2026-03-13 17:30:34 +00:00
parent 6ca46bb295
commit 11fdd1a840
23 changed files with 869 additions and 285 deletions

View File

@@ -67,10 +67,12 @@
(~docs/page :title "Provide / Context / Emit!"
(p :class "text-stone-500 text-sm italic mb-8"
"Render-time dynamic scope. " (code "provide") " creates a named scope with a value "
"and an accumulator. " (code "context") " reads the value downward. "
"Sugar for " (code "scope") " with a value. " (code "provide") " creates a named scope "
"with a value and an accumulator. " (code "context") " reads the value downward. "
(code "emit!") " appends to the accumulator upward. " (code "emitted") " retrieves what was emitted. "
"This is the substrate that spreads, CSSX, and script collection are built on.")
"See "
(a :href "/sx/(geography.(scopes))" :class "text-violet-600 hover:underline" "scopes")
" for the unified primitive.")
;; =====================================================================
;; I. The four primitives
@@ -215,25 +217,26 @@
;; =====================================================================
(~docs/section :title "Platform implementation" :id "platform"
(p "Each platform (Python, JavaScript) must provide five operations. "
"The platform manages per-name stacks — each stack entry has a value and an "
"emitted list.")
(p (code "provide") " is sugar for " (code "scope") ". At the platform level, "
(code "provide-push!") " and " (code "provide-pop!") " are aliases for "
(code "scope-push!") " and " (code "scope-pop!") ". All operations work on a unified "
(code "_scope_stacks") " data structure.")
(~docs/table
:headers (list "Platform primitive" "Purpose")
:rows (list
(list "provide-push!(name, value)" "Push a new scope with value and empty emitted list")
(list "provide-pop!(name)" "Pop the most recent scope")
(list "scope-push!(name, value)" "Push a new scope with value and empty accumulator")
(list "scope-pop!(name)" "Pop the most recent scope")
(list "context(name, ...default)" "Read value from nearest scope (error if missing and no default)")
(list "emit!(name, value)" "Append to nearest scope's emitted list (tolerant: no-op if missing)")
(list "emitted(name)" "Return list of emitted values from nearest scope")))
(list "emit!(name, value)" "Append to nearest scope's accumulator (tolerant: no-op if missing)")
(list "emitted(name)" "Return accumulated values from nearest scope")))
(p (code "provide") " itself is a special form in "
(p (code "provide") " is a special form in "
(a :href "/sx/(language.(spec.(explore.evaluator)))" :class "font-mono text-violet-600 hover:underline text-sm" "eval.sx")
" — it calls " (code "provide-push!") ", evaluates the body, "
"then calls " (code "provide-pop!") ". The five platform primitives are declared in "
(a :href "/sx/(language.(spec.(explore.boundary)))" :class "font-mono text-violet-600 hover:underline text-sm" "boundary.sx")
" (Tier 5: Dynamic scope).")
" — it calls " (code "scope-push!") ", evaluates the body, "
"then calls " (code "scope-pop!") ". See "
(a :href "/sx/(geography.(scopes))" :class "text-violet-600 hover:underline" "scopes")
" for the full unified platform.")
(~docs/note
(p (strong "Spec explorer: ") "See the provide/emit! primitives in "