diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 9b12a9ad4..278600d10 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -995,17 +995,57 @@ mod test { } #[test] - fn match_atoms_with_custom_matcher_implementation() { + fn match_atoms_with_custom_matcher() { assert_match( - expr!({Rand{}}), - expr!((x)), + expr!( {Rand{}} ), + expr!( (x) ), vec![bind!{x: expr!({42})}]); assert_match( - expr!((x)), - expr!({Rand{}}), + expr!( (x) ), + expr!( {Rand{}} ), vec![bind!{x: expr!({42})}]); } + #[derive(PartialEq, Clone, Debug, Copy)] + struct ReturnPairInX{} + + impl Grounded for ReturnPairInX { + fn type_(&self) -> Atom { + Atom::sym("ReturnPairInX") + } + fn execute(&self, _args: &mut Vec) -> Result, ExecError> { + execute_not_executable(self) + } + fn match_(&self, _other: &Atom) -> matcher::MatchResultIter { + let result = vec![ bind!{ x: expr!("B") }, bind!{ x: expr!("C") } ]; + Box::new(result.into_iter()) + } + } + + impl Display for ReturnPairInX { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "ReturnPairInX") + } + } + + #[ignore = "An API change in Bindings is required in order to implement this"] + #[test] + fn match_atoms_with_custom_matcher_split_results_by_adding_value() { + let pair = ReturnPairInX{}; + + assert_match( + expr!( { pair } ("A" x) ), + expr!( s s ), + vec![ bind!{ s: expr!({ pair }), x: expr!("B") }, + bind!{ s: expr!({ pair }), x: expr!("C") } ]); + + assert_match( + expr!( { pair } y y ), + expr!( s ("A" x) s ), + vec![ bind!{ s: expr!({ pair }), y: expr!("A" x), x: expr!("B") }, + bind!{ s: expr!({ pair }), y: expr!("A" x), x: expr!("C") } ]); + } + #[ignore = "Requires sorting inside Bindings to be stable"] #[test] fn bindings_match_display() { @@ -1083,4 +1123,39 @@ mod test { assert_eq!(narrow, bind!{ rightB: expr!("A"), rightF: expr!("F"), rightE: expr!(rightE) }); } + + #[ignore = "An API change is required in order to implement this"] + #[test] + fn bindings_add_var_value_splits_bindings() { + let mut bindings = Bindings::new(); + let pair = ReturnPairInX{}; + + // ({ x -> B, x -> C } (A $x)) ~ ($s $s) + bindings.add_var_binding(VariableAtom::new("s"), expr!({ pair })); + bindings.add_var_binding(VariableAtom::new("s"), expr!("A" x)); + + // Bindings::add_var_binding() should return a list of resulting + // Bindings instances. + // assert_eq_no_order!(result, + // vec![ bind!{ s: expr!({ pair }), x: expr!("B") }, + // bind!{ s: expr!({ pair }), x: expr!("C") } ]); + } + + #[ignore = "An API change is required in order to implement this"] + #[test] + fn bindings_add_var_equality_splits_bindings() { + let mut bindings = Bindings::new(); + let pair = ReturnPairInX{}; + + // ({ x -> B, x -> C } $y $y) ~ ($s (A $x) $s) + bindings.add_var_binding(VariableAtom::new("s"), expr!({ pair })); + bindings.add_var_binding(VariableAtom::new("y"), expr!("A" x)); + bindings.add_var_equality(&VariableAtom::new("y"), &VariableAtom::new("s")); + + // Bindings::add_var_binding() should return a list of resulting + // Bindings instances. + // assert_eq_no_order!(result, + // vec![ bind!{ s: expr!({ pair }), y: expr!("A" x), x: expr!("B") }, + // bind!{ s: expr!({ pair }), y: expr!("A" x), x: expr!("C") } ]); + } } diff --git a/lib/src/metta/types.rs b/lib/src/metta/types.rs index 7813bb6ed..f659d152d 100644 --- a/lib/src/metta/types.rs +++ b/lib/src/metta/types.rs @@ -59,7 +59,7 @@ fn add_super_types(space: &dyn Space, sub_types: &mut Vec, from: usize) { fn check_types(actual: &[Vec], expected: &[Atom], bindings: &mut Bindings) -> bool { log::trace!("check_types: actual: {:?}, expected: {:?}, bindings: {}", actual, expected, bindings); - match (actual, expected) { + let matched = match (actual, expected) { ([actual, actual_tail @ ..], [expected, expected_tail @ ..]) => { actual.iter().map(|actual| { match_reducted_types(actual, expected, bindings) @@ -68,7 +68,9 @@ fn check_types(actual: &[Vec], expected: &[Atom], bindings: &mut Bindings) }, ([], []) => true, _ => false, - } + }; + log::trace!("check_types: actual: {:?}, expected: {:?}, bindings: {}, matched: {}", actual, expected, bindings, matched); + matched } /// Returns true if passed type is a type of function.