use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Term {
pub kind: TermKind,
pub line: u32,
pub column: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TermKind {
Var(String),
Int(i128),
App {
head: String,
args: Vec<Term>,
},
}
impl Term {
pub fn walk<'t>(&'t self, visit: &mut impl FnMut(&'t Term)) {
visit(self);
if let TermKind::App { args, .. } = &self.kind {
for arg in args {
arg.walk(visit);
}
}
}
}
impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
TermKind::Var(name) => f.write_str(name),
TermKind::Int(value) => write!(f, "{value}"),
TermKind::App { head, args } => {
write!(f, "({head}")?;
for arg in args {
write!(f, " {arg}")?;
}
f.write_str(")")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Rule {
pub pattern: Term,
pub guard: Option<Term>,
pub replacement: Term,
pub spec: Term,
pub bounded: Option<String>,
pub line: u32,
pub column: u32,
}
impl fmt::Display for Rule {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "(rule (lower {})", self.pattern)?;
if let Some(guard) = &self.guard {
writeln!(f, " (if {guard})")?;
}
writeln!(f, " {}", self.replacement)?;
match &self.bounded {
Some(why) => {
writeln!(f, " (spec {})", self.spec)?;
write!(f, " (bounded \"{why}\"))")
}
None => write!(f, " (spec {}))", self.spec),
}
}
}