struct TermDisplay<'parent> { parent: Option<&'parent crate::Term>, term: &'parent crate::Term, } struct FormulaDisplay<'parent> { parent: Option<&'parent crate::Formula>, formula: &'parent crate::Formula, } fn display_term<'parent>(term: &'parent crate::Term, parent: Option<&'parent crate::Term>) -> TermDisplay<'parent> { TermDisplay { parent, term, } } fn display_formula<'parent>(formula: &'parent crate::Formula, parent: Option<&'parent crate::Formula>) -> FormulaDisplay<'parent> { FormulaDisplay { parent, formula, } } fn term_precedence(term: &crate::Term) -> u64 { match term { crate::Term::Infimum | crate::Term::Supremum | crate::Term::Integer(_) | crate::Term::Symbolic(_) | crate::Term::String(_) | crate::Term::Variable(_) => 0, crate::Term::Negative(_) => 1, crate::Term::Multiply(_, _) => 2, crate::Term::Add(_, _) | crate::Term::Subtract(_, _) => 3, } } fn term_requires_parentheses(child: &crate::Term, parent: Option<&crate::Term>) -> bool { match parent { None => false, Some(parent) => { let child_precedence = term_precedence(child); let parent_precedence = term_precedence(parent); if child_precedence != parent_precedence { return child_precedence > parent_precedence; } // Subtraction isn’t associative, so handle them separately // TODO: only do this for right-hand side of subtractions match parent { crate::Term::Subtract(_, _) => true, _ => false, } }, } } fn formula_precedence(formula: &crate::Formula) -> u64 { match formula { crate::Formula::Predicate(_) | crate::Formula::Boolean(_) | crate::Formula::Less(_, _) | crate::Formula::LessOrEqual(_, _) | crate::Formula::Greater(_, _) | crate::Formula::GreaterOrEqual(_, _) | crate::Formula::Equal(_, _) | crate::Formula::NotEqual(_, _) => 0, crate::Formula::Exists(_) | crate::Formula::ForAll(_) => 1, crate::Formula::Not(_) => 2, crate::Formula::And(_) => 3, crate::Formula::Or(_) => 4, crate::Formula::Implies(_, _, _) => 5, crate::Formula::Biconditional(_, _) => 6, } } fn formula_requires_parentheses(child: &crate::Formula, parent: Option<&crate::Formula>) -> bool { match parent { None => false, Some(parent) => { let child_precedence = formula_precedence(child); let parent_precedence = formula_precedence(parent); if child_precedence != parent_precedence { return child_precedence > parent_precedence; } // Implications aren’t associative, so handle them separately match parent { crate::Formula::Implies(_, _, _) => true, _ => false, } }, } } impl std::fmt::Debug for crate::VariableDeclaration { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{}", &self.name) } } impl std::fmt::Display for crate::VariableDeclaration { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{:?}", &self) } } impl<'term> std::fmt::Debug for TermDisplay<'term> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { let requires_parentheses = term_requires_parentheses(self.term, self.parent); if requires_parentheses { write!(format, "(")?; } match self.term { crate::Term::Infimum => write!(format, "#inf"), crate::Term::Supremum => write!(format, "#sup"), crate::Term::Integer(value) => write!(format, "{}", value), crate::Term::Symbolic(ref value) => write!(format, "{}", value), crate::Term::String(ref value) => write!(format, "\"{}\"", value), crate::Term::Variable(ref declaration) => write!(format, "{:?}", declaration), crate::Term::Add(ref left, ref right) => write!(format, "{:?} + {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))), crate::Term::Subtract(ref left, ref right) => write!(format, "{:?} - {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))), crate::Term::Multiply(ref left, ref right) => write!(format, "{:?} * {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))), crate::Term::Negative(ref argument) => write!(format, "-{:?}", display_term(argument, Some(self.term))), }?; if requires_parentheses { write!(format, ")")?; } Ok(()) } } impl<'term> std::fmt::Display for TermDisplay<'term> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{:?}", self) } } impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { let requires_parentheses = formula_requires_parentheses(self.formula, self.parent); if requires_parentheses { write!(format, "(")?; } match self.formula { crate::Formula::Exists(ref exists) => { write!(format, "exists")?; let mut separator = " "; for parameter in &exists.parameters { write!(format, "{}{:?}", separator, parameter)?; separator = ", " } write!(format, " {:?}", display_formula(&exists.argument, Some(self.formula)))?; }, crate::Formula::ForAll(ref for_all) => { write!(format, "forall")?; let mut separator = " "; for parameter in &for_all.parameters { write!(format, "{}{:?}", separator, parameter)?; separator = ", " } write!(format, " {:?}", display_formula(&for_all.argument, Some(self.formula)))?; }, crate::Formula::Not(ref argument) => write!(format, "not {:?}", display_formula(argument, Some(self.formula)))?, crate::Formula::And(ref arguments) => { let mut separator = ""; for argument in arguments { write!(format, "{}{:?}", separator, display_formula(argument, Some(self.formula)))?; separator = " and " } }, crate::Formula::Or(ref arguments) => { let mut separator = ""; for argument in arguments { write!(format, "{}{:?}", separator, display_formula(argument, Some(self.formula)))?; separator = " or " } }, crate::Formula::Implies(ref left, ref right, implication_direction) => match implication_direction { crate::ImplicationDirection::LeftToRight => write!(format, "{:?} -> {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?, crate::ImplicationDirection::RightToLeft => write!(format, "{:?} <- {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?, }, crate::Formula::Biconditional(ref left, ref right) => write!(format, "{:?} <-> {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?, crate::Formula::Less(ref left, ref right) => write!(format, "{:?} < {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::LessOrEqual(ref left, ref right) => write!(format, "{:?} <= {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::Greater(ref left, ref right) => write!(format, "{:?} > {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::GreaterOrEqual(ref left, ref right) => write!(format, "{:?} >= {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::Equal(ref left, ref right) => write!(format, "{:?} = {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::NotEqual(ref left, ref right) => write!(format, "{:?} != {:?}", display_term(left, None), display_term(right, None))?, crate::Formula::Boolean(value) => match value { true => write!(format, "#true")?, false => write!(format, "#false")?, }, crate::Formula::Predicate(ref predicate) => { write!(format, "{}", predicate.declaration.name)?; if !predicate.arguments.is_empty() { write!(format, "(")?; let mut separator = ""; for argument in &predicate.arguments { write!(format, "{}{:?}", separator, display_term(argument, None))?; separator = ", " } write!(format, ")")?; } }, } if requires_parentheses { write!(format, ")")?; } Ok(()) } } impl<'formula> std::fmt::Display for FormulaDisplay<'formula> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{:?}", self) } } impl std::fmt::Debug for crate::Formula { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{:?}", display_formula(&self, None)) } } impl std::fmt::Display for crate::Formula { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{}", display_formula(&self, None)) } } impl std::fmt::Debug for crate::Term { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{:?}", display_term(&self, None)) } } impl std::fmt::Display for crate::Term { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { write!(format, "{}", display_term(&self, None)) } }