Fixed #29: Parsers: Implement parsing memoization

Fixed #77 : Parser: ShortTermMemoryParser should be called separately
Fixed #78 : Remove VariableNode usage
Fixed #79 : ConceptManager: Implement compile caching
Fixed #80 : SheerkaExecute : parsers_key is not correctly computed
Fixed #81 : ValidateConceptEvaluator : Validate concept's where and pre clauses right after the parsing
Fixed #82 : SheerkaIsAManager: isa() failed when the set as a body
Fixed #83 : ValidateConceptEvaluator : Support BNF and SYA Concepts
Fixed #84 : ExpressionParser: Implement the parser as a standard parser
Fixed #85 : Services: Give order to services
Fixed #86 : cannot manage smart_get_attr(the short, color)
This commit is contained in:
2021-06-07 21:14:03 +02:00
parent 1059ce25c5
commit 7dcaa9c111
92 changed files with 4263 additions and 1890 deletions
@@ -0,0 +1,198 @@
import pytest
from core.builtin_concepts import ParserResultConcept
from core.builtin_concepts_ids import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from evaluators.BaseEvaluator import BaseEvaluator
from evaluators.ValidateConceptEvaluator import ValidateConceptEvaluator
from parsers.BaseNodeParser import ConceptNode
from parsers.BaseParser import BaseParser
from parsers.BnfNodeParser import BnfNodeParser
from parsers.SyaNodeParser import SyaNodeParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.evaluators.EvaluatorTestsUtils import p_ret_val, pr_ret_val, ret_val
class TestValidateConceptEvaluator(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("return_value, need_validation, expected", [
(pr_ret_val(Concept("foo", where="something"), status=True), True, True),
(pr_ret_val(Concept("foo", pre="something"), status=True), True, True),
(pr_ret_val(Concept("foo", where="something"), status=True), False, False),
(pr_ret_val(Concept("foo", pre="something"), status=True), False, False),
(pr_ret_val(Concept("foo"), status=True), True, False),
(pr_ret_val(Concept("foo"), status=True), True, False),
(pr_ret_val(Concept("foo", where=None), status=True), True, False),
(pr_ret_val(Concept("foo", pre=None), status=True), True, False),
(pr_ret_val(Concept("foo", where=""), status=True), True, False),
(pr_ret_val(Concept("foo", pre=""), status=True), True, False),
(pr_ret_val(Concept("foo", where="something"), status=False), True, False),
(pr_ret_val(Concept("foo", pre="something"), status=False), True, False),
(pr_ret_val("Not a concept", status=True), True, False),
(pr_ret_val("Not a concept", status=False), True, False),
(p_ret_val("Not a parser result", status=True), True, False),
(p_ret_val("Not a parser result", status=False), True, False),
])
def test_i_can_match(self, return_value, need_validation, expected):
sheerka, context = self.init_concepts()
evaluator = ValidateConceptEvaluator()
if (sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT) and
isinstance(return_value.body.body, Concept)):
return_value.body.body.get_hints().need_validation = need_validation
assert evaluator.matches(context, return_value) == expected
def test_i_cannot_match_when_the_return_value_is_not_a_direct_parsing_result(self):
# I match only if the return_value comes from a parser (not from an after_parsing evaluator)
sheerka, context = self.init_concepts()
concept = Concept("foo", pre="something")
parser_result = ParserResultConcept(BaseParser.get_name("parser"), source=concept.name, value=concept)
return_value = ret_val(value=parser_result, who="evaluators.something", status=True)
return_value.body.body.get_hints().need_validation = True
evaluator = ValidateConceptEvaluator()
assert not evaluator.matches(context, return_value)
@pytest.mark.parametrize("concept", [
Concept("foo", pre="False"),
Concept("foo", where="False"),
])
def test_i_can_eval_when_constraint_is_false(self, concept):
sheerka, context, foo = self.init_concepts(concept)
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert not res.status
assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
assert res.body.body == foo
@pytest.mark.parametrize("concept", [
Concept("foo"),
Concept("foo", pre="True"),
Concept("foo", where="True"),
])
def test_i_can_eval_when_constraint_is_true_or_when_no_constrain(self, concept):
sheerka, context, foo = self.init_concepts(concept)
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert res is None
@pytest.mark.parametrize("concept", [
Concept("foo"),
Concept("foo", pre="True"),
Concept("foo", where="True"),
])
def test_i_can_eval_when_constraint_is_true_or_when_no_constrain_use_copy(self, concept):
sheerka, context, foo = self.init_concepts(concept)
foo.get_hints().use_copy = True
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert res.status
assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME
assert res.body.body.id == foo.id
assert not res.body.body.get_hints().use_copy
def test_i_can_eval_when_is_question(self):
sheerka, context, foo = self.init_concepts(Concept("foo", pre="is_question()"))
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert not res.status
context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert res is None
def test_i_can_eval_when_unknown_variables_but_no_constraint(self):
sheerka, context, foo = self.init_concepts(Concept("a plus b").def_var("a").def_var("b"))
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert res is None
def test_i_can_eval_when_unknown_variables(self):
# ValidateConceptEvaluator must filter only if all the variables are known
# In this example, 'b' is not set, so the return_value must not be filtered
sheerka, context, foo = self.init_concepts(
Concept("a plus b", where="isinstance(b, int)").def_var("a", "10").def_var("b"))
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert res is None
def test_i_can_eval_when_constraint_on_variable_fails(self):
sheerka, context, foo = self.init_concepts(
Concept("a plus b", where="isinstance(b, int)").def_var("a").def_var("b", "'a string'"))
ret_val = pr_ret_val(foo, status=True)
res = ValidateConceptEvaluator().eval(context, ret_val)
assert not res.status
def test_i_can_eval_bnf_concepts(self):
sheerka, context, quantify_x = self.init_concepts(
Concept("quantify x", definition="('one'|'two') x", where="x != 'one'").def_var("x"),
create_new=True)
evaluator = ValidateConceptEvaluator()
# success
ret_val = BnfNodeParser().parse(context, ParserInput("one 'two'"))
assert evaluator.matches(context, ret_val)
res = evaluator.eval(context, ret_val)
assert isinstance(res.body.body, list)
assert len(res.body.body) == 1
assert isinstance(res.body.body[0], ConceptNode)
assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id
# failure
ret_val = BnfNodeParser().parse(context, ParserInput("one 'one'"))
assert evaluator.matches(context, ret_val)
res = evaluator.eval(context, ret_val)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
assert res.body.body == ret_val.body.body
def test_i_can_eval_sya_concepts(self):
sheerka, context, quantify_x = self.init_concepts(
Concept("a plus b", where="a < 10").def_var("a").def_var("b"),
create_new=True)
evaluator = ValidateConceptEvaluator()
# success
ret_val = SyaNodeParser().parse(context, ParserInput("5 plus 3"))
assert evaluator.matches(context, ret_val)
res = evaluator.eval(context, ret_val)
assert isinstance(res.body.body, list)
assert len(res.body.body) == 1
assert isinstance(res.body.body[0], ConceptNode)
assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id
# failure
ret_val = SyaNodeParser().parse(context, ParserInput("15 plus 3"))
assert evaluator.matches(context, ret_val)
res = evaluator.eval(context, ret_val)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
assert res.body.body == ret_val.body.body
def test_i_can_manage_infinite_recursion(self):
sheerka, context, a_and_b = self.init_concepts(
Concept("a and b", where="is_question()", body="a and b").def_var("a").def_var("b"),
create_new=True)
evaluator = ValidateConceptEvaluator()
ret_val = pr_ret_val(a_and_b)
res = evaluator.eval(context, ret_val)
assert res is None # infinite recursion detected, res is None to drop the validator