Add provide/context/emit!/emitted — render-time dynamic scope
Four new primitives for scoped downward value passing and upward accumulation through the render tree. Specced in .sx, bootstrapped to Python and JS across all adapters (eval, html, sx, dom, async). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,46 @@ def _collect_reset():
|
||||
_collect_buckets = {}
|
||||
|
||||
|
||||
# Render-time dynamic scope stacks (provide/context/emit!)
|
||||
_provide_stacks: dict[str, list[dict]] = {}
|
||||
|
||||
|
||||
def provide_push(name, value=None):
|
||||
"""Push a provider scope with name, value, and empty emitted list."""
|
||||
_provide_stacks.setdefault(name, []).append({"value": value, "emitted": []})
|
||||
|
||||
|
||||
def provide_pop(name):
|
||||
"""Pop the most recent provider scope for name."""
|
||||
if name in _provide_stacks and _provide_stacks[name]:
|
||||
_provide_stacks[name].pop()
|
||||
|
||||
|
||||
def sx_context(name, *default):
|
||||
"""Read value from nearest enclosing provider. Error if no provider and no default."""
|
||||
if name in _provide_stacks and _provide_stacks[name]:
|
||||
return _provide_stacks[name][-1]["value"]
|
||||
if default:
|
||||
return default[0]
|
||||
raise RuntimeError(f"No provider for: {name}")
|
||||
|
||||
|
||||
def sx_emit(name, value):
|
||||
"""Append value to nearest enclosing provider's accumulator. Error if no provider."""
|
||||
if name in _provide_stacks and _provide_stacks[name]:
|
||||
_provide_stacks[name][-1]["emitted"].append(value)
|
||||
else:
|
||||
raise RuntimeError(f"No provider for emit!: {name}")
|
||||
return NIL
|
||||
|
||||
|
||||
def sx_emitted(name):
|
||||
"""Return list of values emitted into nearest matching provider."""
|
||||
if name in _provide_stacks and _provide_stacks[name]:
|
||||
return list(_provide_stacks[name][-1]["emitted"])
|
||||
return []
|
||||
|
||||
|
||||
def sx_truthy(x):
|
||||
"""SX truthiness: everything is truthy except False, None, and NIL."""
|
||||
if x is False:
|
||||
@@ -942,6 +982,12 @@ PRIMITIVES["spread-attrs"] = spread_attrs
|
||||
PRIMITIVES["collect!"] = sx_collect
|
||||
PRIMITIVES["collected"] = sx_collected
|
||||
PRIMITIVES["clear-collected!"] = sx_clear_collected
|
||||
# provide/context/emit! — render-time dynamic scope
|
||||
PRIMITIVES["provide-push!"] = provide_push
|
||||
PRIMITIVES["provide-pop!"] = provide_pop
|
||||
PRIMITIVES["context"] = sx_context
|
||||
PRIMITIVES["emit!"] = sx_emit
|
||||
PRIMITIVES["emitted"] = sx_emitted
|
||||
''',
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user