From 5951bd365453f629b79418b8453a4ec1184a3041 Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Tue, 16 Apr 2024 16:43:31 +0300 Subject: [PATCH 1/2] Fix variable_operation feature to support nested expressions --- lib/src/metta/interpreter_minimal.rs | 26 ++++++++++++++++++++------ lib/src/metta/old_interpreter.rs | 10 ++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/src/metta/interpreter_minimal.rs b/lib/src/metta/interpreter_minimal.rs index 0aeec87df..8097fde52 100644 --- a/lib/src/metta/interpreter_minimal.rs +++ b/lib/src/metta/interpreter_minimal.rs @@ -517,12 +517,16 @@ fn call_to_stack(call: Atom, vars: Variables, prev: Option>>) #[cfg(not(feature = "variable_operation"))] fn is_variable_op(atom: &Atom) -> bool { match atom { - Atom::Expression(expr) => { - match expr.children().get(0) { - Some(Atom::Variable(_)) => true, - _ => false, - } - }, + Atom::Expression(expr) => is_variable_op_expr(expr), + _ => false, + } +} + +#[cfg(not(feature = "variable_operation"))] +fn is_variable_op_expr(expr: &ExpressionAtom) -> bool { + match expr.children().get(0) { + Some(Atom::Variable(_)) => true, + Some(Atom::Expression(expr)) => is_variable_op_expr(expr), _ => false, } } @@ -1486,6 +1490,16 @@ mod tests { assert_eq!(result[0], sym!("value")); } + #[test] + fn interpret_atom_evaluate_variable_operation_nested() { + let space = space("(= ((baz $a) $b) ($a $b))"); + let result = call_interpret(&space, &metta_atom("(eval (($a A) B))")); + #[cfg(feature = "variable_operation")] + assert_eq!(result, vec![metta_atom("(A B)")]); + #[cfg(not(feature = "variable_operation"))] + assert_eq!(result, vec![NOT_REDUCIBLE_SYMBOL]); + } + #[test] fn interpret_atom_chain_incorrect_args() { diff --git a/lib/src/metta/old_interpreter.rs b/lib/src/metta/old_interpreter.rs index 7f00b1e7c..c451d2700 100644 --- a/lib/src/metta/old_interpreter.rs +++ b/lib/src/metta/old_interpreter.rs @@ -317,6 +317,7 @@ fn is_grounded_op(expr: &ExpressionAtom) -> bool { fn is_variable_op(expr: &ExpressionAtom) -> bool { match expr.children().get(0) { Some(Atom::Variable(_)) => true, + Some(Atom::Expression(expr)) => is_variable_op(expr), _ => false, } } @@ -1126,5 +1127,14 @@ mod tests { #[cfg(not(feature = "variable_operation"))] assert_eq!(actual, vec![expr!(op "arg")]); } + + #[cfg(not(feature = "variable_operation"))] + #[test] + fn interpret_match_variable_operation_nested() { + let mut space = GroundingSpace::new(); + space.add(expr!("=" (("baz" x) y) ("baz result" x y))); + let actual = interpret(&space, &expr!((op "arg1") "arg2")).unwrap(); + assert_eq!(actual, vec![expr!((op "arg1") "arg2")]); + } } From 0e261f47fdc4022236fae5714c2892a7949d54af Mon Sep 17 00:00:00 2001 From: Vitaly Bogdanov Date: Tue, 16 Apr 2024 17:01:39 +0300 Subject: [PATCH 2/2] Fix unit tests to pass when variable_operation feature is enabled --- lib/src/metta/runner/stdlib.rs | 14 +++++++------- lib/src/metta/runner/stdlib_minimal.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/src/metta/runner/stdlib.rs b/lib/src/metta/runner/stdlib.rs index c4b90ff0d..4bc7714dd 100644 --- a/lib/src/metta/runner/stdlib.rs +++ b/lib/src/metta/runner/stdlib.rs @@ -2407,8 +2407,8 @@ mod tests { fn let_op_keep_variables_equalities_issue290() { assert_eq_metta_results!(run_program("!(let* (($f f) ($f $x)) $x)"), Ok(vec![vec![expr!("f")]])); assert_eq_metta_results!(run_program("!(let* (($f $x) ($f f)) $x)"), Ok(vec![vec![expr!("f")]])); - assert_eq_metta_results!(run_program("!(let ($x $x) ($z $y) (let $y A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]])); - assert_eq_metta_results!(run_program("!(let ($x $x) ($z $y) (let $z A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]])); + assert_eq_metta_results!(run_program("!(let (quote ($x $x)) (quote ($z $y)) (let $y A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]])); + assert_eq_metta_results!(run_program("!(let (quote ($x $x)) (quote ($z $y)) (let $z A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]])); } #[test] @@ -2524,11 +2524,11 @@ mod tests { #[test] fn sealed_op_runner() { - let nested = run_program("!(sealed ($x) (sealed ($a $b) (= ($a $x $c) ($b))))"); - let simple_replace = run_program("!(sealed ($x $y) (= ($y) ($z)))"); + let nested = run_program("!(sealed ($x) (sealed ($a $b) (quote (= ($a $x $c) ($b)))))"); + let simple_replace = run_program("!(sealed ($x $y) (quote (= ($y $z))))"); - assert!(crate::atom::matcher::atoms_are_equivalent(&nested.unwrap()[0][0], &expr!("="(a b c) (z)))); - assert!(crate::atom::matcher::atoms_are_equivalent(&simple_replace.unwrap()[0][0], &expr!("="(y) (z)))); + assert!(crate::atom::matcher::atoms_are_equivalent(&nested.unwrap()[0][0], &expr!("quote" ("=" (a b c) (z))))); + assert!(crate::atom::matcher::atoms_are_equivalent(&simple_replace.unwrap()[0][0], &expr!("quote" ("=" (y z))))); } #[test] @@ -2540,7 +2540,7 @@ mod tests { #[test] fn use_sealed_to_make_scoped_variable() { assert_eq!(run_program("!(let $x (input $x) (output $x))"), Ok(vec![vec![expr!("output" ("input" x))]])); - assert_eq!(run_program("!(let ($sv $st) (sealed ($x) ($x (output $x))) + assert_eq!(run_program("!(let (quote ($sv $st)) (sealed ($x) (quote ($x (output $x)))) (let $sv (input $x) $st))"), Ok(vec![vec![expr!("output" ("input" x))]])); } diff --git a/lib/src/metta/runner/stdlib_minimal.rs b/lib/src/metta/runner/stdlib_minimal.rs index f11fffd08..cee8e71ef 100644 --- a/lib/src/metta/runner/stdlib_minimal.rs +++ b/lib/src/metta/runner/stdlib_minimal.rs @@ -597,7 +597,7 @@ mod tests { #[test] fn metta_cdr_atom() { assert_eq!(run_program(&format!("!(cdr-atom (a b c))")), Ok(vec![vec![expr!("b" "c")]])); - assert_eq!(run_program(&format!("!(cdr-atom ($a $b $c))")), Ok(vec![vec![expr!(b c)]])); + assert_eq!(run_program(&format!("!(cdr-atom ($a b $c))")), Ok(vec![vec![expr!("b" c)]])); assert_eq!(run_program(&format!("!(cdr-atom ())")), Ok(vec![vec![expr!("Error" ("cdr-atom" ()) {Str::from_str("cdr-atom expects a non-empty expression as an argument")})]])); assert_eq!(run_program(&format!("!(cdr-atom a)")), Ok(vec![vec![expr!("Error" ("cdr-atom" "a") {Str::from_str("cdr-atom expects a non-empty expression as an argument")})]])); assert_eq!(run_program(&format!("!(cdr-atom $a)")), Ok(vec![vec![expr!("Error" ("cdr-atom" a) {Str::from_str("cdr-atom expects a non-empty expression as an argument")})]])); @@ -1052,7 +1052,7 @@ mod tests { #[test] fn use_sealed_to_make_scoped_variable() { assert_eq!(run_program("!(let $x (input $x) (output $x))"), Ok(vec![vec![]])); - assert_eq!(run_program("!(let ($sv $st) (sealed ($x) ($x (output $x))) + assert_eq!(run_program("!(let (quote ($sv $st)) (sealed ($x) (quote ($x (output $x)))) (let $sv (input $x) $st))"), Ok(vec![vec![expr!("output" ("input" x))]])); }