From 87cd7338e601d4e4c9d252936dee8001805a7df0 Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Thu, 12 Dec 2024 11:17:47 +0300 Subject: [PATCH 1/8] Calling help! without parameters shows list of stdlib functions --- lib/src/metta/runner/stdlib/stdlib.metta | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/src/metta/runner/stdlib/stdlib.metta b/lib/src/metta/runner/stdlib/stdlib.metta index 43fe597e4..aa364322a 100644 --- a/lib/src/metta/runner/stdlib/stdlib.metta +++ b/lib/src/metta/runner/stdlib/stdlib.metta @@ -816,7 +816,7 @@ (@doc-formal (@item $atom) (@kind atom) (@type $type) (@desc "No documentation")) ))))) (@doc help! - (@desc "Function prints documentation for the input atom.") + (@desc "Function prints documentation for the input atom. Without parameters prints the list of the stdlib functions.") (@params ( (@param "Input to get documentation for"))) (@return "Unit atom")) @@ -839,6 +839,16 @@ () )) ($other (Error $other "Cannot match @doc-formal structure") )))) +(: help! (-> (->))) +(= (help!) (let $top-space (mod-space! top) + (unify $top-space (@doc $name (@desc $desc) $params $ret) + (let () (println! (format-args "{}\n\t{}" ($name $desc))) Empty) + Empty))) +(= (help!) (let $top-space (mod-space! top) + (unify $top-space (@doc $name (@desc $desc)) + (let () (println! (format-args "{}\n\t{}" ($name $desc))) Empty) + Empty))) + (@doc help-param! (@desc "Function used by function help! to output parameters using println!") (@params ( From 74dae4df4b00ed79f61f60dbf6f6b429e9f770f1 Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Thu, 12 Dec 2024 11:26:25 +0300 Subject: [PATCH 2/8] Add REPL banner with help information --- repl/src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/repl/src/main.rs b/repl/src/main.rs index 4a9b28a6c..686b57c7a 100644 --- a/repl/src/main.rs +++ b/repl/src/main.rs @@ -137,6 +137,9 @@ fn start_interactive_mode(repl_params: ReplParams, mut metta: MettaShim) -> rust } } + println!("Visit https://metta-lang.dev/ for tutorials."); + println!("Execute !(help!) to get list of the standard library functions."); + //The Interpreter Loop loop { From 4ea5f01b32b0517a3ddf7f7fd558b917ed16c3de Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Thu, 12 Dec 2024 11:55:03 +0300 Subject: [PATCH 3/8] Add function to document code --- repl/src/main.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/repl/src/main.rs b/repl/src/main.rs index 686b57c7a..06615adfd 100644 --- a/repl/src/main.rs +++ b/repl/src/main.rs @@ -93,6 +93,11 @@ fn main() -> Result<()> { } } +fn show_welcome_message() { + println!("Visit https://metta-lang.dev/ for tutorials."); + println!("Execute !(help!) to get list of the standard library functions."); +} + // To debug rustyline: // RUST_LOG=rustyline=debug cargo run --example example 2> debug.log fn start_interactive_mode(repl_params: ReplParams, mut metta: MettaShim) -> rustyline::Result<()> { @@ -137,8 +142,7 @@ fn start_interactive_mode(repl_params: ReplParams, mut metta: MettaShim) -> rust } } - println!("Visit https://metta-lang.dev/ for tutorials."); - println!("Execute !(help!) to get list of the standard library functions."); + show_welcome_message(); //The Interpreter Loop loop { From 9c669ce2966500ae14291e213e57e80250f2a95b Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Mon, 16 Dec 2024 13:08:20 +0300 Subject: [PATCH 4/8] Replace deprecated add_var_binding implementation --- c/src/atom.rs | 2 +- lib/src/atom/matcher.rs | 98 +++++++++++++++--------------------- lib/src/metta/interpreter.rs | 2 +- 3 files changed, 43 insertions(+), 59 deletions(-) diff --git a/c/src/atom.rs b/c/src/atom.rs index aa038ad02..e1767b40f 100644 --- a/c/src/atom.rs +++ b/c/src/atom.rs @@ -1256,7 +1256,7 @@ pub extern "C" fn bindings_add_var_binding(bindings: *mut bindings_t, var: atom_ _ => panic!("var argument must be variable atom") }; let atom = atom.into_inner(); - match bindings.clone().add_var_binding_v2(var, atom) { + match bindings.clone().add_var_binding(var, atom) { Ok(new_bindings) => { *bindings = new_bindings; true diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 102bcf58c..6ed24c513 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -131,6 +131,7 @@ impl Binding { } } +// TODO: rename Bindings to Substitution which is more common term /// Represents variable bindings. Keeps two kinds of relations inside: /// variables equalities and variable value assignments. For example this /// structure is able to precisely represent result of matching atoms like @@ -358,13 +359,13 @@ impl Bindings { /// let mut binds = bind!{ a: expr!("A"), b: expr!("B") }; /// /// // Re-asserting an existing binding is ok - /// binds = binds.add_var_binding_v2(&a, &expr!("A"))?; + /// binds = binds.add_var_binding(&a, &expr!("A"))?; /// /// // Asserting a conflicting binding is an error - /// assert!(binds.clone().add_var_binding_v2(&b, &expr!("C")).is_err()); + /// assert!(binds.clone().add_var_binding(&b, &expr!("C")).is_err()); /// /// // Creating a new binding is ok - /// binds = binds.add_var_binding_v2(&c, &expr!("C"))?; + /// binds = binds.add_var_binding(&c, &expr!("C"))?; /// /// assert_eq!(binds.resolve(&a), Some(expr!("A"))); /// assert_eq!(binds.resolve(&b), Some(expr!("B"))); @@ -372,9 +373,7 @@ impl Bindings { /// # Ok(()) /// # } /// ``` - /// - /// TODO: Rename to `add_var_binding` when clients have adopted the new API - pub fn add_var_binding_v2(self, var: T1, value: T2) -> Result + pub fn add_var_binding(self, var: T1, value: T2) -> Result where T1: RefOrMove, T2: RefOrMove { let temp_set = self.add_var_binding_internal(var, value); @@ -421,21 +420,6 @@ impl Bindings { result } - /// Tries to insert `value` as a binding for the `var`. If `self` already - /// has binding for the `var` and it is not matchable with the `value` then - /// function returns `false`. Otherwise it inserts binding and returns `true`. - /// - /// TODO: This implementation should be deprecated in favor of the implementation in `add_var_binding_v2` - pub fn add_var_binding<'a, T1: RefOrMove, T2: RefOrMove>(&mut self, var: T1, value: T2) -> bool { - match self.clone().add_var_binding_v2(var.as_value(), value.as_value()) { - Ok(new_bindings) => { - *self = new_bindings; - true - }, - Err(_) => false - } - } - fn with_var_no_value(mut self, var: &VariableAtom) -> Self { self.add_var_no_value(var); self @@ -756,7 +740,7 @@ impl Bindings { for var in to_remove { let atom = self.remove_var_from_binding(&var); if let Some(atom) = atom { - removed.add_var_binding(var, atom); + removed = removed.add_var_binding(var, atom).unwrap(); } } for binding in &mut self.bindings { @@ -868,7 +852,7 @@ impl From<&[(VariableAtom, Atom)]> for Bindings { for (var, val) in pairs { bindings = match val { Atom::Variable(val) => bindings.add_var_equality(&var, &val), - _ => bindings.add_var_binding_v2(var, val), + _ => bindings.add_var_binding(var, val), }.unwrap_or_else(|e| panic!("Error creating Bindings from Atoms: {}", e)); } bindings @@ -1452,7 +1436,7 @@ mod test { match expr.children()[0] { Atom::Variable(ref var) => { let bindings = Bindings::new() - .add_var_binding_v2(var, expr!({42})).unwrap(); + .add_var_binding(var, expr!({42})).unwrap(); Box::new(std::iter::once(bindings)) }, _ => Box::new(std::iter::empty()), @@ -1527,7 +1511,7 @@ mod test { fn bindings_match_display() -> Result<(), &'static str> { let bindings = Bindings::new() .add_var_equality(&VariableAtom::new("a"), &VariableAtom::new("b"))? - .add_var_binding_v2(VariableAtom::new("b"), Atom::sym("v"))? + .add_var_binding(VariableAtom::new("b"), Atom::sym("v"))? .add_var_equality(&VariableAtom::new("c"), &VariableAtom::new("d"))?; assert_eq!(bindings.to_string(), "{ $a = $b = v, $c = $d }"); @@ -1552,8 +1536,8 @@ mod test { #[test] fn bindings_get_variable_bound_to_value() -> Result<(), &'static str> { let bindings = Bindings::new() - .add_var_binding_v2(VariableAtom::new("x"), expr!("A" y))? - .add_var_binding_v2(VariableAtom::new("y"), expr!("B" z))?; + .add_var_binding(VariableAtom::new("x"), expr!("A" y))? + .add_var_binding(VariableAtom::new("y"), expr!("B" z))?; assert_eq!(bindings.resolve(&VariableAtom::new("x")), Some(expr!("A" ("B" z)))); assert_eq!(bindings.resolve(&VariableAtom::new("y")), Some(expr!("B" z))); @@ -1563,8 +1547,8 @@ mod test { #[test] fn bindings_get_variable_bound_to_value_with_loop() -> Result<(), &'static str> { let bindings = Bindings::new() - .add_var_binding_v2(VariableAtom::new("x"), expr!("A" y))? - .add_var_binding_v2(VariableAtom::new("y"), expr!("B" x))?; + .add_var_binding(VariableAtom::new("x"), expr!("A" y))? + .add_var_binding(VariableAtom::new("y"), expr!("B" x))?; assert_eq!(bindings.resolve(&VariableAtom::new("x")), None); assert_eq!(bindings.resolve(&VariableAtom::new("y")), None); @@ -1574,7 +1558,7 @@ mod test { #[test] fn bindings_get_variable_bound_to_variable() -> Result<(), &'static str> { let bindings = Bindings::new() - .add_var_binding_v2(VariableAtom::new("x"), expr!(x))?; + .add_var_binding(VariableAtom::new("x"), expr!(x))?; assert_eq!(bindings.resolve(&VariableAtom::new("x")), None); Ok(()) @@ -1600,11 +1584,11 @@ mod test { #[test] fn bindings_narrow_vars() -> Result<(), &'static str> { let bindings = Bindings::new() - .add_var_binding_v2(VariableAtom::new("leftA"), expr!("A"))? + .add_var_binding(VariableAtom::new("leftA"), expr!("A"))? .add_var_equality(&VariableAtom::new("leftA"), &VariableAtom::new("rightB"))? - .add_var_binding_v2(VariableAtom::new("leftC"), expr!("C"))? + .add_var_binding(VariableAtom::new("leftC"), expr!("C"))? .add_var_equality(&VariableAtom::new("leftD"), &VariableAtom::new("rightE"))? - .add_var_binding_v2(VariableAtom::new("rightF"), expr!("F"))?; + .add_var_binding(VariableAtom::new("rightF"), expr!("F"))?; let narrow = bindings.narrow_vars(&HashSet::from([&VariableAtom::new("rightB"), &VariableAtom::new("rightE"), &VariableAtom::new("rightF")])); @@ -1615,7 +1599,7 @@ mod test { #[test] fn bindings_narrow_vars_infinite_loop() -> Result<(), &'static str> { - let bindings = Bindings::new().add_var_binding_v2(VariableAtom::new("x"), expr!("a" x "b"))?; + let bindings = Bindings::new().add_var_binding(VariableAtom::new("x"), expr!("a" x "b"))?; let narrow = bindings.narrow_vars(&HashSet::from([&VariableAtom::new("x")])); @@ -1642,18 +1626,18 @@ mod test { let b = VariableAtom::new("b"); let bindings = Bindings::new() .add_var_equality(&a, &b)? - .add_var_binding_v2(a.clone(), expr!("A"))?; + .add_var_binding(a.clone(), expr!("A"))?; let result = bindings.clone().convert_var_equalities_to_bindings(&[a.clone()].into()); let expected = Bindings::new() - .add_var_binding_v2(a.clone(), expr!("A"))? - .add_var_binding_v2(&b, expr!(a))?; + .add_var_binding(a.clone(), expr!("A"))? + .add_var_binding(&b, expr!(a))?; assert_eq!(result, expected); let result = bindings.clone().convert_var_equalities_to_bindings(&[b.clone()].into()); let expected = Bindings::new() - .add_var_binding_v2(b.clone(), expr!("A"))? - .add_var_binding_v2(&a, expr!(b))?; + .add_var_binding(b.clone(), expr!("A"))? + .add_var_binding(&a, expr!(b))?; assert_eq!(result, expected); Ok(()) @@ -1680,7 +1664,7 @@ mod test { let a = VariableAtom::new("a"); let bindings = Bindings::new(); assert_eq!( - bindings.add_var_binding_v2(a.clone(), Atom::expr([Atom::sym("S"), Atom::Variable(a)])), + bindings.add_var_binding(a.clone(), Atom::expr([Atom::sym("S"), Atom::Variable(a)])), Ok(bind!{ a: expr!("S" a) })); } @@ -1707,7 +1691,7 @@ mod test { let b = VariableAtom::new("b"); let mut bindings = Bindings::new(); bindings.add_var_no_value(&a); - let bindings = bindings.add_var_binding_v2(b.clone(), Atom::expr([Atom::sym("S"), Atom::Variable(a.clone())]))?; + let bindings = bindings.add_var_binding(b.clone(), Atom::expr([Atom::sym("S"), Atom::Variable(a.clone())]))?; let bindings = bindings.add_var_equality(&a, &b); assert_eq!(bindings, Ok(bind!{ b: expr!("S" a), a: expr!(b) })); Ok(()) @@ -1780,13 +1764,13 @@ mod test { let mut atom = expr!(a b c d e); let mut bindings = Bindings::new() .add_var_equality(&VariableAtom::new("a"), &VariableAtom::new("b"))? - .add_var_binding_v2(VariableAtom::new("b"), expr!("B" d))? - .add_var_binding_v2(VariableAtom::new("c"), expr!("C"))? - .add_var_binding_v2(VariableAtom::new("d"), expr!("D"))? + .add_var_binding(VariableAtom::new("b"), expr!("B" d))? + .add_var_binding(VariableAtom::new("c"), expr!("C"))? + .add_var_binding(VariableAtom::new("d"), expr!("D"))? .with_var_no_value(&VariableAtom::new("e")); bindings.apply_and_retain(&mut atom, |v| *v == VariableAtom::new("b") || *v == VariableAtom::new("e")); let expected = Bindings::new() - .add_var_binding_v2(VariableAtom::new("b"), expr!("B" "D"))? + .add_var_binding(VariableAtom::new("b"), expr!("B" "D"))? .with_var_no_value(&VariableAtom::new("e")); assert_eq!(bindings, expected); assert_eq!(atom, expr!(("B" "D") b "C" "D" e)); @@ -1807,8 +1791,8 @@ mod test { #[test] fn bindings_retain_apply_to_self() -> Result<(), &'static str> { let mut bindings = Bindings::new() - .add_var_binding_v2(&VariableAtom::new("y"), expr!((x)))? - .add_var_binding_v2(&VariableAtom::new("x"), sym!("value"))?; + .add_var_binding(&VariableAtom::new("y"), expr!((x)))? + .add_var_binding(&VariableAtom::new("x"), sym!("value"))?; bindings.apply_and_retain(&mut expr!(), |v| *v == VariableAtom::new("y")); assert_eq!(bindings, bind!{ y: expr!(("value")) }); Ok(()) @@ -1819,7 +1803,7 @@ mod test { let mut atom = expr!(b); let mut bindings = Bindings::new() .add_var_equality(&VariableAtom::new("a"), &VariableAtom::new("retained"))? - .add_var_binding_v2(&VariableAtom::new("b"), expr!((a)))?; + .add_var_binding(&VariableAtom::new("b"), expr!((a)))?; bindings.apply_and_retain(&mut atom, |v| *v == VariableAtom::new("retained")); assert_eq!(bindings, bind!{ retained: expr!(retained) }); assert_eq!(atom, expr!((retained))); @@ -1851,9 +1835,9 @@ mod test { fn bindings_into_entries() -> Result<(), &'static str> { let bindings = Bindings::new() .add_var_equality(&VariableAtom::new("x"), &VariableAtom::new("y"))? - .add_var_binding_v2(VariableAtom::new("x"), Atom::sym("Z"))? - .add_var_binding_v2(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("x")]))? - .add_var_binding_v2(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("x")]))?; + .add_var_binding(VariableAtom::new("x"), Atom::sym("Z"))? + .add_var_binding(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("x")]))? + .add_var_binding(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("x")]))?; let entries: Vec<(VariableAtom, Atom)> = bindings.into_vec_of_pairs(); @@ -1870,9 +1854,9 @@ mod test { fn bindings_rename_vars() -> Result<(), &'static str> { let bindings = Bindings::new() .add_var_equality(&VariableAtom::new("x"), &VariableAtom::new("y"))? - .add_var_binding_v2(VariableAtom::new("x"), Atom::sym("Z"))? - .add_var_binding_v2(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("x")]))? - .add_var_binding_v2(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("x")]))?; + .add_var_binding(VariableAtom::new("x"), Atom::sym("Z"))? + .add_var_binding(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("x")]))? + .add_var_binding(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("x")]))?; let map: HashMap = vec![ (VariableAtom::new("x"), VariableAtom::new("z")) @@ -1886,9 +1870,9 @@ mod test { let expected = Bindings::new() .add_var_equality(&VariableAtom::new("z"), &VariableAtom::new("y"))? - .add_var_binding_v2(VariableAtom::new("z"), Atom::sym("Z"))? - .add_var_binding_v2(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("z")]))? - .add_var_binding_v2(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("z")]))?; + .add_var_binding(VariableAtom::new("z"), Atom::sym("Z"))? + .add_var_binding(VariableAtom::new("a"), Atom::expr([Atom::sym("A"), Atom::var("z")]))? + .add_var_binding(VariableAtom::new("b"), Atom::expr([Atom::sym("B"), Atom::var("z")]))?; assert_eq!(renamed, expected); Ok(()) } diff --git a/lib/src/metta/interpreter.rs b/lib/src/metta/interpreter.rs index e879d56c8..d4cb54af6 100644 --- a/lib/src/metta/interpreter.rs +++ b/lib/src/metta/interpreter.rs @@ -640,7 +640,7 @@ fn chain(stack: Stack, bindings: Bindings) -> Vec { panic!("Unexpected state") } }; - let b = Bindings::new().add_var_binding_v2(var, nested).unwrap(); + let b = Bindings::new().add_var_binding(var, nested).unwrap(); let templ = apply_bindings_to_atom_move(templ, &b); vec![InterpretedAtom(atom_to_stack(templ, prev), bindings)] } From d96f9f001f6ab745e8f77252cfb7f98e29893e68 Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Mon, 16 Dec 2024 13:19:41 +0300 Subject: [PATCH 5/8] Remove deprecated Bindings::merge() --- lib/src/atom/matcher.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 6ed24c513..6bfa870dd 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -439,14 +439,14 @@ impl Bindings { /// /// ``` /// use hyperon::*; - /// use hyperon::matcher::Bindings; + /// use hyperon::matcher::{Bindings, BindingsSet}; /// /// let mut binds = bind!{ a: expr!("A") }; /// let mut comp = bind!{ b: expr!("B") }; /// let mut incomp = bind!{ a: expr!("B") }; /// - /// assert_eq!(Bindings::merge(&binds, &comp), Some(bind!{ a: expr!("A"), b: expr!("B") })); - /// assert_eq!(Bindings::merge(&binds, &incomp), None); + /// assert_eq!(binds.clone().merge_v2(&comp), BindingsSet::from(bind!{ a: expr!("A"), b: expr!("B") })); + /// assert_eq!(binds.merge_v2(&incomp), BindingsSet::empty()); /// ``` /// /// TODO: Rename to `merge` when clients have adopted new API @@ -493,11 +493,6 @@ impl Bindings { results } - /// Compatibility shim for merge_v2. TODO: Delete then the new API has been adopted downstream - pub fn merge(a: &Bindings, b: &Bindings) -> Option { - a.clone().merge_v2(b).into_iter().next() - } - fn find_deps<'a>(&'a self, var: &'a VariableAtom, deps: &mut HashSet<&'a VariableAtom>) { if !deps.contains(var) { deps.insert(var); From 4f3ef75ee9d499e1dc87c81c091366e883c05b1f Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Mon, 16 Dec 2024 13:22:09 +0300 Subject: [PATCH 6/8] Rename Bindings::merge_v2() into Bindings::merge() --- c/src/atom.rs | 2 +- lib/src/atom/matcher.rs | 26 ++++++++++++-------------- lib/src/metta/interpreter.rs | 8 ++++---- lib/src/metta/types.rs | 4 ++-- lib/src/space/grounding.rs | 2 +- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/c/src/atom.rs b/c/src/atom.rs index e1767b40f..47c0d9167 100644 --- a/c/src/atom.rs +++ b/c/src/atom.rs @@ -1309,7 +1309,7 @@ pub extern "C" fn bindings_merge(_self: bindings_t, other: *const bindings_t) -> let other = unsafe{ &*other }.borrow(); let owned_self = _self.into_inner(); - let new_set = owned_self.merge_v2(other); + let new_set = owned_self.merge(other); new_set.into() } diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 6bfa870dd..398a67910 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -319,7 +319,7 @@ impl Bindings { fn match_values(&self, current: &Atom, value: &Atom) -> BindingsSet { match_atoms_recursively(current, value).into_iter() - .flat_map(|binding| binding.merge_v2(self)) + .flat_map(|binding| binding.merge(self)) .collect() } @@ -445,12 +445,10 @@ impl Bindings { /// let mut comp = bind!{ b: expr!("B") }; /// let mut incomp = bind!{ a: expr!("B") }; /// - /// assert_eq!(binds.clone().merge_v2(&comp), BindingsSet::from(bind!{ a: expr!("A"), b: expr!("B") })); - /// assert_eq!(binds.merge_v2(&incomp), BindingsSet::empty()); + /// assert_eq!(binds.clone().merge(&comp), BindingsSet::from(bind!{ a: expr!("A"), b: expr!("B") })); + /// assert_eq!(binds.merge(&incomp), BindingsSet::empty()); /// ``` - /// - /// TODO: Rename to `merge` when clients have adopted new API - pub fn merge_v2(self, other: &Bindings) -> BindingsSet { + pub fn merge(self, other: &Bindings) -> BindingsSet { log::trace!("Bindings::merge: {} ^ {}", self, other); let trace_self = match log::log_enabled!(log::Level::Trace) { true => Some(self.clone()), @@ -1036,7 +1034,7 @@ impl BindingsSet { } fn merge_bindings(self, b: &Bindings) -> Self { - self.perform_one_to_many_op(|bindings| bindings.merge_v2(b)) + self.perform_one_to_many_op(|bindings| bindings.merge(b)) } /// Merges each bindings from `other` to each bindings from `self` @@ -1210,7 +1208,7 @@ pub fn apply_bindings_to_bindings(from: &Bindings, to: &Bindings) -> Result //TODO: Delete of this function pending refactor of Interpreter - from.clone().merge_v2(to).into_iter().filter(|bindings| !bindings.has_loops()).next().ok_or(()) + from.clone().merge(to).into_iter().filter(|bindings| !bindings.has_loops()).next().ok_or(()) } /// Checks if atoms are equal up to variables replacement. @@ -1292,25 +1290,25 @@ mod test { #[test] fn bindings_merge_value_conflict() { - assert_eq!(bind!{ a: expr!("A") }.merge_v2( + assert_eq!(bind!{ a: expr!("A") }.merge( &bind!{ a: expr!("C"), b: expr!("B") }), BindingsSet::empty()); - assert_eq!(bind!{ a: expr!("C"), b: expr!("B") }.merge_v2( + assert_eq!(bind!{ a: expr!("C"), b: expr!("B") }.merge( &bind!{ a: expr!("A") }), BindingsSet::empty()); } #[test] fn bindings_merge() { - assert_eq!(bind!{ a: expr!("A") }.merge_v2( + assert_eq!(bind!{ a: expr!("A") }.merge( &bind!{ a: expr!("A"), b: expr!("B") }), bind_set![{ a: expr!("A"), b: expr!("B") }]); - assert_eq!(bind!{ a: expr!("A"), b: expr!("B") }.merge_v2( + assert_eq!(bind!{ a: expr!("A"), b: expr!("B") }.merge( &bind!{ a: expr!("A") }), bind_set![{ a: expr!("A"), b: expr!("B") }]); } #[test] fn bindings_merge_self_recursion() { - assert_eq!(bind!{ a: expr!(b) }.merge_v2( + assert_eq!(bind!{ a: expr!(b) }.merge( &bind!{ b: expr!("S" b) }), bind_set![{ a: expr!(b), b: expr!("S" b) }]); } @@ -1737,7 +1735,7 @@ mod test { let a = bind!{ a: expr!({ assigner }), b: expr!({ assigner }) }; let b = bind!{ a: expr!(x "C" "D"), b: expr!(y "E" "F") }; - let bindings = a.merge_v2(&b); + let bindings = a.merge(&b); assert_eq!(bindings, bind_set![ bind!{ a: expr!({ assigner }), b: expr!({ assigner }), x: expr!("C"), y: expr!("E") }, diff --git a/lib/src/metta/interpreter.rs b/lib/src/metta/interpreter.rs index d4cb54af6..1b81b8d23 100644 --- a/lib/src/metta/interpreter.rs +++ b/lib/src/metta/interpreter.rs @@ -567,7 +567,7 @@ fn query<'a, T: Space>(space: T, prev: Option>>, to_eval: Atom let result = |res, bindings| eval_result(prev.clone(), res, &call_stack, bindings); let results: Vec = results.into_iter().flat_map(|b| { log::debug!("interpreter::query: b: {}", b); - b.merge_v2(&bindings).into_iter() + b.merge(&bindings).into_iter() }).filter_map(move |b| { b.resolve(&var_x).map_or(None, |res| { if b.has_loops() { @@ -760,7 +760,7 @@ fn unify(stack: Stack, bindings: Bindings) -> Vec { }; let bindings_ref = &bindings; let matches: Vec = matches.into_iter().flat_map(move |b| { - b.merge_v2(bindings_ref).into_iter().filter_map(move |b| { + b.merge(bindings_ref).into_iter().filter_map(move |b| { if b.has_loops() { None } else { @@ -842,7 +842,7 @@ fn superpose_bind(stack: Stack, bindings: Bindings) -> Vec { let stack = Stack::finished(prev.clone(), atom); InterpretedAtom(stack, bindings) }; - b.merge_v2(&bindings).into_iter().filter_map(move |b| { + b.merge(&bindings).into_iter().filter_map(move |b| { if b.has_loops() { None } else { @@ -989,7 +989,7 @@ fn match_types(type1: &Atom, type2: &Atom, bindings: Bindings) -> Result], meta: &[Vec], expected: &[Atom], for typ in actual { result_bindings.extend( match_reducted_types_v2(typ, expected) - .flat_map(|b| b.merge_v2(&bindings)) + .flat_map(|b| b.merge(&bindings)) .flat_map(|b| check_arg_types(actual_tail, meta_tail, expected_tail, b)) ); } @@ -347,7 +347,7 @@ pub fn match_reducted_types(left: &Atom, right: &Atom, bindings: &mut Bindings) let matched = match result.len() { 0 => false, 1 => { - let result_set = result.pop().unwrap().merge_v2(bindings); + let result_set = result.pop().unwrap().merge(bindings); *bindings = result_set.try_into().expect("Single result is expected because custom matching for types is not supported yet!"); true } diff --git a/lib/src/space/grounding.rs b/lib/src/space/grounding.rs index 862da5ada..783a9bee9 100644 --- a/lib/src/space/grounding.rs +++ b/lib/src/space/grounding.rs @@ -259,7 +259,7 @@ impl GroundingSpace { let query = matcher::apply_bindings_to_atom_move(query.clone(), &prev); let mut res = self.query(&query); res.drain(0..) - .flat_map(|next| next.merge_v2(&prev)) + .flat_map(|next| next.merge(&prev)) .collect() }).collect() }; From c584c71e7ad4fae98913badada112f52d7c1fc27 Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Mon, 16 Dec 2024 14:23:35 +0300 Subject: [PATCH 7/8] Remove redundant match_result_product() function --- lib/examples/custom_match.rs | 9 +++++---- lib/src/atom/matcher.rs | 10 ---------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/examples/custom_match.rs b/lib/examples/custom_match.rs index d3cc34516..27dbe2bdf 100644 --- a/lib/examples/custom_match.rs +++ b/lib/examples/custom_match.rs @@ -36,14 +36,15 @@ impl Grounded for TestDict { impl CustomMatch for TestDict { fn match_(&self, other: &Atom) -> MatchResultIter { if let Some(other) = other.as_gnd::() { - other.0.iter().map(|(ko, vo)| { + Box::new(other.0.iter().map(|(ko, vo)| { self.0.iter().map(|(k, v)| { match_atoms(&Atom::expr(vec![k.clone(), v.clone()]), &Atom::expr(vec![ko.clone(), vo.clone()])) }).fold(Box::new(std::iter::empty()) as MatchResultIter, |acc, i| { Box::new(acc.chain(i)) - }) - }).fold(Box::new(std::iter::once(Bindings::new())), - |acc, i| { matcher::match_result_product(acc, i) }) + }).collect::() + }).fold(BindingsSet::single(), + |acc, i| { acc.merge(&i) }) + .into_iter()) } else { Box::new(std::iter::empty()) } diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 398a67910..75a9dc120 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -1134,16 +1134,6 @@ fn match_atoms_recursively(left: &Atom, right: &Atom) -> BindingsSet { res } -//TODO: This function is redundant, as the functionality is subsumed by BindingsSet::merge -/// Merges each bindings from `prev` iter to each bindings from `next` -/// iter. The result is an iter over successfully merged bindings. -pub fn match_result_product(prev: MatchResultIter, next: MatchResultIter) -> MatchResultIter { - let next: BindingsSet = next.collect(); - let prev: BindingsSet = prev.collect(); - log::trace!("match_result_product_iter, next: {:?}", next); - Box::new(prev.merge(&next).into_iter()) -} - /// Applies bindings to atom and return it (see [apply_bindings_to_atom_mut]). #[inline] pub fn apply_bindings_to_atom_move(mut atom: Atom, bindings: &Bindings) -> Atom { From f0d36a19da0d92a87603961ece54dd723b62bc4a Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Mon, 16 Dec 2024 14:25:21 +0300 Subject: [PATCH 8/8] Remove redundant apply_bindings_to_bindings() function --- lib/src/atom/matcher.rs | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/lib/src/atom/matcher.rs b/lib/src/atom/matcher.rs index 75a9dc120..aec13263b 100644 --- a/lib/src/atom/matcher.rs +++ b/lib/src/atom/matcher.rs @@ -1174,33 +1174,6 @@ pub fn apply_bindings_to_atom_mut(atom: &mut Atom, bindings: &Bindings) { } } -/// Applies bindings `from` to the each value from bindings `to`. -/// Function also checks that resulting value is not expressed recursively -/// via variable to which value is bound. Function returns error if such -/// value is detected. -/// -/// # Examples -/// -/// ``` -/// use hyperon::*; -/// use hyperon::atom::matcher::apply_bindings_to_bindings; -/// -/// let from = bind!{ x: expr!("Y") }; -/// let to = bind!{ y: expr!(x) }; -/// let rec = bind!{ x: expr!(y) }; -/// let _loop = bind!{ x: expr!((y)) }; -/// -/// assert_eq!(apply_bindings_to_bindings(&from, &to), Ok(bind!{ y: expr!("Y"), x: expr!(y) })); -/// assert_eq!(apply_bindings_to_bindings(&rec, &to), Ok(bind!{ y: expr!(x) })); -/// assert_eq!(apply_bindings_to_bindings(&_loop, &to), Err(())); -/// ``` -pub fn apply_bindings_to_bindings(from: &Bindings, to: &Bindings) -> Result { - // TODO: apply_bindings_to_bindings can be replaced by Bindings::merge, - // when Bindings::merge are modified to return Vec - //TODO: Delete of this function pending refactor of Interpreter - from.clone().merge(to).into_iter().filter(|bindings| !bindings.has_loops()).next().ok_or(()) -} - /// Checks if atoms are equal up to variables replacement. /// /// # Examples