Fixed #131 : Implement ExprToConditions
Fixed #130 : ArithmeticOperatorParser Fixed #129 : python_wrapper : create_namespace Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
This commit is contained in:
@@ -0,0 +1,500 @@
|
||||
import ast
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaEvaluateRules import SheerkaEvaluateRules
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.sheerka.services.SheerkaRuleManager import CompiledCondition
|
||||
from evaluators.PythonEvaluator import PythonEvaluator
|
||||
from parsers.BaseParser import ErrorSink
|
||||
from parsers.ExpressionParser import ExpressionParser
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sheerkapython.ExprToConditions import ExprToConditionsVisitor
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
from tests.core.test_SheerkaRuleManager import PYTHON_EVALUATOR_NAME
|
||||
|
||||
|
||||
@dataclass
|
||||
class Obj:
|
||||
value: object
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, Obj) and self.value == other.value
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
|
||||
cmap = {
|
||||
"one": Concept("one", body="1"),
|
||||
"two": Concept("two", body="2"),
|
||||
"three": Concept("three", body="3"),
|
||||
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit", body="20 + unit").def_var("unit"),
|
||||
"equals": Concept("x equals y", pre="is_question()", body="x == y").def_var("x").def_var("y"),
|
||||
"isa1": Concept("x is a y", pre="is_question()", body="isa(x, y)").def_var("x").def_var("y"),
|
||||
"isa2": Concept("x is a y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
"isan1": Concept("x is an y", pre="is_question()", body="isa(x , y)").def_var("x").def_var("y"),
|
||||
"isan2": Concept("x is an y", body="set_isa(x, y)").def_var("x").def_var("y"),
|
||||
"foo": Concept("foo"),
|
||||
"bar": Concept("bar"),
|
||||
"baz": Concept("baz"),
|
||||
}
|
||||
|
||||
|
||||
class TestExprToConditionsVisitor(TestUsingMemoryBasedSheerka):
|
||||
shared_ontology = None
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
instance = cls()
|
||||
init_test_helper = instance.init_test(cache_only=False, ontology="#TestExprToConditionsVisitor#")
|
||||
sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack()
|
||||
for i, concept_name in enumerate(cmap):
|
||||
cmap[concept_name] = updated[i]
|
||||
|
||||
global_context = instance.get_context(sheerka, global_truth=True)
|
||||
sheerka.set_isa(global_context, cmap["baz"], cmap["foo"])
|
||||
|
||||
cls.shared_ontology = sheerka.get_ontology(context)
|
||||
sheerka.pop_ontology(context)
|
||||
|
||||
def initialize_test(self, concepts_map=None):
|
||||
if concepts_map is None:
|
||||
sheerka, context = self.init_test().unpack()
|
||||
sheerka.add_ontology(context, self.shared_ontology)
|
||||
else:
|
||||
sheerka, context, *updated = super().init_test().with_concepts(*concepts_map.values(),
|
||||
create_new=True).unpack()
|
||||
for i, concept_name in enumerate(concepts_map):
|
||||
concepts_map[concept_name] = updated[i]
|
||||
|
||||
return sheerka, context
|
||||
|
||||
@staticmethod
|
||||
def evaluate_conditions(context, conditions, namespace):
|
||||
with context.push(BuiltinConcepts.EXEC_CODE, None) as sub_context:
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
sub_context.deactivate_push()
|
||||
|
||||
evaluation_service = sub_context.sheerka.services[SheerkaEvaluateRules.NAME]
|
||||
return evaluation_service.evaluate_conditions(sub_context, conditions, namespace)
|
||||
|
||||
@staticmethod
|
||||
def get_conditions_from_expression(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
|
||||
known_variables = parser.known_variables if hasattr(parser, "known_variables") else None
|
||||
visitor = ExprToConditionsVisitor(context, known_variables=known_variables)
|
||||
conditions = visitor.get_conditions(parsed)
|
||||
return conditions
|
||||
|
||||
@staticmethod
|
||||
def validate_condition(context, expression, condition, e_code, e_objects, e_variables, e_not_variables):
|
||||
sheerka = context.sheerka
|
||||
|
||||
# check what was compiled
|
||||
if e_code is None:
|
||||
# manage cases where we only check for variable existence
|
||||
assert condition.evaluator_type is None
|
||||
assert condition.return_value is None
|
||||
else:
|
||||
ast_ = ast.parse(e_code, "<source>", 'exec' if "\n" in e_code else 'eval')
|
||||
expected_python_node = PythonNode(e_code, ast_, expression)
|
||||
assert condition.evaluator_type == PYTHON_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(condition.return_value, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(condition.return_value) == expected_python_node
|
||||
|
||||
# check the objects
|
||||
if e_objects is not None:
|
||||
resolved_objects = {k: v.id for k, v in condition.objects.items()}
|
||||
resolved_expected_objects = {k: cmap[v].id for k, v in e_objects.items()}
|
||||
assert resolved_objects == resolved_expected_objects
|
||||
|
||||
# check that variables detected
|
||||
if e_variables is not None:
|
||||
assert condition.variables == e_variables
|
||||
|
||||
if e_not_variables is not None:
|
||||
assert condition.not_variables == e_not_variables
|
||||
|
||||
def run_test_cases(self, context, conditions, test_suite):
|
||||
sheerka = context.sheerka
|
||||
|
||||
for test_data in test_suite:
|
||||
namespace, expected_value = test_data
|
||||
for k, v in namespace.items():
|
||||
if isinstance(v, str):
|
||||
try:
|
||||
namespace[k] = self.evaluate_from_source(context, v)
|
||||
except:
|
||||
pass
|
||||
|
||||
res = self.evaluate_conditions(context, conditions, namespace)
|
||||
value = sheerka.objvalue(res[0].body) if res else False
|
||||
assert value == expected_value
|
||||
|
||||
@staticmethod
|
||||
def evaluate_condition(context, expression, condition, objects):
|
||||
with context.push("Testing conditions SheerkaRuleManagerRulesCompilation", expression) as sub_context:
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
sub_context.sheerka.add_many_to_short_term_memory(sub_context, objects)
|
||||
|
||||
evaluator = PythonEvaluator()
|
||||
for c in condition.concepts_to_reset:
|
||||
c.get_hints().is_evaluated = False
|
||||
|
||||
return evaluator.eval(sub_context, condition.return_value)
|
||||
|
||||
@pytest.mark.parametrize("expression, e_code, e_variables, e_not_variables, test_suite", [
|
||||
("var", None, {"var"}, set(), [({"var": "value"}, True), ({}, False)]),
|
||||
("True", "True", set(), set(), []),
|
||||
("var.value", None, {"var.value"}, set(), []),
|
||||
("not var", None, set(), {"var"}, [({"var": "value"}, False), ({}, True)]),
|
||||
("not not var", None, {"var"}, set(), []),
|
||||
("var and var2 and not var3", None, {"var", "var2"}, {"var3"}, []),
|
||||
("var and var.value == 3", "var.value == 3", {"var"}, set(), [({"var": Obj(3)}, True)]),
|
||||
("not v2 and v1.value == 3", "v1.value == 3", {"v1"}, {"v2"}, [({"v1": Obj(3)}, True), ({"v2": 0}, False)]),
|
||||
("func(var)", "func(var)", {"var"}, set(), []),
|
||||
("var in []", "var in []", {"var"}, set(), []),
|
||||
("a + b", "a + b", {"a", "b"}, set(), []),
|
||||
("foo x", "__o_00__", set(), set(), []), # foo is not a variable
|
||||
("foo y", "evaluate_question(__o_00__, x=y)", {"y"}, set(), []), # foo is not a variable
|
||||
("bar y", "call_concept(__o_00__, x=y)", {"y"}, set(), []), # bar is not a variable
|
||||
])
|
||||
def test_i_can_parse_and_manage_exists(self, expression, e_code, e_variables, e_not_variables, test_suite):
|
||||
sheerka, context, foo, bar = self.init_test().with_concepts(
|
||||
Concept("foo x", pre="is_question()").def_var("x"),
|
||||
Concept("bar x").def_var("x"),
|
||||
).unpack()
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert isinstance(conditions[0], CompiledCondition)
|
||||
condition = conditions[0]
|
||||
|
||||
self.validate_condition(context, expression, condition, e_code, None, e_variables, e_not_variables)
|
||||
self.run_test_cases(context, conditions, test_suite)
|
||||
|
||||
@pytest.mark.parametrize("expression, e_code, e_objects, e_variables, test_suite", [
|
||||
# Concept
|
||||
("1 equals 1", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, True)]),
|
||||
("1 equals 2", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
||||
("one equals one", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, True)]),
|
||||
("one equals two", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
||||
("one equals twenty one", "evaluate_question(__o_00__)", {"__o_00__": "equals"}, set(), [({}, False)]),
|
||||
("self equals 1", "evaluate_question(__o_00__, x=self)", {"__o_00__": "equals"}, {"self"}, [
|
||||
({"self": 1}, True),
|
||||
({"self": 2}, False)]),
|
||||
("x equals 1", "evaluate_question(__o_00__, x=x)", {"__o_00__": "equals"}, {"x"}, [
|
||||
({"x": 1}, True),
|
||||
({"x": 2}, False)]),
|
||||
("one equals self", "evaluate_question(__o_00__, y=self)", {"__o_00__": "equals"}, {"self"}, [
|
||||
({"self": "one"}, True),
|
||||
({"self": "two"}, False)]),
|
||||
("self equals twenty two", "evaluate_question(__o_00__, x=self)", {"__o_00__": "equals"}, {"self"}, [
|
||||
({"self": "twenty two"}, True),
|
||||
({"self": "two"}, False)]
|
||||
),
|
||||
("x equals 1 and y equals 2",
|
||||
"evaluate_question(__o_00__, x=x) and evaluate_question(__o_01__, x=y)",
|
||||
{"__o_00__": "equals", "__o_01__": "equals"},
|
||||
{"x", "y"},
|
||||
[({"x": 1, "y": 2}, True), ({"x": "0", "y": "0"}, False)]
|
||||
),
|
||||
("x equals y", "__o_00__", {"__o_00__": "equals"}, set(), []),
|
||||
("func(self) equals twenty one",
|
||||
"evaluate_question(__o_00__, x=func(self))",
|
||||
{"__o_00__": "equals"},
|
||||
{"self"},
|
||||
[({"self": "twenty one", "func": lambda x: x}, True)]),
|
||||
("func(self) equals twenty one + 1",
|
||||
"evaluate_question(__o_01__, x=func(self), y=__o_00__ + 1)",
|
||||
{"__o_01__": "equals", "__o_00__": "twenties"},
|
||||
{"self"},
|
||||
[({"self": "22", "func": lambda x: x}, True)]),
|
||||
|
||||
# equality
|
||||
("a == 10", "a == 10", {}, {"a"}, [({"a": 10}, True), ({"a": 20}, False), ({}, False)]),
|
||||
("__ret.status == True", "__ret.status == True", {}, {"__ret"}, []),
|
||||
("self == sheerka", "is_sheerka(self)", {}, {"self"}, [
|
||||
({"self": "sheerka"}, True),
|
||||
({"self": "other"}, False),
|
||||
]),
|
||||
("self == BuiltinConcepts.TO_DICT", "self == BuiltinConcepts.TO_DICT", {}, {"self"}, [
|
||||
({"self": "BuiltinConcepts.TO_DICT"}, True),
|
||||
({"self": "other"}, False),
|
||||
]),
|
||||
|
||||
# other Comparisons
|
||||
("a + self > 10", "a + self > 10", {}, {"a", "self"}, [
|
||||
({"a": 10, "self": 1}, True),
|
||||
({"a": 10, "self": 0}, False),
|
||||
]),
|
||||
("10 < one + self", "10 < __o_00__ + self", {"__o_00__": "one"}, {"self"}, [
|
||||
({"self": 10}, True),
|
||||
({"self": 1}, False),
|
||||
]),
|
||||
("23 < twenty one + self", "23 < __o_00__ + self", {"__o_00__": "twenties"}, {"self"}, [
|
||||
({"self": 10}, True),
|
||||
({"self": 1}, False),
|
||||
]),
|
||||
("a equals b and c equals d",
|
||||
"evaluate_question(__o_00__, x=a, y=b) and evaluate_question(__o_01__, x=c, y=d)",
|
||||
{"__o_00__": "equals", "__o_01__": "equals"},
|
||||
{"a", "b", "c", "d"},
|
||||
[]),
|
||||
|
||||
# simple expressions
|
||||
("True", "True", {}, set(), [({}, True)]),
|
||||
("False", "False", {}, set(), [({}, False)]),
|
||||
("10 + 5", "10 + 5", {}, set(), [({}, 15)]),
|
||||
("a + self", "a + self", {}, {"a", "self"}, [({"a": 10, "self": 5}, 15)]),
|
||||
("a + twenty one", "a + __o_00__", {"__o_00__": "twenties"}, {"a"}, [({"a": 10}, 31)]),
|
||||
|
||||
# functions
|
||||
("isinstance('hello', str)", "isinstance('hello', str)", {}, set(), [({}, True)]),
|
||||
("isinstance(a, str)", "isinstance(a, str)", {}, {"a"}, [({"a": "an_str"}, True), ({"a": 1}, False)]),
|
||||
("f(BuiltinConcepts.TO_DICT)", "f(BuiltinConcepts.TO_DICT)", {}, set(), [({"f": lambda x: x}, "__TO_DICT")])
|
||||
|
||||
])
|
||||
def test_i_can_parse(self, expression, e_code, e_objects, e_variables, test_suite):
|
||||
sheerka, context = self.initialize_test()
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert isinstance(conditions[0], CompiledCondition)
|
||||
condition = conditions[0]
|
||||
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
self.run_test_cases(context, conditions, test_suite)
|
||||
|
||||
def test_i_can_force_variable(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
parser = ExpressionParser(known_variables={"one"})
|
||||
conditions = self.get_conditions_from_expression(context, "one < two", parser)
|
||||
python_source = conditions[0].return_value.body.body.source
|
||||
assert python_source == "one < __o_00__"
|
||||
|
||||
resolved_objects = {k: v.id for k, v in conditions[0].objects.items()}
|
||||
resolved_expected_objects = {k: cmap[v].id for k, v in {"__o_00__": "two"}.items()}
|
||||
assert resolved_objects == resolved_expected_objects
|
||||
|
||||
def test_i_can_parse_when_variables_are_missing(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
expression = "x equals 1"
|
||||
e_code = "evaluate_question(__o_00__, x=x)"
|
||||
e_objects = {"__o_00__": "equals"}
|
||||
e_variables = {"x"}
|
||||
test_suite = [({}, False), ({"y": 1}, False)]
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert isinstance(conditions[0], CompiledCondition)
|
||||
condition = conditions[0]
|
||||
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
self.run_test_cases(context, conditions, test_suite)
|
||||
|
||||
def test_question_concept_is_chosen_other_non_question_concept(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
expression = "a is an b"
|
||||
e_code = "evaluate_question(__o_00__, x=a, y=b)"
|
||||
e_objects = {"__o_00__": "isan1"}
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert isinstance(conditions[0], CompiledCondition)
|
||||
condition = conditions[0]
|
||||
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, None, None)
|
||||
|
||||
def test_i_can_manage_when_multiple_concepts(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
expression = "a is a b"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 2
|
||||
|
||||
condition = conditions[0]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "evaluate_question(__o_00__, x=a, y=b)"
|
||||
e_objects = {"__o_00__": "isa1"}
|
||||
e_variables = {"a", "b"}
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
condition = conditions[1]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "evaluate_question(__o_01__, x=a, y=b)"
|
||||
e_objects = {"__o_01__": "isa2"}
|
||||
e_variables = {"a", "b"}
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
# testing
|
||||
|
||||
namespace = {"a": sheerka.new("foo"), "b": sheerka.new("bar")}
|
||||
res = self.evaluate_conditions(context, conditions, namespace)
|
||||
assert len(res) == 2
|
||||
assert isinstance(res[0].value, bool) and not res[0].value
|
||||
assert isinstance(res[1].value, bool) and not res[1].value
|
||||
|
||||
namespace = {"a": sheerka.new("foo"), "b": sheerka.new("foo")}
|
||||
res = self.evaluate_conditions(context, conditions, namespace)
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0].value, bool) and res[0].value
|
||||
|
||||
namespace = {"a": sheerka.new("baz"), "b": sheerka.new("foo")}
|
||||
res = self.evaluate_conditions(context, conditions, namespace)
|
||||
assert len(res) == 1
|
||||
assert isinstance(res[0].value, bool) and res[0].value
|
||||
|
||||
def test_i_can_manage_or_expressions(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
expression = "isinstance(self, foo) or self is a bar"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 3
|
||||
|
||||
condition = conditions[0]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "isinstance(self, __o_00__)"
|
||||
e_objects = {"__o_00__": "foo"}
|
||||
e_variables = {"self"}
|
||||
self.validate_condition(context, "isinstance(self, foo)", condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
condition = conditions[1]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "evaluate_question(__o_01__, x=self)"
|
||||
e_objects = {"__o_01__": "isa1"}
|
||||
e_variables = {"self"}
|
||||
self.validate_condition(context, "self is a bar", condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
condition = conditions[2]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "evaluate_question(__o_02__, x=self)"
|
||||
e_objects = {"__o_02__": "isa2"}
|
||||
e_variables = {"self"}
|
||||
self.validate_condition(context, "self is a bar", condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
def test_i_can_manage_multiple_concepts_melt_with_and_expressions(self):
|
||||
sheerka, context = self.initialize_test()
|
||||
expression = "isinstance(self, foo) and self is a bar"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 2
|
||||
|
||||
condition = conditions[0]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "isinstance(self, __o_00__) and evaluate_question(__o_01__, x=self)"
|
||||
e_objects = {"__o_00__": "foo", "__o_01__": "isa1"}
|
||||
e_variables = {"self"}
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
condition = conditions[1]
|
||||
assert isinstance(condition, CompiledCondition)
|
||||
e_code = "isinstance(self, __o_00__) and evaluate_question(__o_02__, x=self)"
|
||||
e_objects = {"__o_00__": "foo", "__o_02__": "isa2"}
|
||||
e_variables = {"self"}
|
||||
self.validate_condition(context, expression, condition, e_code, e_objects, e_variables, None)
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("self is a 'foo'", {"x is a y"}),
|
||||
("set self is a 'foo'", set()),
|
||||
])
|
||||
def test_i_can_get_concept_to_reset(self, expression, expected):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:param expression:
|
||||
:param expected:
|
||||
:return:
|
||||
"""
|
||||
concepts_map = {
|
||||
"isa": Concept("x is a y", pre="is_question()").def_var("x").def_var("y"),
|
||||
"set_isa": Concept("set x is a y").def_var("x").def_var("y"),
|
||||
}
|
||||
sheerka, context = self.initialize_test(concepts_map)
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert {c.name for c in conditions[0].concepts_to_reset} == expected
|
||||
|
||||
def test_i_can_reset_concepts_when_multiple_levels(self):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:return:
|
||||
"""
|
||||
sheerka, context, is_instance, is_int, is_integer = self.init_concepts(
|
||||
Concept("x is an instance of y", pre="is_question()", body="isinstance(x, y)").def_var("x").def_var("y"),
|
||||
Concept("x is a int", pre="is_question()", body="x is an instance of int").def_var("x"),
|
||||
Concept("x is an integer", pre="is_question()", body="x is a int").def_var("x"),
|
||||
)
|
||||
|
||||
expression = "self is an integer"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert {c.name for c in conditions[0].concepts_to_reset} == {"x is an instance of y",
|
||||
"x is a int",
|
||||
"x is an integer"}
|
||||
|
||||
# So I can evaluate multiple times
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
||||
assert res.status
|
||||
assert sheerka.objvalue(res.body)
|
||||
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
||||
assert res.status
|
||||
assert not sheerka.objvalue(res.body)
|
||||
|
||||
def test_i_can_reset_concepts_when_multiple_levels_and_concept_node(self):
|
||||
"""
|
||||
When compiled conditions, sometimes there are concepts to reset between two usages
|
||||
:return:
|
||||
"""
|
||||
# in this example, x + 2 is an int won't be parsed as an ExactNodeConcept, but as a ConceptNode
|
||||
sheerka, context, is_int, is_integer = self.init_concepts(
|
||||
Concept("x is a int", pre="is_question()", body="isinstance(x, int)").def_var("x"),
|
||||
Concept("x is an integer", pre="is_question()", body="x + 2 is a int").def_var("x"),
|
||||
create_new=True
|
||||
)
|
||||
|
||||
expression = "self is an integer"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert set(c.name for c in conditions[0].concepts_to_reset) == {"x is a int",
|
||||
"x is an integer"}
|
||||
|
||||
# So I can evaluate multiple times
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': 10})
|
||||
assert res.status
|
||||
assert sheerka.objvalue(res.body)
|
||||
|
||||
res = self.evaluate_condition(context, expression, conditions[0], {'self': "string"})
|
||||
assert not res.status
|
||||
|
||||
def test_long_name_concepts_are_not_considered_as_variables(self):
|
||||
sheerka, context, one, number = self.init_concepts(
|
||||
"one",
|
||||
"all numbers",
|
||||
)
|
||||
sheerka.set_isa(context, one, number)
|
||||
|
||||
expression = "all numbers < 5"
|
||||
conditions = self.get_conditions_from_expression(context, expression)
|
||||
|
||||
assert len(conditions) == 1
|
||||
assert conditions[0].return_value.body.body.source == '__o_00__ < 5'
|
||||
Reference in New Issue
Block a user