pub struct Scope<T: Hash + Eq> { /* private fields */ }Expand description
Utility to implement lookup scopes.
Scope implements the logic needed to support name lookup in a local scope, similar to what may many need in simple programming languages or in logical formalisms. It supports looking up by name elements of any given type and implements Stack to support incremental interfaces, e.g., in SAT or SMT solvers.
A call to lookup() method produces an instance of LookupSet which can be used
to further filter and navigate the objects found by name. LookupSet in turn is in charge of
emitting detailed error diagnostics when a lookup fails, helping to standardize such diagnostics
across all formally and its clients.
Example:
use formally::{support::*, smt::*};
let mut scope = Scope::new();
scope.push();
scope.add("x", Loc::new(42));
println!("x: {}", scope.lookup(Identifier::from("x")).one()?);
scope.pop();
assert!(scope.lookup(Identifier::from("x")).all()?.is_empty());Here the LookupSet::one() method requires a single result to exist and emits detailed diagnostics if this is not the case. See its documentation for details.
The element type needs to implement Hash and Eq. These are used to ensure that if the same element is added twice under the same name, it is treated as a single entry.
Scope objects support being nested under other Scope objects. Nesting simulates how one would implement a nested scope in a typical language, such as the scope under a function definition that sees its arguments locally but the elements declared outside globally. Elements defined in the local Scope shadow the ones defined in the parent, but if no element is defined at all with a given name, lookup is delegated to the parent.
Example:
use formally::{support::*, smt::*};
let mut parent = Scope::new();
parent.add("x", term!(p));
parent.add("x", term!(q));
parent.add("y", term!(and p q));
let mut scope = Scope::new().with_parent(parent);
scope.add("x", term!(=> p q));
scope.lookup("x").one()?;
scope.lookup("y").one()?;Note that the first call to one() succeeds here because the only element
declared in scope with name "x" shadows all the elements with the same name in parent. The
second one succeeds as well because "y" is found in the parent.
Implementations§
Source§impl<T: Hash + Eq> Scope<T>
impl<T: Hash + Eq> Scope<T>
Sourcepub fn with_parent(self, parent: Scope<T>) -> Scope<T>
pub fn with_parent(self, parent: Scope<T>) -> Scope<T>
Construct a new Scope similar to self but nested under a different parent.
Sourcepub fn set_parent(&mut self, parent: Scope<T>)
pub fn set_parent(&mut self, parent: Scope<T>)
Set a new parent to the current Scope.
Sourcepub fn add(&mut self, name: &str, element: T)
pub fn add(&mut self, name: &str, element: T)
Add an element to the Scope under the given name.
pub fn lookup<'i>( &self, name: impl Into<Identifier<'i>>, ) -> LookupSet<'_, 'i, T, &T>
Trait Implementations§
Source§impl<T: Hash + Eq> Default for Scope<T>where
Stacked<HashTrieMapSync<String, HashTrieSetSync<T>>>: Default,
Option<Arc<Scope<T>>>: Default,
impl<T: Hash + Eq> Default for Scope<T>where
Stacked<HashTrieMapSync<String, HashTrieSetSync<T>>>: Default,
Option<Arc<Scope<T>>>: Default,
Auto Trait Implementations§
impl<T> Freeze for Scope<T>
impl<T> RefUnwindSafe for Scope<T>where
Stacked<HashTrieMap<String, HashTrieSet<T, ArcTK>, ArcTK>>: RefUnwindSafe,
Option<Arc<Scope<T>>>: RefUnwindSafe,
impl<T> Send for Scope<T>
impl<T> Sync for Scope<T>
impl<T> Unpin for Scope<T>
impl<T> UnsafeUnpin for Scope<T>where
Stacked<HashTrieMap<String, HashTrieSet<T, ArcTK>, ArcTK>>: UnsafeUnpin,
Option<Arc<Scope<T>>>: UnsafeUnpin,
impl<T> UnwindSafe for Scope<T>where
Stacked<HashTrieMap<String, HashTrieSet<T, ArcTK>, ArcTK>>: UnwindSafe,
Option<Arc<Scope<T>>>: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more