Data.Scope
Lexical scope resolution over branded names: a spelling-to-binder stack.
While resolving syntax, a scope maps each source spelling to the stack of Data.Name binders currently in force for it. Entering a binding pushes; leaving pops; a reference resolves to the innermost binder. Shadowing is a push that changes what the spelling means without disturbing the identity underneath, so alpha-renaming a source program never changes which identities the resolved output carries, only their hints.
Failure is explicit and named: resolving an unknown spelling and popping a spelling with no active binder are ScopeError values, never silent fallbacks. The scope is an ordinary persistent value, so a resolver may thread it through State, pass it as an argument, or keep sub-scopes by simply keeping the old value. Opt-in: not in Base.
Types
Scope
type Scope(space) = Scope { spellings: Map(String, List(Binder(space))) }
A resolution scope for one namespace: each spelling maps to its stack of active binders, innermost first.
ScopeError
type ScopeError
= ScopeUnknown(String)
| ScopeUnderflow(String)
deriving (Eq, Show)
Why a scope operation refused.
Functions and Values
scope_empty
scope_empty : forall a. Data.Scope.Scope(a)
The empty scope: no spelling resolves.
scope_push
scope_push : forall a. (Data.Scope.Scope(a), Data.Name.Binder(a)) -> Data.Scope.Scope(a)
Bring binder into force for its own hint spelling, shadowing any binder already in force for it.
scope_lookup
scope_lookup : forall a. (Data.Scope.Scope(a), String) -> Result(Data.Name.Binder(a), Data.Scope.ScopeError)
The innermost binder in force for spelling, or ScopeUnknown.
scope_pop
scope_pop : forall a. (Data.Scope.Scope(a), String) -> Result(Data.Scope.Scope(a), Data.Scope.ScopeError)
Leave the innermost binding for spelling, restoring whatever it shadowed; popping a spelling with no active binder is ScopeUnderflow.
scope_depth
scope_depth : forall a. (Data.Scope.Scope(a), String) -> Int
How many binders are in force for spelling; zero for an unknown one.