use symbolic_mgu::{MguError, SimpleType, Type, TypeCore};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_type_supports_all_capabilities() {
let boolean = SimpleType::try_boolean();
assert!(boolean.is_ok());
assert_eq!(boolean.unwrap(), SimpleType::Boolean);
let setvar = SimpleType::try_setvar();
assert!(setvar.is_ok());
assert_eq!(setvar.unwrap(), SimpleType::Setvar);
let class = SimpleType::try_class();
assert!(class.is_ok());
assert_eq!(class.unwrap(), SimpleType::Class);
}
#[test]
fn capability_methods_match_types() -> Result<(), MguError> {
let boolean = SimpleType::try_boolean()?;
let setvar = SimpleType::try_setvar()?;
let class = SimpleType::try_class()?;
assert_ne!(boolean, setvar);
assert_ne!(boolean, class);
assert_ne!(setvar, class);
Ok(())
}
#[test]
fn subtyping_relationships() -> Result<(), MguError> {
let boolean = SimpleType::try_boolean()?;
let setvar = SimpleType::try_setvar()?;
let class = SimpleType::try_class()?;
assert!(boolean.is_subtype_of(&boolean));
assert!(setvar.is_subtype_of(&class));
assert!(setvar.is_subtype_of(&setvar));
assert!(class.is_subtype_of(&class));
assert!(!boolean.is_subtype_of(&setvar));
assert!(!boolean.is_subtype_of(&class));
assert!(!class.is_subtype_of(&setvar));
Ok(())
}
#[test]
fn type_checking_methods() -> Result<(), MguError> {
let boolean = SimpleType::try_boolean()?;
let setvar = SimpleType::try_setvar()?;
let class = SimpleType::try_class()?;
assert!(boolean.is_boolean());
assert!(!setvar.is_boolean());
assert!(!class.is_boolean());
assert!(!boolean.is_setvar());
assert!(setvar.is_setvar());
assert!(!class.is_setvar());
assert!(!boolean.is_class());
assert!(!setvar.is_class());
assert!(class.is_class());
Ok(())
}
}
#[cfg(test)]
mod capability_checking_patterns {
use super::*;
use symbolic_mgu::{
EnumTerm, EnumTermFactory, MetaByte, MetaByteFactory, Metavariable, MetavariableFactory,
NodeByte, Statement, Term, TermFactory,
};
fn create_boolean_term<T, V, N, F>(
factory: &mut F,
var_factory: &impl MetavariableFactory<MetavariableType = T, Metavariable = V>,
) -> Result<EnumTerm<T, V, N>, MguError>
where
T: Type,
V: Metavariable<Type = T>,
N: symbolic_mgu::Node<Type = T>,
F: TermFactory<EnumTerm<T, V, N>, T, V, N, Term = EnumTerm<T, V, N>, TermMetavariable = V>,
{
let bool_type = T::try_boolean()?;
let var = var_factory
.list_metavariables_by_type(&bool_type)
.next()
.ok_or_else(|| MguError::from_type_and_var_strings("Boolean", "P"))?;
factory.create_leaf(var)
}
#[test]
fn capability_checking_in_generic_code() -> Result<(), MguError> {
let mut term_factory = EnumTermFactory::<SimpleType, MetaByte, NodeByte>::new();
let var_factory = MetaByteFactory();
let result = create_boolean_term(&mut term_factory, &var_factory);
assert!(result.is_ok());
let term = result?;
assert!(term.is_metavariable());
assert_eq!(term.get_type()?, SimpleType::Boolean);
Ok(())
}
#[test]
fn create_terms_with_all_types() -> Result<(), MguError> {
let term_factory = EnumTermFactory::<SimpleType, MetaByte, NodeByte>::new();
let var_factory = MetaByteFactory();
let bool_var = var_factory
.list_metavariables_by_type(&SimpleType::try_boolean()?)
.next()
.unwrap();
let bool_term = term_factory.create_leaf(bool_var)?;
assert_eq!(bool_term.get_type()?, SimpleType::Boolean);
let setvar = var_factory
.list_metavariables_by_type(&SimpleType::try_setvar()?)
.next()
.unwrap();
let setvar_term = term_factory.create_leaf(setvar)?;
assert_eq!(setvar_term.get_type()?, SimpleType::Setvar);
let class_var = var_factory
.list_metavariables_by_type(&SimpleType::try_class()?)
.next()
.unwrap();
let class_term = term_factory.create_leaf(class_var)?;
assert_eq!(class_term.get_type()?, SimpleType::Class);
Ok(())
}
#[test]
fn statements_require_boolean_assertions() -> Result<(), MguError> {
let term_factory = EnumTermFactory::<SimpleType, MetaByte, NodeByte>::new();
let var_factory = MetaByteFactory();
let bool_var = var_factory
.list_metavariables_by_type(&SimpleType::try_boolean()?)
.next()
.unwrap();
let p = term_factory.create_leaf(bool_var)?;
let implies = term_factory.create_node(NodeByte::Implies, vec![p.clone(), p])?;
let stmt = Statement::simple_axiom(implies);
assert!(stmt.is_ok());
Ok(())
}
#[test]
fn statements_reject_non_boolean_assertions() {
let term_factory = EnumTermFactory::<SimpleType, MetaByte, NodeByte>::new();
let var_factory = MetaByteFactory();
let setvar = var_factory
.list_metavariables_by_type(&SimpleType::Setvar)
.next()
.unwrap();
let setvar_term = term_factory.create_leaf(setvar).unwrap();
let stmt = Statement::simple_axiom(setvar_term);
assert!(
stmt.is_err(),
"Statement with Setvar assertion should be rejected"
);
if let Err(e) = stmt {
match e {
MguError::TypeMismatch(_, _) | MguError::TypeUnassignable(_, _) => {
}
_ => {
panic!(
"Expected TypeMismatch or TypeUnassignable error, got: {:?}",
e
);
}
}
}
}
#[test]
fn compound_boolean_expressions() -> Result<(), MguError> {
let term_factory = EnumTermFactory::<SimpleType, MetaByte, NodeByte>::new();
let var_factory = MetaByteFactory();
let p = var_factory
.list_metavariables_by_type(&SimpleType::try_boolean()?)
.next()
.unwrap();
let q = var_factory
.list_metavariables_by_type(&SimpleType::try_boolean()?)
.nth(1)
.unwrap();
let p_term = term_factory.create_leaf(p)?;
let q_term = term_factory.create_leaf(q)?;
let and_term =
term_factory.create_node(NodeByte::And, vec![p_term.clone(), q_term.clone()])?;
assert_eq!(and_term.get_type()?, SimpleType::Boolean);
let not_term = term_factory.create_node(NodeByte::Not, vec![p_term.clone()])?;
assert_eq!(not_term.get_type()?, SimpleType::Boolean);
let implies = term_factory.create_node(NodeByte::Implies, vec![and_term, p_term])?;
assert_eq!(implies.get_type()?, SimpleType::Boolean);
let stmt = Statement::simple_axiom(implies)?;
assert_eq!(stmt.get_n_hypotheses(), 0);
Ok(())
}
#[test]
fn demonstrate_capability_check_pattern() {
let supports_boolean = SimpleType::try_boolean().is_ok();
assert!(supports_boolean, "SimpleType should support Boolean");
let supports_setvar = SimpleType::try_setvar().is_ok();
assert!(supports_setvar, "SimpleType should support Setvar");
let supports_class = SimpleType::try_class().is_ok();
assert!(supports_class, "SimpleType should support Class");
fn needs_setvar_capability<T: Type>() -> Result<T, MguError> {
T::try_setvar()
}
let result = needs_setvar_capability::<SimpleType>();
assert!(result.is_ok());
}
}