Resolved some remaining chicken and egg when parsing BNF nodes

This commit is contained in:
2020-07-05 11:03:03 +02:00
parent ad8a997942
commit 71f753c925
14 changed files with 310 additions and 56 deletions
+4 -4
View File
@@ -373,15 +373,15 @@ class ExecutionContext:
:param predicate: what execution context to keep
:param get_obj: lambda to compute what to return
:param start_with_self: include the current execution context in the search
:param stop: stop the search if matched
:param stop: condition to stop
:return:
"""
current = self if start_with_self else self._parent
while current:
if stop and stop(current):
break
if predicate is None or predicate(current):
yield current if get_obj is None else get_obj(current)
if stop and stop(current):
break
current = current._parent
+6
View File
@@ -8,6 +8,7 @@ from cache.CacheManager import CacheManager
from cache.DictionaryCache import DictionaryCache
from cache.IncCache import IncCache
from cache.ListIfNeededCache import ListIfNeededCache
from cache.SetCache import SetCache
from core.builtin_concepts import BuiltinConcepts, ErrorConcept, ReturnValueConcept, BuiltinErrors, BuiltinUnique, \
UnknownConcept
from core.concept import Concept, ConceptParts, PROPERTIES_FOR_NEW
@@ -31,6 +32,8 @@ 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_BY_FIRST_KEYWORD_ENTRY = "Concepts_By_First_Keyword"
RESOLVED_CONCEPTS_BY_FIRST_KEYWORD_ENTRY = "Resolved_Concepts_By_First_Keyword"
CONCEPTS_SYA_DEFINITION_ENTRY = "Concepts_Sya_Definitions"
@@ -215,6 +218,9 @@ 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 = 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)
self.cache_manager.get(self.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, None) # to init from sdp
@@ -1,6 +1,6 @@
import core.utils
from core.builtin_concepts import BuiltinConcepts, ErrorConcept
from core.concept import Concept, DEFINITION_TYPE_DEF, ensure_concept
from core.concept import Concept, DEFINITION_TYPE_DEF, ensure_concept, DEFINITION_TYPE_BNF
from core.sheerka.services.sheerka_service import BaseService
from sdp.sheerkaDataProvider import SheerkaDataProviderDuplicateKeyError
@@ -64,7 +64,6 @@ class SheerkaCreateNewConcept(BaseService):
resolved_concepts_by_first_keyword = init_ret_value.body
# if everything is fine
concept.freeze_definition_hash()
cache_manager.add_concept(concept)
cache_manager.put(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY, False, concepts_by_first_keyword)
@@ -74,9 +73,36 @@ class SheerkaCreateNewConcept(BaseService):
# allow search by definition when definition relevant
cache_manager.put(self.sheerka.CONCEPTS_BY_NAME_ENTRY, concept.metadata.definition, concept)
# update references
for ref in self.compute_references(concept):
cache_manager.put(sheerka.CONCEPTS_REFERENCES, ref, concept.id)
# TODO : this line seems to be useless
# The grammar is never reset
if concept.bnf and init_bnf_ret_value is not None and init_bnf_ret_value.status:
sheerka.cache_manager.clear(sheerka.CONCEPTS_GRAMMARS_ENTRY)
# process the return if needed
ret = sheerka.ret(self.NAME, True, sheerka.new(BuiltinConcepts.NEW_CONCEPT, body=concept))
return ret
def compute_references(self, concept):
"""
We need to keep a track of all concepts used by the current concept
So that if one of these are modified, we can modify the current concept accordingly
:param concept:
:return:
"""
refs = set()
if concept.metadata.definition_type == DEFINITION_TYPE_BNF:
from parsers.BnfNodeParser import BnfNodeConceptExpressionVisitor
other_concepts_visitor = BnfNodeConceptExpressionVisitor()
other_concepts_visitor.visit(concept.bnf)
for concept in other_concepts_visitor.references:
if isinstance(concept, str):
concept = self.sheerka.get_by_key(concept)
refs.add(concept.id)
return refs
@@ -1,5 +1,6 @@
from core.builtin_concepts import BuiltinConcepts
from core.sheerka.services.sheerka_service import BaseService
from parsers.BnfParser import BnfParser
class SheerkaModifyConcept(BaseService):
@@ -36,6 +37,10 @@ class SheerkaModifyConcept(BaseService):
BuiltinConcepts.CONCEPT_ALREADY_DEFINED,
body=concept))
old_references = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES, concept.id)
if old_references:
old_references = old_references.copy()
self.sheerka.cache_manager.update_concept(old_version, concept)
# TODO : update concept by first keyword
@@ -45,3 +50,21 @@ class SheerkaModifyConcept(BaseService):
ret = self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.NEW_CONCEPT, body=concept))
return ret
def update_references(self, context, concept):
"""
Updates all the concepts that reference concept
:param context:
:param concept:
:return:
"""
refs = self.sheerka.cache_manager.get(self.sheerka.CONCEPTS_REFERENCES, concept.id)
if not refs:
return
for concept_id in refs:
concept = self.sheerka.get_by_id(concept_id)
if concept.bnf is not None:
BnfParser.update_recurse_id(context, concept_id, concept.bnf)
@@ -4,6 +4,7 @@ from cache.SetCache import SetCache
from core.ast.nodes import python_to_concept
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, ConceptParts, ensure_concept, DEFINITION_TYPE_BNF
from core.sheerka.services.SheerkaModifyConcept import SheerkaModifyConcept
from core.sheerka.services.sheerka_service import BaseService
GROUP_PREFIX = 'All_'
@@ -54,7 +55,13 @@ class SheerkaSetsManager(BaseService):
if not res.status:
return res
return self.add_concept_to_set(context, concept, concept_set)
res = self.add_concept_to_set(context, concept, concept_set)
# update concept_set references
self.sheerka.services[SheerkaModifyConcept.NAME].update_references(context, concept_set)
self.concepts_in_set.delete(concept_set.id)
return res
def add_concept_to_set(self, context, concept, concept_set):
"""