use std::fmt;
pub use super::term::Term as Type;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Atom {
Lit(String),
Hole(String),
Ref(String),
Ctx(String),
Inst(String),
Top,
Bot,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TypeExpr(pub Vec<Atom>);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TyExpr {
Var(String),
Ref(String),
Ctx(String),
Inst(String),
Top,
Bot,
Lit(String),
Con(String, Vec<TyExpr>),
}
impl fmt::Display for TyExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TyExpr::Var(n) => write!(f, "?{n}"),
TyExpr::Ref(n) => write!(f, "{n}"),
TyExpr::Ctx(v) => write!(f, "Γ({v})"),
TyExpr::Inst(v) => write!(f, "inst({v})"),
TyExpr::Top => write!(f, "⊤"),
TyExpr::Bot => write!(f, "∅"),
TyExpr::Lit(s) => write!(f, "'{s}'"),
TyExpr::Con(label, kids) => {
write!(f, "{label}(")?;
for (i, k) in kids.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{k}")?;
}
write!(f, ")")
}
}
}
}
impl TypeExpr {
#[must_use]
pub fn holes(&self) -> Vec<&str> {
self.collect(|a| matches!(a, Atom::Hole(_)))
}
#[must_use]
pub fn refs(&self) -> Vec<&str> {
self.collect(|a| matches!(a, Atom::Ref(_)))
}
fn collect(&self, pred: impl Fn(&Atom) -> bool) -> Vec<&str> {
self.0
.iter()
.filter(|a| pred(a))
.filter_map(Atom::name)
.collect()
}
#[must_use]
pub fn has_holes(&self) -> bool {
self.0.iter().any(|a| matches!(a, Atom::Hole(_)))
}
}
impl Atom {
fn name(&self) -> Option<&str> {
match self {
Atom::Lit(n) | Atom::Hole(n) | Atom::Ref(n) | Atom::Ctx(n) | Atom::Inst(n) => {
Some(n.as_str())
}
Atom::Top | Atom::Bot => None,
}
}
}
impl fmt::Display for Atom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Atom::Lit(s) => write!(f, "{s}"),
Atom::Hole(n) => write!(f, "?{n}"),
Atom::Ref(n) => write!(f, "{n}"),
Atom::Ctx(v) => write!(f, "Γ({v})"),
Atom::Inst(v) => write!(f, "inst({v})"),
Atom::Top => write!(f, "⊤"),
Atom::Bot => write!(f, "∅"),
}
}
}
impl fmt::Display for TypeExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for a in &self.0 {
write!(f, "{a}")?;
}
Ok(())
}
}