Wrap a catalog declaration. Called only by the registry — obtain scopes via expressionScopes, never by constructing one.
The scope's stable id.
The catalog declaration.
The data field(s) this scope applies to (for generated documentation).
Short human name for this scope.
The declared identifier names, in declaration order.
Whether undeclared identifiers are permitted. true only for genuinely
dynamic contexts, where the declared bindings serve as documentation and
autocomplete rather than as a gate.
What the expression is expected to evaluate to.
Where the expression is authored (for generated documentation).
One sentence on when this scope applies.
Check a call site's evaluation context against this declaration and
return it, ready to hand to evaluate().
This guards the direction construction-time validation cannot: a call
site that quietly stops binding something the scope promises (or invents
a key the scope never declared) would otherwise leave every expression
using that identifier silently reading undefined. A mismatch is logged
once per distinct shape and the context is passed through unchanged —
a binding bug must not take the sheet down with it.
An open scope accepts any keys and is passed straight through.
The bindings the call site is supplying.
context, unchanged.
Whether an identifier is declared by this scope. Note this asks about the
declaration, not about a runtime context — a declared binding may still
evaluate to undefined (an unresolved item's itemLogic, say), which is
an absent value, not an out-of-scope identifier.
The identifier to look up.
Whether the identifier is declared.
The set of identifiers a sohl.entity.expr.SafeExpression may use at one call site — SoHL's answer to "what is actually in scope here?".
Before scopes existed, every call site built an ad-hoc object literal and handed it to
evaluate(); nothing connected the identifiers an author could write to the identifiers that site actually bound, so an out-of-scope name (sayactorLogicwhere onlyitemLogicis bound) parsed cleanly, threw at evaluation, was caught by the caller, and silently disabled the feature. A scope makes that contract a declared, checkable object:Scopes are declared in
expression-scopes.mjsand reached through the expressionScopes registry; they are never constructed ad hoc.See
expressionScopes — the registry of every declared scope.