pub struct ScopeMap<V> { /* private fields */ }Expand description
A map from a name to a value, in a stack of scopes.
A lookup has to find the innermost binding of a name, and a scope closing has to expose whatever that name meant outside it. Walking a stack of scopes would make every lookup cost the depth, and a compiler looks up every identifier it reads, so the shape is inverted: one map from name to the stack of bindings for that name, innermost last, plus a log of the names bound in each open scope so that closing one knows what to undo.
Implementations§
Source§impl<V: Copy> ScopeMap<V>
impl<V: Copy> ScopeMap<V>
Sourcepub fn depth(&self) -> u32
pub fn depth(&self) -> u32
How many scopes are open. The file scope counts, so this is never zero.
Sourcepub fn at_file_scope(&self) -> bool
pub fn at_file_scope(&self) -> bool
Whether the only open scope is the file scope.
Sourcepub fn pop(&mut self)
pub fn pop(&mut self)
Closes the innermost scope, exposing whatever its names meant outside it.
§Panics
Panics on closing the file scope, which nothing in C does and which would leave the namespace unable to hold a declaration.
Sourcepub fn declare(&mut self, name: Symbol, value: V) -> Option<V>
pub fn declare(&mut self, name: Symbol, value: V) -> Option<V>
Binds name in the innermost scope, and gives back what it was already bound to in
that same scope.
A returned value is a redeclaration, which is the caller’s to judge: int x; int x; is
fine at file scope and typedef int T; T T; is not, and neither decision belongs here.
Shadowing an outer binding is not a redeclaration and gives back None.
Sourcepub fn declare_at_file_scope(&mut self, name: Symbol, value: V) -> bool
pub fn declare_at_file_scope(&mut self, name: Symbol, value: V) -> bool
Binds name in the file scope from wherever the caller is, and answers whether it took.
For the declaration a program did not write. A builtin used inside a function is declared where C says the implementation declared it, which is the file scope, so that what it means does not change when the block it was first used in closes.
It takes only when the name is bound nowhere, which is the caller’s own condition: this is reached because a lookup found nothing. A name bound anywhere is left alone rather than bound underneath, because the binding it already has may be the one being closed over and this has no log entry to undo.