use super::imports::{FileImports, ImportTarget};
use super::index::Index;
use super::universe;
pub(super) enum Outcome {
Found(Box<[usize]>),
External,
Missing,
}
impl Outcome {
fn of(found: Box<[usize]>, absent: Outcome) -> Self {
match found.is_empty() {
true => absent,
false => Self::Found(found),
}
}
}
pub(super) fn bare(index: &Index, scope: (usize, &FileImports<'_>), name: &str) -> Outcome {
let (unit, imports) = scope;
let mut found: Vec<usize> = declared(index, unit, name).to_vec();
for dotted in imports.dotted() {
found.extend(pulled(index, *dotted, name));
}
found.sort_unstable();
found.dedup();
Outcome::of(found.into_boxed_slice(), absent(imports, name))
}
pub(super) fn qualified(index: &Index, target: ImportTarget<'_>, name: &str) -> Outcome {
match target.unit {
None => Outcome::External,
Some(unit) => Outcome::of(Box::from(declared(index, unit, name)), Outcome::Missing),
}
}
pub(super) fn declared<'a>(index: &'a Index, unit: usize, name: &str) -> &'a [usize] {
index
.unit(unit)
.map(|found| found.named(name))
.unwrap_or_default()
}
fn pulled(index: &Index, target: ImportTarget<'_>, name: &str) -> Box<[usize]> {
match target.unit {
None => Box::from([]),
Some(unit) => Box::from(declared(index, unit, name)),
}
}
fn absent(imports: &FileImports<'_>, name: &str) -> Outcome {
let outside = imports.dotted().iter().any(|dotted| dotted.unit.is_none());
match universe::is_predeclared(name) || outside {
true => Outcome::External,
false => Outcome::Missing,
}
}