use owo_colors::{OwoColorize, colors::css::Gray}; use std::fmt::Display; #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Variable(pub String, pub Option); #[derive(Clone, Debug)] pub struct Module { pub clauses: Vec, } #[derive(Clone, Debug)] pub struct Clause { pub head: Predicate, pub body: Option, } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Body { Term(Predicate), And(Vec), Or(Vec), } #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum Predicate { Variable(Variable), // Upercase variable like X Fixed(String, Vec), } impl Display for Body { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Body::Term(predicate) => write!(f, "{}", predicate), Body::And(items) | Body::Or(items) => { let len = items.len(); for (i, item) in items.iter().enumerate() { write!(f, "{}", item)?; if i != len - 1 { write!(f, ",")?; } } Ok(()) } } } } impl Display for Variable { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0)?; if let Some(num) = self.1 { write!(f, "{}", format!("[{}]", num).fg::())?; } Ok(()) } } impl Display for Predicate { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Predicate::Variable(variable) => write!(f, "{}", variable), Predicate::Fixed(name, predicates) => { write!(f, "{}", name)?; if !predicates.is_empty() { write!(f, "(")?; let len = predicates.len(); for (i, predicate) in predicates.iter().enumerate() { write!(f, "{}", predicate)?; if i != len - 1 { write!(f, ", ")?; } } write!(f, ")") } else { Ok(()) } } } } } impl Display for Clause { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.head)?; self.body .as_ref() .map_or_else(|| Ok(()), |body| write!(f, ":- {}", body))?; write!(f, ".") } } impl Display for Module { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for clause in self.clauses.iter() { writeln!(f, "{}", clause)?; } Ok(()) } }