use std::fmt;
use super::symbols::{ConstantSymbol, PredicateSymbol};
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize,
)]
#[serde(try_from = "super::serde_input::GroundTermInput")]
pub enum GroundTerm {
Constant(ConstantSymbol),
TripleTerm(Box<GroundAtom>),
}
impl GroundTerm {
#[must_use]
pub fn constant(c: ConstantSymbol) -> Self {
Self::Constant(c)
}
#[must_use]
pub fn as_constant(&self) -> Option<&ConstantSymbol> {
match self {
Self::Constant(c) => Some(c),
Self::TripleTerm(_) => None,
}
}
}
impl From<ConstantSymbol> for GroundTerm {
fn from(c: ConstantSymbol) -> Self {
Self::Constant(c)
}
}
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize,
)]
#[serde(deny_unknown_fields)]
pub struct GroundAtom {
pub predicate: PredicateSymbol,
pub args: Vec<GroundTerm>,
}
impl GroundAtom {
#[must_use]
pub fn arity(&self) -> usize {
self.args.len()
}
}
impl fmt::Display for GroundTerm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Constant(c) => write!(f, "{}", c.as_str()),
Self::TripleTerm(atom) => {
if atom.args.len() == 2 {
write!(
f,
"<< {} {} {} >>",
atom.args[0],
atom.predicate.as_str(),
atom.args[1],
)
} else {
write!(f, "<< {atom} >>")
}
}
}
}
}
impl fmt::Display for GroundAtom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}(", self.predicate.as_str())?;
for (idx, arg) in self.args.iter().enumerate() {
if idx > 0 {
write!(f, ", ")?;
}
write!(f, "{arg}")?;
}
write!(f, ")")
}
}