use super::common::*;
#[derive(Debug, Clone, PartialEq)]
pub enum FOFStatement<'a> {
Logical(FOFFormula<'a>),
Sequent(Vec<FOFFormula<'a>>, Vec<FOFFormula<'a>>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum FOFFormula<'a> {
Atomic(FOFAtomicFormula<'a>),
Negation(Box<FOFFormula<'a>>),
Quantified {
quantifier: Quantifier,
variables: Vec<&'a str>,
formula: Box<FOFFormula<'a>>,
},
Binary {
left: Box<FOFFormula<'a>>,
connective: BinaryConnective,
right: Box<FOFFormula<'a>>,
},
Equality(FOFTerm<'a>, FOFTerm<'a>),
Inequality(FOFTerm<'a>, FOFTerm<'a>),
Parens(Box<FOFFormula<'a>>),
}
impl<'a> FOFFormula<'a> {
pub fn atomic(predicate: AtomicWord<'a>, args: Vec<FOFTerm<'a>>) -> Self {
FOFFormula::Atomic(FOFAtomicFormula::Plain(predicate, args))
}
pub fn negation(formula: FOFFormula<'a>) -> Self {
FOFFormula::Negation(Box::new(formula))
}
pub fn forall(variables: Vec<&'a str>, formula: FOFFormula<'a>) -> Self {
FOFFormula::Quantified {
quantifier: Quantifier::Forall,
variables,
formula: Box::new(formula),
}
}
pub fn exists(variables: Vec<&'a str>, formula: FOFFormula<'a>) -> Self {
FOFFormula::Quantified {
quantifier: Quantifier::Exists,
variables,
formula: Box::new(formula),
}
}
pub fn binary(left: FOFFormula<'a>, conn: BinaryConnective, right: FOFFormula<'a>) -> Self {
FOFFormula::Binary {
left: Box::new(left),
connective: conn,
right: Box::new(right),
}
}
pub fn and(left: FOFFormula<'a>, right: FOFFormula<'a>) -> Self {
Self::binary(left, BinaryConnective::And, right)
}
pub fn or(left: FOFFormula<'a>, right: FOFFormula<'a>) -> Self {
Self::binary(left, BinaryConnective::Or, right)
}
pub fn implies(left: FOFFormula<'a>, right: FOFFormula<'a>) -> Self {
Self::binary(left, BinaryConnective::Impl, right)
}
pub fn iff(left: FOFFormula<'a>, right: FOFFormula<'a>) -> Self {
Self::binary(left, BinaryConnective::Iff, right)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum FOFAtomicFormula<'a> {
Plain(AtomicWord<'a>, Vec<FOFTerm<'a>>),
Defined(DefinedWord<'a>, Vec<FOFTerm<'a>>),
System(SystemWord<'a>, Vec<FOFTerm<'a>>),
True,
False,
}
impl<'a> FOFAtomicFormula<'a> {
pub fn plain(predicate: AtomicWord<'a>, args: Vec<FOFTerm<'a>>) -> Self {
FOFAtomicFormula::Plain(predicate, args)
}
pub fn proposition(name: AtomicWord<'a>) -> Self {
FOFAtomicFormula::Plain(name, Vec::new())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum FOFTerm<'a> {
Variable(&'a str),
Function(AtomicWord<'a>, Vec<FOFTerm<'a>>),
DefinedFunction(DefinedWord<'a>, Vec<FOFTerm<'a>>),
SystemFunction(SystemWord<'a>, Vec<FOFTerm<'a>>),
Number(Number<'a>),
DistinctObject(&'a str),
}
impl<'a> FOFTerm<'a> {
pub fn variable(name: &'a str) -> Self {
FOFTerm::Variable(name)
}
pub fn function(name: AtomicWord<'a>, args: Vec<FOFTerm<'a>>) -> Self {
FOFTerm::Function(name, args)
}
pub fn constant(name: AtomicWord<'a>) -> Self {
FOFTerm::Function(name, Vec::new())
}
pub fn is_variable(&self) -> bool {
matches!(self, FOFTerm::Variable(_))
}
pub fn is_ground(&self) -> bool {
match self {
FOFTerm::Variable(_) => false,
FOFTerm::Function(_, args)
| FOFTerm::DefinedFunction(_, args)
| FOFTerm::SystemFunction(_, args) => args.iter().all(|a| a.is_ground()),
FOFTerm::Number(_) | FOFTerm::DistinctObject(_) => true,
}
}
}