miden_assembly/ast/procedure/
resolver.rsuse alloc::{collections::BTreeMap, vec::Vec};
use super::{ProcedureIndex, ProcedureName, QualifiedProcedureName};
use crate::{ast::Ident, LibraryPath, RpoDigest, SourceSpan, Span, Spanned};
#[derive(Debug, Clone)]
pub enum ResolvedProcedure {
Local(Span<ProcedureIndex>),
External(QualifiedProcedureName),
MastRoot(RpoDigest),
}
impl Spanned for ResolvedProcedure {
fn span(&self) -> SourceSpan {
match self {
ResolvedProcedure::Local(p) => p.span(),
ResolvedProcedure::External(p) => p.span(),
ResolvedProcedure::MastRoot(_) => SourceSpan::default(),
}
}
}
pub struct LocalNameResolver {
imports: BTreeMap<Ident, Span<LibraryPath>>,
resolved: BTreeMap<ProcedureName, ProcedureIndex>,
resolutions: Vec<ResolvedProcedure>,
}
impl LocalNameResolver {
pub fn resolve(&self, name: &ProcedureName) -> Option<ResolvedProcedure> {
self.resolved
.get(name)
.copied()
.map(|index| self.resolutions[index.as_usize()].clone())
}
pub fn resolve_import(&self, name: &Ident) -> Option<Span<&LibraryPath>> {
self.imports.get(name).map(|spanned| spanned.as_ref())
}
pub fn get_name(&self, index: ProcedureIndex) -> &ProcedureName {
self.resolved
.iter()
.find_map(|(k, v)| if v == &index { Some(k) } else { None })
.expect("invalid procedure index")
}
pub fn with_imports<I>(mut self, imports: I) -> Self
where
I: IntoIterator<Item = (Ident, Span<LibraryPath>)>,
{
self.imports.extend(imports);
self
}
}
impl FromIterator<(ProcedureName, ResolvedProcedure)> for LocalNameResolver {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = (ProcedureName, ResolvedProcedure)>,
{
let mut resolver = Self {
imports: Default::default(),
resolved: Default::default(),
resolutions: Default::default(),
};
for (name, resolution) in iter {
let index = ProcedureIndex::new(resolver.resolutions.len());
resolver.resolutions.push(resolution);
resolver.resolved.insert(name, index);
}
resolver
}
}