From 56e1cb458714dc69c6e26b40e3f4c571e1bf7120 Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Sun, 5 Jul 2020 20:19:19 +0200 Subject: [PATCH] Fixed some bugs --- _concepts.txt | 5 ++++- src/core/sheerka/Sheerka.py | 18 +++++++++++++----- src/core/sheerka/services/SheerkaAdmin.py | 18 ++++++++++++++++++ .../services/SheerkaCreateNewConcept.py | 2 +- src/core/sheerka/services/SheerkaDump.py | 13 +------------ .../sheerka/services/SheerkaModifyConcept.py | 4 ++-- src/core/utils.py | 9 --------- src/evaluators/AddConceptInSetEvaluator.py | 9 ++++++--- src/parsers/AtomNodeParser.py | 2 +- src/parsers/BnfNodeParser.py | 2 +- tests/core/test_SheerkaCreateNewConcept.py | 10 +++++----- tests/non_reg/test_sheerka_non_reg.py | 13 +++++++++++++ tests/parsers/test_BnfNodeParser.py | 5 ++--- 13 files changed, 67 insertions(+), 43 deletions(-) diff --git a/_concepts.txt b/_concepts.txt index 6ec2437..53049b4 100644 --- a/_concepts.txt +++ b/_concepts.txt @@ -73,9 +73,12 @@ def concept one hundred as 100 one hundred isa number def concept hundreds from bnf number=n1 'hundred' 'and' number=n2 where n1 < 10 and n2 < 100 as n1 * 100 + n2 hundreds isa number -#def concept hundreds from bnf number 'hundred' where number < 10 as number * 100 +def concept hundreds from bnf number 'hundred' where number < 10 as number * 100 +last_created_concept() is number def concept thousands from bnf number 'thousand' where number < 1000 as number * 1000 thousands isa number +def concept thousands from bnf number=n1 'thousand' 'and' number=n2 as n1 * 1000 + n2 where n1 < 1000 and n2 < 1000 +last_created_concept() is number def concept history as history() def concept plus from a plus b as a + b def concept mult from a mult b as a * b diff --git a/src/core/sheerka/Sheerka.py b/src/core/sheerka/Sheerka.py index 84f9dff..dd771ef 100644 --- a/src/core/sheerka/Sheerka.py +++ b/src/core/sheerka/Sheerka.py @@ -32,7 +32,7 @@ class Sheerka(Concept): CONCEPTS_BY_NAME_ENTRY = "Concepts_By_Name" CONCEPTS_BY_HASH_ENTRY = "Concepts_By_Hash" # store hash of concepts definitions (not values) - CONCEPTS_REFERENCES = "Concepts_References" # tracks references between concepts + CONCEPTS_REFERENCES_ENTRY = "Concepts_References" # tracks references between concepts CONCEPTS_BY_FIRST_KEYWORD_ENTRY = "Concepts_By_First_Keyword" RESOLVED_CONCEPTS_BY_FIRST_KEYWORD_ENTRY = "Resolved_Concepts_By_First_Keyword" @@ -45,6 +45,8 @@ class Sheerka(Concept): BUILTIN_CONCEPTS_KEYS = "Builtins_Concepts" # sequential key for builtin concepts USER_CONCEPTS_KEYS = "User_Concepts" # sequential key for user defined concepts + MAX_EXECUTION_HISTORY = 100 + def __init__(self, cache_only=False, debug=False, loggers=None): self.init_logging(debug, loggers) self.loggers = loggers @@ -91,6 +93,8 @@ class Sheerka(Concept): self.locals = {} + self.last_executions = [] + @property def resolved_concepts_by_first_keyword(self): """ @@ -218,8 +222,8 @@ class Sheerka(Concept): cache = ListIfNeededCache(**params(self.CONCEPTS_BY_HASH_ENTRY)) register_concept_cache(self.CONCEPTS_BY_HASH_ENTRY, cache, lambda c: c.get_definition_hash(), True) - cache = SetCache(default=lambda k: self.sdp.get(self.CONCEPTS_REFERENCES, k)) - self.cache_manager.register_cache(self.CONCEPTS_REFERENCES, cache) + cache = SetCache(default=lambda k: self.sdp.get(self.CONCEPTS_REFERENCES_ENTRY, k)) + self.cache_manager.register_cache(self.CONCEPTS_REFERENCES_ENTRY, cache) cache = DictionaryCache(default=lambda k: self.sdp.get(self.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, k)) self.cache_manager.register_cache(self.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, cache) @@ -299,7 +303,7 @@ class Sheerka(Concept): Init the parsers :return: """ - core.utils.init_package_import("parsers") + core.utils.import_module_and_sub_module("parsers") base_class = core.utils.get_class("parsers.BaseParser.BaseParser") modules_to_skip = ["parsers.BaseNodeParser"] @@ -332,7 +336,7 @@ class Sheerka(Concept): Init the evaluators :return: """ - core.utils.init_package_import("evaluators") + core.utils.import_module_and_sub_module("evaluators") for evaluator in core.utils.get_sub_classes("evaluators", "evaluators.BaseEvaluator.OneReturnValueEvaluator"): self.init_log.debug(f"Adding builtin evaluator '{evaluator.__name__}'") self.evaluators.append(evaluator) @@ -412,6 +416,10 @@ class Sheerka(Concept): # f.write(text + "\n") self._last_execution = execution_context + if len(self.last_executions) == self.MAX_EXECUTION_HISTORY: + del self.last_executions[0] + self.last_executions.append(execution_context) + return ret def print(self, result, instructions=None): diff --git a/src/core/sheerka/services/SheerkaAdmin.py b/src/core/sheerka/services/SheerkaAdmin.py index 9a3241d..5df245b 100644 --- a/src/core/sheerka/services/SheerkaAdmin.py +++ b/src/core/sheerka/services/SheerkaAdmin.py @@ -16,6 +16,8 @@ class SheerkaAdmin(BaseService): self.sheerka.bind_service_method(self.caches_names) self.sheerka.bind_service_method(self.cache) self.sheerka.bind_service_method(self.restore) + self.sheerka.bind_service_method(self.concepts) + self.sheerka.bind_service_method(self.last_created_concept) def caches_names(self): """ @@ -61,3 +63,19 @@ class SheerkaAdmin(BaseService): print(f"Execution time: {elapsed}") except IOError: pass + + def concepts(self): + return self.sheerka.sdp.list(self.sheerka.CONCEPTS_BY_ID_ENTRY) + + def last_created_concept(self, use_history=False): + for exec_result in reversed(self.sheerka.last_executions): + return_values = exec_result.values["return_values"] + for ret in return_values: + if ret.status and self.sheerka.isinstance(ret.value, BuiltinConcepts.NEW_CONCEPT): + return ret.value.body + + if use_history: + return self.sheerka.new(BuiltinConcepts.ERROR, body="Not yet implement") + + return self.sheerka.new(BuiltinConcepts.NOT_FOUND) + diff --git a/src/core/sheerka/services/SheerkaCreateNewConcept.py b/src/core/sheerka/services/SheerkaCreateNewConcept.py index 321b8e9..b1c85a8 100644 --- a/src/core/sheerka/services/SheerkaCreateNewConcept.py +++ b/src/core/sheerka/services/SheerkaCreateNewConcept.py @@ -75,7 +75,7 @@ class SheerkaCreateNewConcept(BaseService): # update references for ref in self.compute_references(concept): - cache_manager.put(sheerka.CONCEPTS_REFERENCES, ref, concept.id) + cache_manager.put(sheerka.CONCEPTS_REFERENCES_ENTRY, ref, concept.id) # TODO : this line seems to be useless # The grammar is never reset diff --git a/src/core/sheerka/services/SheerkaDump.py b/src/core/sheerka/services/SheerkaDump.py index b1917a3..bb75dd1 100644 --- a/src/core/sheerka/services/SheerkaDump.py +++ b/src/core/sheerka/services/SheerkaDump.py @@ -15,26 +15,15 @@ def get_pp(): class SheerkaDump(BaseService): - NAME = "Dump" def __init__(self, sheerka): super().__init__(sheerka) - + def initialize(self): - self.sheerka.bind_service_method(self.dump_concepts, "concepts") self.sheerka.bind_service_method(self.dump_desc, "desc") self.sheerka.bind_service_method(self.dump_state, "state") - def dump_concepts(self): - lst = self.sheerka.sdp.list(self.sheerka.CONCEPTS_BY_ID_ENTRY) - for item in lst: - if hasattr(item, "__iter__"): - for i in item: - self.sheerka.log.info(i) - else: - self.sheerka.log.info(item) - def dump_desc(self, *concept_names, eval=False): first = True event = Event(f"Dumping description", "") diff --git a/src/core/sheerka/services/SheerkaModifyConcept.py b/src/core/sheerka/services/SheerkaModifyConcept.py index 7f58c48..a4c79a7 100644 --- a/src/core/sheerka/services/SheerkaModifyConcept.py +++ b/src/core/sheerka/services/SheerkaModifyConcept.py @@ -37,7 +37,7 @@ class SheerkaModifyConcept(BaseService): BuiltinConcepts.CONCEPT_ALREADY_DEFINED, body=concept)) - old_references = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES, concept.id) + old_references = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES_ENTRY, concept.id) if old_references: old_references = old_references.copy() @@ -59,7 +59,7 @@ class SheerkaModifyConcept(BaseService): :return: """ - refs = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES, concept.id) + refs = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES_ENTRY, concept.id) if not refs: return diff --git a/src/core/utils.py b/src/core/utils.py index 6e7b7b1..e6e6a9f 100644 --- a/src/core/utils.py +++ b/src/core/utils.py @@ -122,15 +122,6 @@ def get_classes_from_package(package_name): yield c -def init_package_import(package_name): - pkg = __import__(package_name) - prefix = pkg.__name__ + "." - # prefix = package_name + "." - for (module_loader, name, ispkg) in pkgutil.iter_modules(pkg.__path__, prefix): - importlib.import_module(name) - importlib.import_module(package_name) - - def import_module_and_sub_module(module_name): """ Import the module, and one sub level diff --git a/src/evaluators/AddConceptInSetEvaluator.py b/src/evaluators/AddConceptInSetEvaluator.py index 008837a..36c5a1a 100644 --- a/src/evaluators/AddConceptInSetEvaluator.py +++ b/src/evaluators/AddConceptInSetEvaluator.py @@ -35,7 +35,8 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator): True, sheerka.new(BuiltinConcepts.USER_INPUT, body=parser_input, user_name="N/A")) - with context.push(BuiltinConcepts.PROCESS_INPUT, name_node, desc=f"Recognizing '{name_node}'") as sub_context: + with context.push(BuiltinConcepts.PROCESS_INPUT, name_node, + desc=f"Recognizing '{name_node}'") as sub_context: r = sheerka.execute(sub_context, ret_val, ALL_STEPS) one_r = core.builtin_helpers.expect_one(context, r) sub_context.add_values(return_values=one_r) @@ -55,6 +56,10 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator): parents=[return_value]) concept = res.value + if sheerka.has_id(concept.id) and id(concept) == id(sheerka.get_by_id(concept.id)): + # hack because it is not possible to use sheerka.modify_concept() on a cache instance + concept = sheerka.new((concept.name, concept.id)) + res = _resolve(isa_node.set) if not res.status: return sheerka.ret( @@ -75,5 +80,3 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator): res.status, res.body, parents=[return_value]) - - diff --git a/src/parsers/AtomNodeParser.py b/src/parsers/AtomNodeParser.py index 6d8d81b..6aead37 100644 --- a/src/parsers/AtomNodeParser.py +++ b/src/parsers/AtomNodeParser.py @@ -275,7 +275,7 @@ class AtomNodeParser(BaseNodeParser): concept_parser.eat_concept(concepts[0], pos) continue - # make the cartesian product + # len(concepts) > 1, make the cartesian product temp_res = [] for concept_parser in concept_parser_helpers: if concept_parser.is_locked: diff --git a/src/parsers/BnfNodeParser.py b/src/parsers/BnfNodeParser.py index d6afc9c..affa1da 100644 --- a/src/parsers/BnfNodeParser.py +++ b/src/parsers/BnfNodeParser.py @@ -980,7 +980,7 @@ class BnfConceptParserHelper: _add_prop(concept, underlying.parsing_expression.rule_name, value) # KSI : Why don't we set concept.metadata.need_validation to True ? - if isinstance(underlying, NonTerminalNode): + if isinstance(underlying, NonTerminalNode) and not isinstance(underlying.parsing_expression, ConceptExpression): for node in underlying.children: _process_rule_name(concept, node) diff --git a/tests/core/test_SheerkaCreateNewConcept.py b/tests/core/test_SheerkaCreateNewConcept.py index f0a41c4..8931c8f 100644 --- a/tests/core/test_SheerkaCreateNewConcept.py +++ b/tests/core/test_SheerkaCreateNewConcept.py @@ -192,11 +192,11 @@ class TestSheerkaCreateNewConcept(TestUsingMemoryBasedSheerka): create_new=True ) - assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES, one.id) == {twenties.id} - assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES, two.id) == {twenties.id} - assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES, number.id) is None - assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES, twenty.id) == {twenties.id} - assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES, twenties.id) is None + assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES_ENTRY, one.id) == {twenties.id} + assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES_ENTRY, two.id) == {twenties.id} + assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES_ENTRY, number.id) is None + assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES_ENTRY, twenty.id) == {twenties.id} + assert sheerka.cache_manager.get(sheerka.CONCEPTS_REFERENCES_ENTRY, twenties.id) is None class TestSheerkaCreateNewConceptFileBased(TestUsingFileBasedSheerka): diff --git a/tests/non_reg/test_sheerka_non_reg.py b/tests/non_reg/test_sheerka_non_reg.py index 8c4154f..dd69db7 100644 --- a/tests/non_reg/test_sheerka_non_reg.py +++ b/tests/non_reg/test_sheerka_non_reg.py @@ -963,6 +963,19 @@ as: assert res[0].status assert res[0].body == 21 + def test_i_can_use_last_created_concept_to_define_set(self): + init = [ + "def concept number", + "def concept one", + ] + + sheerka = self.init_scenario(init) + + res = sheerka.evaluate_user_input("last_created_concept() isa number") + + assert res[0].status + assert sheerka.isa(sheerka.new("one"), sheerka.new("number")) + class TestSheerkaNonRegFile(TestUsingFileBasedSheerka): def test_i_can_def_several_concepts(self): diff --git a/tests/parsers/test_BnfNodeParser.py b/tests/parsers/test_BnfNodeParser.py index 80055c0..9621188 100644 --- a/tests/parsers/test_BnfNodeParser.py +++ b/tests/parsers/test_BnfNodeParser.py @@ -608,7 +608,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka): "foo": concept_foo } - def test_i_can_use_context_reference_with_multiple_levels(self): + def test_i_can_manage_concepts_reference_when_multiple_levels(self): my_map = { "foo": self.bnf_concept("foo", Sequence(StrMatch("one"), StrMatch("two"))), "bar": self.bnf_concept("bar", ConceptExpression("foo")), @@ -639,8 +639,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka): assert concept_baz.body == BuiltinConcepts.NOT_INITIALIZED assert concept_baz.compiled == { ConceptParts.BODY: concept_bar, - "bar": concept_bar, - "foo": concept_foo, + "bar": concept_bar } def test_i_can_mix_reference_to_other_concepts(self):