Files
Sheerka-Old/tests/sheerkapython/test_PythonExprVisitor.py
T
kodjo 89e1f20975 Fixed #131 : Implement ExprToConditions
Fixed #130 : ArithmeticOperatorParser
Fixed #129 : python_wrapper : create_namespace
Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
2021-10-13 16:06:57 +02:00

737 lines
31 KiB
Python

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)