89e1f20975
Fixed #130 : ArithmeticOperatorParser Fixed #129 : python_wrapper : create_namespace Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
737 lines
31 KiB
Python
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)
|