use crate::app::format as fmt_appl;
use alloc::vec::Vec;
use core::fmt::{self, Display};
pub type Miller = usize;
#[derive(Clone)]
pub enum Pattern<S> {
Symb(S, Vec<Pattern<S>>),
MVar(Miller),
Joker,
}
pub type TopPattern<S> = crate::App<S, Pattern<S>>;
impl<S> Pattern<S> {
pub fn joke(self, joker: Miller) -> Self {
match self {
Self::Symb(s, args) => Self::Symb(s, args.into_iter().map(|p| p.joke(joker)).collect()),
Self::MVar(v) if v == joker => Self::Joker,
pat => pat,
}
}
}
impl<S> From<TopPattern<S>> for Pattern<S> {
fn from(tp: TopPattern<S>) -> Self {
Self::Symb(tp.symbol, tp.args)
}
}
impl<S> TryFrom<Pattern<S>> for TopPattern<S> {
type Error = ();
fn try_from(p: Pattern<S>) -> Result<Self, Self::Error> {
match p {
Pattern::Symb(symbol, args) => Ok(TopPattern { symbol, args }),
_ => Err(()),
}
}
}
impl<S: Display> Display for Pattern<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Symb(s, pats) => fmt_appl(s, pats, f),
Self::MVar(m) => write!(f, "μ{}", m),
Self::Joker => write!(f, "_"),
}
}
}