use crate::{
containers::{Map, Symbol},
typesys::{Type, Variable},
};
use super::state::TypecheckState;
#[derive(Clone, Debug)]
pub struct TypeFacts<Tv: Variable, Cv: Variable> {
mapping: Map<Symbol, Type<Tv, Cv>>,
}
impl<Tv: Variable, Cv: Variable> TypeFacts<Tv, Cv> {
pub fn empty() -> Self {
Self {
mapping: Map::new(),
}
}
pub fn with_mapping(mut self, sym: Symbol, t: Type<Tv, Cv>) -> Self {
self.mapping.insert(sym, t);
self
}
pub fn clear_mapping(mut self, sym: Symbol) -> Self {
self.mapping.remove(&sym);
self
}
pub fn union(mut self, other: Self) -> Self {
self.mapping = self.mapping.union_with(other.mapping, |a, b| {
if a.subtype_of(&b) {
a
} else if b.subtype_of(&a) {
b
} else {
Type::Nothing
}
});
self
}
pub fn negate_against(mut self, universe: &TypecheckState<Tv, Cv>) -> Self {
let _pre = self.clone();
self.mapping.iter_mut().for_each(|(k, b)| {
if let Some(u) = universe.lookup_var(*k) {
let new = u.subtract(b).into_owned();
*b = new;
}
});
self
}
pub fn iter(&self) -> impl Iterator<Item = (&Symbol, &Type<Tv, Cv>)> {
self.mapping.iter()
}
}