import pytest from core.builtin_concepts_ids import BuiltinConcepts from core.concept import Concept, DEFINITION_TYPE_DEF from core.sheerka.services.SheerkaExecute import ParserInput from evaluators.PythonEvaluator import PythonEvaluator from parsers.BaseParser import ErrorSink from parsers.ExpressionParser import ExpressionParser from parsers.FunctionParser import FunctionParser from parsers.ListComprehensionParser import ListComprehensionParser from parsers.PythonParser import PythonNode from sheerkapython.ExprToPython import PythonExprVisitor from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestPythonExprVisitor(TestUsingMemoryBasedSheerka): @staticmethod def get_expr_node(context, expression, parser=None): parser = parser or ExpressionParser(old_style=False) error_sink = ErrorSink() parser_input = ParserInput(expression) parser.reset_parser_input(parser_input, error_sink) parsed = parser.parse_input(context, parser_input, error_sink) assert not error_sink.has_error return parsed @staticmethod def eval(context, return_value, namespace=None): evaluator = PythonEvaluator() assert evaluator.matches(context, return_value) if namespace: for k, v in namespace.items(): context.add_to_short_term_memory(k, v) res = evaluator.eval(context, return_value) assert res.status return res.body @pytest.mark.parametrize("expression, source, objects", [ ("foo w", "call_concept(__o_00__, x=w)", {"__o_00__": "foo"}), ("foo z + 2", "call_concept(__o_00__, x=z + 2)", {"__o_00__": "foo"}), ("foo a and bar b", "call_concept(__o_00__, x=a) and call_concept(__o_01__, y=b)", {"__o_00__": "foo", "__o_01__": "bar"}), ("foo a or bar b", "call_concept(__o_00__, x=a) or call_concept(__o_01__, y=b)", {"__o_00__": "foo", "__o_01__": "bar"}), ("not foo w", "not (call_concept(__o_00__, x=w))", {"__o_00__": "foo"}), ("foo a >= bar b", "call_concept(__o_00__, x=a) >= call_concept(__o_01__, y=b)", {"__o_00__": "foo", "__o_01__": "bar"}), ("function(foo a, bar b)", "function(call_concept(__o_00__, x=a), call_concept(__o_01__, y=b))", {"__o_00__": "foo", "__o_01__": "bar"}), ("set_isa(one, number)", "set_isa(__o_00__, __o_01__)", {"__o_00__": "one", "__o_01__": "number"}), ("set_isa(twenty two, number)", "set_isa(__o_00__, __o_01__)", {"__o_00__": "twenties", "__o_01__": "number"}), ("foo and twenty one", "__o_00__ and __o_01__", {"__o_00__": "foo", "__o_01__": "twenties"}), ("func(z) is a 'foo'", "call_concept(__o_00__, x=func(z))", {"__o_00__": "isa"}), ("isinstance('hello', str)", "isinstance('hello', str)", {}), ("not (a and b)", "not (a and b)", {}), ("twenty one is a number", "__o_00__", {"__o_00__": "isa"}), ("x is a number", "call_concept(__o_00__, x=x)", {"__o_00__": "isa"}), ("y is a number", "call_concept(__o_00__, x=y)", {"__o_00__": "isa"}), ("number is a x", "call_concept(__o_00__, y=x)", {"__o_00__": "isa"}), ("number is a y", "call_concept(__o_00__, y=y)", {"__o_00__": "isa"}), ("x is a y", "__o_00__", {"__o_00__": "isa"}), ("foo x + 1", "call_concept(__o_00__, x=x + 1)", {"__o_00__": "foo"}), ("twenty two + 3", "__o_00__ + 3", {"__o_00__": "twenties"}), ("twenty two * 2 - 1", "__o_00__ * 2 - 1", {"__o_00__": "twenties"}), ("x * bar a + 2", "x * call_concept(__o_00__, y=a + 2)", {"__o_00__": "bar"}), ("foo x * bar a + 2", "call_concept(__o_01__, x=x * call_concept(__o_00__, y=a + 2))", {"__o_00__": "bar", "__o_01__": "foo"}), ("(foo y) * (bar a) + 2", "call_concept(__o_00__, x=y) * call_concept(__o_01__, y=a) + 2", {"__o_00__": "foo", "__o_01__": "bar"}), ("func([one, two])", "func([__o_00__, __o_01__])", {"__o_00__": "one", "__o_01__": "two"}), ("func([twenty one, two])", "func([__o_00__, __o_01__])", {"__o_00__": "twenties", "__o_01__": "two"}), ("func((twenty one, two))", "func((__o_00__, __o_01__))", {"__o_00__": "twenties", "__o_01__": "two"}), ("func({twenty one, two})", "func({__o_00__, __o_01__})", {"__o_00__": "twenties", "__o_01__": "two"}), ("foo twenty one + self", "call_concept(__o_01__, x=__o_00__ + self)", {"__o_01__": "foo", "__o_00__": "twenties"}), ]) def test_i_can_compile_concept_when_is_question_is_false(self, expression, source, objects): sheerka, context, foo, bar, isa, one, two, twenties, number = self.init_test().with_concepts( Concept("foo", definition="foo x", definition_type=DEFINITION_TYPE_DEF, body="x").def_var("x"), Concept("bar y", body="y").def_var("y"), Concept("x is a y").def_var("x").def_var("y"), Concept("one", body="1"), Concept("two", body="2"), Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"), Concept("number"), create_new=True ).unpack() concepts = { "foo": foo, "bar": bar, "isa": isa, "one": one, "two": two, "twenties": twenties, "number": number } node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == source assert len(objects) == len(python_node.objects) for obj_name, obj_value in objects.items(): assert obj_name in python_node.objects obj = python_node.objects[obj_name] if isinstance(obj, Concept): assert sheerka.isinstance(obj, concepts[obj_value]) assert obj.get_hints().use_copy # assert obj.get_hints().is_evaluated else: assert False @pytest.mark.parametrize("expression, source, objects", [ ("foo w", "evaluate_question(__o_00__, x=w)", {"__o_00__": "foo"}), ("foo z + 2", "evaluate_question(__o_00__, x=z + 2)", {"__o_00__": "foo"}), ]) def test_i_can_compile_concept_when_is_question_is_true(self, expression, source, objects): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x", body="x", pre="is_question()").def_var("x"), create_new=True ).unpack() concepts = { "foo": foo } node = self.get_expr_node(context, expression) context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == source for obj_name, obj_value in objects.items(): assert obj_name in python_node.objects obj = python_node.objects[obj_name] if isinstance(obj, Concept): assert sheerka.isinstance(obj, concepts[obj_value]) assert obj.get_hints().use_copy assert obj.get_hints().is_evaluated else: assert False @pytest.mark.parametrize("expression, expected", [ ("foo w", [ ("call_concept(__o_00__, x=w)", {"__o_00__": "foo1"}), ("call_concept(__o_01__, y=w)", {"__o_01__": "foo2"}) ]), ("foo z + 2", [ ("call_concept(__o_00__, x=z + 2)", {"__o_00__": "foo1"}), ("call_concept(__o_01__, y=z + 2)", {"__o_01__": "foo2"}), ]), ("foo bar a + 2", [ ("call_concept(__o_00__, x=call_concept(__o_01__, x=a + 2))", {"__o_00__": "foo1", "__o_01__": "bar1"}), ("call_concept(__o_02__, y=call_concept(__o_03__, x=a + 2))", {"__o_02__": "foo2", "__o_03__": "bar1"}), ("call_concept(__o_04__, y=call_concept(__o_05__, y=a + 2))", {"__o_04__": "foo2", "__o_05__": "bar2"}), ("call_concept(__o_06__, x=call_concept(__o_07__, y=a + 2))", {"__o_06__": "foo1", "__o_07__": "bar2"}), ]), ]) def test_i_can_compile_when_multiple_concept_are_possible(self, expression, expected): sheerka, context, foo1, foo2, bar1, bar2, = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x"), Concept("foo y", body="y").def_var("y"), Concept("bar x", body="x").def_var("x"), Concept("bar y", body="y").def_var("y"), create_new=True ).unpack() concepts = { "foo1": foo1, "foo2": foo2, "bar1": bar1, "bar2": bar2 } node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == len(expected) for ret, (source, objects) in zip(ret, expected): python_node = ret.body.body assert python_node.original_source == expression assert python_node.source == source for obj_name, obj_value in objects.items(): assert obj_name in python_node.objects obj = python_node.objects[obj_name] if isinstance(obj, Concept): assert sheerka.isinstance(obj, concepts[obj_value]) assert obj.get_hints().use_copy assert obj.get_hints().is_evaluated else: assert False def test_i_can_compile_simple_list_comprehension(self): sheerka, context = self.init_test().unpack() expression = "[ x for x in ['a', 'b'] if x == 'a' ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == expression assert self.eval(context, ret[0]) == ["a"] def test_i_can_compile_simple_list_comprehension_when_no_if(self): sheerka, context = self.init_test().unpack() expression = "[ x for x in ['a', 'b'] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == expression assert self.eval(context, ret[0]) == ['a', 'b'] def test_i_can_compile_list_comprehension_when_element_is_a_concept(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x") ).unpack() expression = "[ foo w for w in ['a', 'b'] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_00__, x=w) for w in ['a', 'b'] ]" assert "__o_00__" in python_node.objects concept = python_node.objects["__o_00__"] assert sheerka.isinstance(concept, foo) assert concept.get_hints().use_copy assert concept.get_hints().is_evaluated assert self.eval(context, ret[0]) == ["a", "b"] def test_i_can_compile_list_comprehension_when_element_is_a_concept_using_bnf(self): sheerka, context, one, two, twenties, foo = self.init_test().with_concepts( Concept("one", body="1"), Concept("two", body="2"), Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"), Concept("foo x y", body="{x, y}").def_var("x").def_var("y"), create_new=True, ).unpack() expression = "[ foo x twenty one for x in ['a', 'b'] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_00__, x=x) for x in ['a', 'b'] ]" assert "__o_00__" in python_node.objects concept = python_node.objects["__o_00__"] assert sheerka.isinstance(concept, foo) assert concept.get_hints().use_copy assert concept.get_hints().is_evaluated twenty_one = self.evaluate_from_source(context, "twenty one") assert self.eval(context, ret[0]) == [{"a", twenty_one}, {"b", twenty_one}] def test_i_can_compile_list_comprehension_when_concept_with_complex_parameter(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x"), create_new=True ).unpack() expression = "[ foo w + 1 for w in [1, 2] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_00__, x=w + 1) for w in [1, 2] ]" assert "__o_00__" in python_node.objects assert self.eval(context, ret[0]) == [2, 3] def test_i_can_compile_list_comprehension_when_iter_is_a_concept(self): sheerka, context, red, blue, color, foo = self.init_test().with_concepts( "red", "blue", "color", Concept("foo x", body="x").def_var("x") ).unpack() global_truth_context = self.get_context(sheerka, global_truth=True) sheerka.set_isa(global_truth_context, red, color) sheerka.set_isa(global_truth_context, blue, color) expression = "[ foo x for x in colors ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_01__, x=x) for x in __o_00__ ]" assert "__o_00__" in python_node.objects assert "__o_01__" in python_node.objects concept0 = python_node.objects["__o_01__"] assert sheerka.isinstance(concept0, foo) assert concept0.get_hints().use_copy assert concept0.get_hints().is_evaluated concept1 = python_node.objects["__o_00__"] assert sheerka.isinstance(concept1, "colors") assert set(self.eval(context, ret[0])) == {red, blue} def test_i_can_compile_list_comprehension_when_target_is_the_name_of_a_concept_concept(self): sheerka, context, red, blue, color, foo = self.init_test().with_concepts( "red", "blue", "color", Concept("foo x", body="x").def_var("x") ).unpack() global_truth_context = self.get_context(sheerka, global_truth=True) sheerka.set_isa(global_truth_context, red, color) sheerka.set_isa(global_truth_context, blue, color) expression = "[ foo color for color in colors ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_01__, x=color) for color in __o_00__ ]" assert "__o_00__" in python_node.objects assert "__o_01__" in python_node.objects concept0 = python_node.objects["__o_01__"] assert sheerka.isinstance(concept0, foo) assert concept0.get_hints().use_copy assert concept0.get_hints().is_evaluated concept1 = python_node.objects["__o_00__"] assert sheerka.isinstance(concept1, "colors") assert set(self.eval(context, ret[0])) == {red, blue} def test_i_can_compile_list_comprehension_when_if_expression_is_a_concept(self): sheerka, context, red, blue, color, foo, startswith = self.init_test().with_concepts( "red", "blue", "color", Concept("foo x", body="x").def_var("x"), Concept("x starts with y", body="x.name.startswith(y)", pre="is_question()").def_var("x").def_var("y"), create_new=True ).unpack() global_truth_context = self.get_context(sheerka, global_truth=True) sheerka.set_isa(global_truth_context, red, color) sheerka.set_isa(global_truth_context, blue, color) expression = "[ foo x for x in colors if x starts with 'b' ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_02__, x=x) for x in __o_00__ if evaluate_question(__o_01__, x=x) ]" assert "__o_00__" in python_node.objects assert "__o_01__" in python_node.objects assert "__o_02__" in python_node.objects assert visitor.obj_counter == 3 assert set(self.eval(context, ret[0])) == {blue} def test_i_can_compile_list_comprehension_when_multiple_concepts(self): sheerka, context, foo1, foo2, bar1, bar2, colors1, colors2, = self.init_test().with_concepts( Concept("foo x").def_var("x"), Concept("foo y", ).def_var("y"), Concept("bar x", pre="is_question()").def_var("x"), Concept("bar y", pre="is_question()").def_var("y"), Concept("colors", body="[1]"), Concept("colors", body="[2]"), ).unpack() expression = "[ foo a for a in colors if bar a ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 8 python_node = ret[0].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == '[ call_concept(__o_04__, x=a) for a in __o_00__ if evaluate_question(__o_02__, x=a) ]' assert object_to_compare == {"__o_04__": "foo x", "__o_00__": "colors", "__o_02__": "bar x"} # ... python_node = ret[7].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == '[ call_concept(__o_05__, y=a) for a in __o_01__ if evaluate_question(__o_03__, y=a) ]' assert object_to_compare == {"__o_05__": "foo y", "__o_01__": "colors", "__o_03__": "bar y"} def test_i_can_compile_list_comprehension_when_missing_concept_parameter(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x y", body="x").def_var("x").def_var("y") ).unpack() expression = "[ foo x k for x in ['a', 'b'] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == "[ call_concept(__o_00__, x=x, y=k) for x in ['a', 'b'] ]" assert object_to_compare == {"__o_00__": "foo x y"} def test_i_can_compile_list_comprehension_when_multiple_for(self): sheerka, context = self.init_test().unpack() expression = "[ (x, y) for x in ['a', 'b'] if x == 'a' for y in ['c', 'd'] if y == 'c' ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == expression assert self.eval(context, ret[0]) == [("a", "c")] def test_i_can_compile_list_comprehension_when_element_is_missing_its_parenthesis(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x") ).unpack() expression = "[ w, foo w for w in ['a', 'b'] ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ (w, call_concept(__o_00__, x=w)) for w in ['a', 'b'] ]" assert "__o_00__" in python_node.objects concept = python_node.objects["__o_00__"] assert sheerka.isinstance(concept, foo) assert concept.get_hints().use_copy assert concept.get_hints().is_evaluated assert self.eval(context, ret[0]) == [("a", "a"), ("b", "b")] def test_i_can_compile_list_comprehension_when_multiple_targets(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x y", body="(x, y)").def_var("x").def_var("y") ).unpack() items = {"one": 1, "two": 2} sheerka.add_to_short_term_memory(None, "items", items) expression = "[ foo x y for x, y in items.items() ]" node = self.get_expr_node(context, expression, parser=ListComprehensionParser()) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 assert sheerka.isinstance(ret[0], BuiltinConcepts.RETURN_VALUE) assert sheerka.isinstance(ret[0].body, BuiltinConcepts.PARSER_RESULT) assert isinstance(ret[0].body.body, PythonNode) python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "[ call_concept(__o_00__, x=x, y=y) for x, y in items.items() ]" assert "__o_00__" in python_node.objects concept0 = python_node.objects["__o_00__"] assert sheerka.isinstance(concept0, foo) assert concept0.get_hints().use_copy assert concept0.get_hints().is_evaluated assert self.eval(context, ret[0]) == [("one", 1), ("two", 2)] def test_i_can_compile_when_multiple_results(self): sheerka, context, foo, foo2, bar, bar2 = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x"), Concept("foo y", body="y").def_var("y"), Concept("bar x", body="x").def_var("x"), Concept("bar y", body="y").def_var("y"), create_new=True ).unpack() node = self.get_expr_node(context, "foo a and bar b") visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 4 python_node = ret[0].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == 'call_concept(__o_00__, x=a) and call_concept(__o_02__, x=b)' assert object_to_compare == {"__o_00__": "foo x", "__o_02__": "bar x"} python_node = ret[1].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == 'call_concept(__o_00__, x=a) and call_concept(__o_03__, y=b)' assert object_to_compare == {"__o_00__": "foo x", "__o_03__": "bar y"} python_node = ret[2].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == 'call_concept(__o_01__, y=a) and call_concept(__o_02__, x=b)' assert object_to_compare == {"__o_01__": "foo y", "__o_02__": "bar x"} python_node = ret[3].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == 'call_concept(__o_01__, y=a) and call_concept(__o_03__, y=b)' assert object_to_compare == {"__o_01__": "foo y", "__o_03__": "bar y"} def test_i_can_compile_function_of_function(self): sheerka, context, one, two = self.init_test().with_concepts( Concept("one"), Concept("two"), ).unpack() expression = "func(func1(func2(one, two)), 'foo')" node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "func(func1(func2(__o_00__, __o_01__)), 'foo')" def test_i_can_compile_function_when_keyword_parameters(self): sheerka, context, foo = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x")).unpack() def func(**kwargs): # Uncomment to test that PythonEvalutor tests until success # if not isinstance(kwargs["y"], str): # raise Exception() return kwargs sheerka.add_to_short_term_memory(None, "func", func) expression = "func(x=5, y=foo 'a')" node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "func(x=5, y=__o_00__)" assert python_node.objects["__o_00__"].name == "foo x" res = self.eval(context, ret[0]) assert res["x"] == 5 assert sheerka.isinstance(res["y"], foo) assert res["y"].body == "a" def test_i_can_compile_function_when_keyword_parameters_and_multiple_results(self): sheerka, context, foo, foo2, bar, bar2 = self.init_test().with_concepts( Concept("foo x", body="x").def_var("x"), Concept("foo y", body="y").def_var("y"), Concept("bar x", body="x").def_var("x"), Concept("bar y", body="y").def_var("y"), create_new=True ).unpack() def func(**kwargs): return kwargs sheerka.add_to_short_term_memory(None, "func", func) expression = "func(foo 'a', y=bar 'b')" node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 4 python_node = ret[0].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == "func(__o_00__, y=__o_02__)" assert object_to_compare == {"__o_00__": "foo x", "__o_02__": "bar x"} # ... python_node = ret[3].body.body object_to_compare = {k: v.name for k, v in python_node.objects.items()} assert python_node.source == "func(__o_01__, y=__o_03__)" assert object_to_compare == {"__o_01__": "foo y", "__o_03__": "bar y"} def test_i_can_compile_sequence_with_function_call(self): sheerka, context, foo, bar = self.init_test().with_concepts( Concept("foo x", body="f'x={x}'").def_var("x"), Concept("x bar", body="x").def_var("x"), create_new=True ).unpack() def func(x): return x + 1 sheerka.add_to_short_term_memory(None, "func", func) expression = "foo func(self)" node = self.get_expr_node(context, expression, parser=FunctionParser(strict=False)) visitor = PythonExprVisitor(context) ret = visitor.compile(node) assert len(ret) == 1 python_node = ret[0].body.body assert python_node.original_source == expression assert python_node.source == "call_concept(__o_00__, x=func(self))" assert python_node.objects["__o_00__"].name == "foo x" assert self.eval(context, ret[0], {"self": 1}) == "x=2" def test_i_cannot_compile_function_when_invalid_keyword_parameters(self): sheerka, context = self.init_test().unpack() expression = "func(x=5=2)" node = self.get_expr_node(context, expression) visitor = PythonExprVisitor(context) with pytest.raises(SyntaxError): visitor.compile(node)