use std::fmt;
use super::atom::Atom;
use super::symbols::{ConstantSymbol, VariableSymbol};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Term {
Variable(VariableSymbol),
Constant(ConstantSymbol),
TripleTerm(Box<Atom>),
Skolem {
name: ConstantSymbol,
args: Vec<Term>,
},
}
impl Term {
#[must_use]
pub(super) fn variable_name(&self) -> Option<&VariableSymbol> {
match self {
Self::Variable(var) => Some(var),
Self::Constant(_) | Self::TripleTerm(_) | Self::Skolem { .. } => None,
}
}
#[must_use]
pub(super) fn nesting_depth(&self) -> usize {
match self {
Self::Variable(_) | Self::Constant(_) | Self::Skolem { .. } => 0,
Self::TripleTerm(atom) => 1 + atom.nesting_depth(),
}
}
#[must_use]
pub fn is_skolem(&self) -> bool {
matches!(self, Self::Skolem { .. })
}
}
pub const MAX_TRIPLE_TERM_NESTING: usize = 4;
impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Variable(var) => write!(f, "?{}", var.as_str()),
Self::Constant(c) => write!(f, "{}", c.as_str()),
Self::TripleTerm(atom) => {
if atom.terms.len() == 2 {
write!(
f,
"<< {} {} {} >>",
atom.terms[0],
atom.predicate.as_str(),
atom.terms[1],
)
} else {
write!(f, "<< {atom} >>")
}
}
Self::Skolem { name, args } => {
write!(f, "SKOLEM({}", name.as_str())?;
for arg in args {
write!(f, ", {arg}")?;
}
write!(f, ")")
}
}
}
}