diff --git a/src/core/builtin_helpers.py b/src/core/builtin_helpers.py index 1b73b14..1af5b88 100644 --- a/src/core/builtin_helpers.py +++ b/src/core/builtin_helpers.py @@ -72,6 +72,9 @@ def expect_one(context, return_values): sheerka.new(BuiltinConcepts.IS_EMPTY, body=return_values), parents=return_values) + if len(return_values) == 1: + return return_values[0] + successful_results = [item for item in return_values if item.status] number_of_successful = len(successful_results) # total_items = len(return_values) @@ -113,7 +116,7 @@ def expect_one(context, return_values): return sheerka.ret( context.who, False, - return_values[0], + return_values[0].body, parents=return_values) else: # test if only one evaluator in error diff --git a/src/core/sheerka/Services/SheerkaCreateNewConcept.py b/src/core/sheerka/Services/SheerkaCreateNewConcept.py index f6e082f..7d8f159 100644 --- a/src/core/sheerka/Services/SheerkaCreateNewConcept.py +++ b/src/core/sheerka/Services/SheerkaCreateNewConcept.py @@ -1,6 +1,7 @@ import core.utils from core.builtin_concepts import BuiltinConcepts, ErrorConcept from core.concept import Concept +from sdp.sheerkaDataProvider import SheerkaDataProviderDuplicateKeyError BNF_NODE_PARSER_CLASS = "parsers.BnfNodeParser_Old.BnfNodeParser" BASE_NODE_PARSER_CLASS = "parsers.BaseNodeParser.BaseNodeParser" diff --git a/src/core/sheerka/Services/SheerkaEvaluateConcept.py b/src/core/sheerka/Services/SheerkaEvaluateConcept.py index 9c4ad2e..15cdac9 100644 --- a/src/core/sheerka/Services/SheerkaEvaluateConcept.py +++ b/src/core/sheerka/Services/SheerkaEvaluateConcept.py @@ -1,5 +1,5 @@ from core.builtin_concepts import BuiltinConcepts -from core.builtin_helpers import expect_one +from core.builtin_helpers import expect_one, only_successful from core.concept import Concept, DoNotResolve, ConceptParts, InfiniteRecursionResolved CONCEPT_EVALUATION_STEPS = [ @@ -71,6 +71,11 @@ class SheerkaEvaluateConcept: :param logger: :return: """ + def is_only_successful(r): +# return False + return context.sheerka.isinstance(r, BuiltinConcepts.RETURN_VALUE) and \ + context.sheerka.isinstance(r.body, BuiltinConcepts.ONLY_SUCCESSFUL) + steps = [BuiltinConcepts.BEFORE_PARSING, BuiltinConcepts.PARSING, BuiltinConcepts.AFTER_PARSING] for part_key in ConceptParts: if part_key in concept.compiled: @@ -88,7 +93,8 @@ class SheerkaEvaluateConcept: to_parse = self.sheerka.ret(context.who, True, self.sheerka.new(BuiltinConcepts.USER_INPUT, body=source)) res = self.sheerka.execute(sub_context, to_parse, steps) - concept.compiled[part_key] = res + only_success = only_successful(sub_context, res) + concept.compiled[part_key] = only_success.body.body if is_only_successful(only_success) else res sub_context.add_values(return_values=res) for var_name, default_value in concept.metadata.variables: @@ -106,7 +112,8 @@ class SheerkaEvaluateConcept: to_parse = self.sheerka.ret(context.who, True, self.sheerka.new(BuiltinConcepts.USER_INPUT, body=default_value)) res = self.sheerka.execute(context, to_parse, steps) - concept.compiled[var_name] = res + only_success = only_successful(sub_context, res) + concept.compiled[var_name] = only_success.body.body if is_only_successful(only_success) else res sub_context.add_values(return_values=res) # Updates the cache of concepts when possible @@ -114,6 +121,7 @@ class SheerkaEvaluateConcept: self.sheerka.get_by_id(concept.id).compiled = concept.compiled def resolve(self, context, to_resolve, current_prop, current_concept, force_evaluation): + if isinstance(to_resolve, DoNotResolve): return to_resolve.value diff --git a/src/parsers/ExactConceptParser.py b/src/parsers/ExactConceptParser.py index 7eff3e3..2e74caa 100644 --- a/src/parsers/ExactConceptParser.py +++ b/src/parsers/ExactConceptParser.py @@ -11,7 +11,7 @@ class ExactConceptParser(BaseParser): Tries to recognize a single concept """ - MAX_WORDS_SIZE = 3 + MAX_WORDS_SIZE = 6 def __init__(self, max_word_size=None, **kwargs): BaseParser.__init__(self, "ExactConcept", 80) @@ -36,7 +36,9 @@ class ExactConceptParser(BaseParser): if len(words) > (self.max_word_size or self.MAX_WORDS_SIZE): context.log(f"Max words reached. Stopping.", self.name) - return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, body=parser_input)) + too_long = sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, body=parser_input) + body = sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=parser_input, reason=too_long) + return sheerka.ret(self.name, False, body) recognized = [] # keep track of the concepts founds for combination in self.combinations(words): diff --git a/tests/core/test_builtin_helpers.py b/tests/core/test_builtin_helpers.py index 7d5c6bf..6ca5123 100644 --- a/tests/core/test_builtin_helpers.py +++ b/tests/core/test_builtin_helpers.py @@ -49,8 +49,7 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka): ] res = core.builtin_helpers.expect_one(self.get_context(sheerka), items) assert not res.status - assert res.value, items[0] - assert res.parents == items + assert res.value == items[0].body def test_i_can_use_expect_when_only_errors_2(self): sheerka = self.get_sheerka() @@ -74,7 +73,6 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka): res = core.builtin_helpers.expect_one(self.get_context(sheerka), items) assert res.status assert res.body == items[0].body - assert res.parents == items def test_i_can_use_expect_one_when_one_success_2(self): sheerka = self.get_sheerka() diff --git a/tests/parsers/test_AtomsParser.py b/tests/parsers/test_AtomsParser.py index cb5709b..3d0e35e 100644 --- a/tests/parsers/test_AtomsParser.py +++ b/tests/parsers/test_AtomsParser.py @@ -193,6 +193,20 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka): assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT) assert lexer_nodes == expected_array + def test_i_can_parse_concepts_with_isa(self): + concepts_map = { + "one": Concept("one"), + "number": Concept("number"), + } + + sheerka, context, parser = self.init_parser(concepts_map) + sheerka.set_isa(context, sheerka.new("one"), sheerka.new("number")) + + res = parser.parse(context, "one") + lexer_nodes = res.body.body + expected_array = compute_expected_array(concepts_map, "one", ["one"]) + assert lexer_nodes == expected_array + @pytest.mark.parametrize("text", [ "foo", f"foo one", diff --git a/tests/parsers/test_ExactConceptParser.py b/tests/parsers/test_ExactConceptParser.py index 83bb270..891e130 100644 --- a/tests/parsers/test_ExactConceptParser.py +++ b/tests/parsers/test_ExactConceptParser.py @@ -129,12 +129,14 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka): def test_i_can_detect_concepts_too_long(self): context = self.get_context(self.get_sheerka(singleton=True)) - source = "a very very long concept" + source = "a very but finally too long concept" res = ExactConceptParser().parse(context, source) assert not res.status - assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_TOO_LONG) - assert res.value.body == "a very very long concept" + assert context.sheerka.isinstance(res.value, BuiltinConcepts.NOT_FOR_ME) + assert context.sheerka.isinstance(res.value.reason, BuiltinConcepts.CONCEPT_TOO_LONG) + assert res.value.reason.body == source + assert res.value.body == source def test_i_can_detect_concept_from_tokens(self): context = self.get_context(self.get_sheerka(singleton=True)) diff --git a/tests/parsers/test_SyaNodeParser.py b/tests/parsers/test_SyaNodeParser.py index bf14bd7..682a3e9 100644 --- a/tests/parsers/test_SyaNodeParser.py +++ b/tests/parsers/test_SyaNodeParser.py @@ -776,7 +776,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka): ("(one infix two) (three prefixed)", ["one", "two", "infix", "three", "prefixed"]), ]) def test_i_can_post_fix_sequences(self, expression, expected): - sheerka, context, parser = self.init_parser(cmap, None) + sheerka, context, parser = self.init_parser() res = parser.infix_to_postfix(context, expression) expected_array = compute_expected_array(cmap, expression, expected) @@ -784,6 +784,24 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka): assert len(res) == 1 assert res[0].out == expected_array + @pytest.mark.parametrize("expression", [ + "one ? two : three", + "one?two:three", + "one ?two:three", + "one? two:three", + "one ? two :three", + "one ? two: three", + ]) + def test_whitespaces_may_be_omitted_in_some_circumstances(self, expression): + sheerka, context, parser = self.init_parser() + + expected = ["one", "two", "three", "?"] + res = parser.infix_to_postfix(context, expression) + expected_array = compute_expected_array(cmap, expression, expected) + + assert len(res) == 1 + assert res[0].out == expected_array + def test_the_more_concepts_the_more_results(self): concepts_map = { "plus": Concept("a plus b").def_var("a").def_var("b"),