First version of explain. Creating a new parser was a wrong approach. Need to reimplement

This commit is contained in:
2020-04-17 17:24:57 +02:00
parent 6c7c529016
commit d6ea2461a8
43 changed files with 2679 additions and 162 deletions
+69
View File
@@ -3,6 +3,7 @@ import time
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.Services.SheerkaExecute import NO_MATCH
from core.sheerka_logger import get_logger
from sdp.sheerkaDataProvider import Event
@@ -261,6 +262,74 @@ class ExecutionContext:
return False
@staticmethod
def _is_return_value(obj):
return isinstance(obj, Concept) and obj.key == str(BuiltinConcepts.RETURN_VALUE)
def _at_least_one_success(self, return_values):
status = False
for ret_val in return_values:
if not self._is_return_value(ret_val):
return None
status |= ret_val.status
return status
def _all_success(self, return_values):
status = True
for ret_val in return_values:
if not self._is_return_value(ret_val):
return None
status &= ret_val.status
return status
def get_status(self):
# In the function, I cannot use sheerka.isinstance() as self.sheerka may not be initialized
# This is the case when ExecutionContext is deserialized
if "return_values" not in self.values:
return None
if hasattr(self.values["return_values"], "__iter__"):
values = self.values["return_values"]
if len(values) == 0:
return None
if isinstance(values, str):
return "No Match" if values == NO_MATCH else values
if isinstance(values[0], dict):
for result in values:
if "return_value" not in result:
return None
if self._is_return_value(result["return_value"]):
return result["return_value"].status
return "No Match"
else:
return self._at_least_one_success(self.values["return_values"])
else:
ret_val = self.values["return_values"]
if not isinstance(ret_val, Concept) or not ret_val.key == str(BuiltinConcepts.RETURN_VALUE):
return None
return ret_val.status
def to_bag(self):
"""
Creates a dictionary with the useful properties of the concept
It quicker to implement than creating the actual property mechanism with @property
And it removes the visibility from the other attributes/methods
"""
bag = {}
for k, v in self._bag.items():
bag[k] = v
bag["bag." + k] = v
for prop in ("id", "who", "desc", "obj", "inputs", "values", "concepts"):
bag[prop] = getattr(self, prop)
bag["status"] = self.get_status()
bag["elapsed"] = self.elapsed
bag["digest"] = self.event.get_digest() if self.event else None
return bag
@staticmethod
def return_value_to_str(r):
value = str(r.value)
+1 -1
View File
@@ -86,7 +86,7 @@ class SheerkaDump:
while True:
try:
if h.event.user != self.sheerka.name:
if h.result:
self.sheerka.log.info(h)
count += 1
h = next(history)
+3 -2
View File
@@ -1,6 +1,7 @@
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
import core.utils
NO_MATCH = "** No Match **"
class SheerkaExecute:
"""
@@ -159,7 +160,7 @@ class SheerkaExecute:
evaluated_items.append(result)
debug_result.append({"input": item, "return_value": result})
else:
debug_result.append({"input": item, "return_value": "** No Match **"})
debug_result.append({"input": item, "return_value": NO_MATCH})
sub_context.add_values(return_values=debug_result)
# process evaluators that work on all return values
@@ -175,7 +176,7 @@ class SheerkaExecute:
to_delete.extend(result.parents)
sub_context.add_values(return_values=results)
else:
sub_context.add_values(return_values="** No Match **")
sub_context.add_values(return_values=NO_MATCH)
return_values = evaluated_items
return_values.extend([item for item in original_items if item not in to_delete])
@@ -2,7 +2,7 @@ from collections import namedtuple
from sdp.sheerkaDataProvider import Event
hist = namedtuple("History", "text status") # tests purposes only
hist = namedtuple("HistoryTest", "text status") # tests purposes only
class History:
@@ -38,34 +38,23 @@ class History:
if self._status:
return self._status
if not self.result or "return_values" not in self.result.values:
return
if hasattr(self.result.values["return_values"], "__iter__"):
if len(self.result.values["return_values"]) != 1:
self._status = False
return self._status
else:
self._status = self.result.values["return_values"][0].status
return self._status
else:
self._status = self.result.values["return_values"].status
return self._status
self._status = self.result.get_status() if self.result else None
return self._status
class SheerkaHistoryManager:
def __init__(self, sheerka):
self.sheerka = sheerka
def history(self, depth_or_digest, start):
def history(self, depth, start):
"""
Load history
:param depth_or_digest: number of items or digest
:param depth: number of items
:param start:
:return:
"""
events = list(self.sheerka.sdp.load_events(depth_or_digest, start))
events = list(self.sheerka.sdp.load_events(depth, start))
for event in events:
try:
result = self.sheerka.sdp.load_result(event.get_digest())
@@ -0,0 +1,54 @@
from dataclasses import dataclass
from typing import List
from sdp.sheerkaSerializer import Serializer
@dataclass
class Variable:
"""
Variable to store
"""
event_id: str # event where the variable is modified
who: str # who is the modifier
key: str # key of the variable
value: object # value
parents: List[str] # previous references of the variable (Note that there should be only one parent)
def get_key(self):
return f"{self.who}.{self.key}"
class SheerkaVariableManager:
VARIABLES_ENTRY = "All_Variables" # to store all the concepts
def __init__(self, sheerka):
self.sheerka = sheerka
def record(self, context, who, key, value):
"""Persist a variable"""
# first check if there is a previous version of the variable
try:
old = self.sheerka.sdp.get(self.VARIABLES_ENTRY, who + "." + key)
if old.value == value:
return
parent = getattr(old, Serializer.ORIGIN)
except IndexError:
parent = None
variable = Variable(context.event.get_digest(), who, key, value, [parent] if parent else None)
self.sheerka.sdp.set(context.event.get_digest(), self.VARIABLES_ENTRY, variable, use_ref=True)
def load(self, who, key):
variable = self.sheerka.sdp.get_safe(self.VARIABLES_ENTRY, who + "." + key)
if variable is None:
return None
return variable.value
def delete(self, context, who, key):
self.sheerka.sdp.remove(
context.event.get_digest(),
self.VARIABLES_ENTRY,
lambda _key, _var: _key == who + "." + key)
+44 -9
View File
@@ -1,3 +1,7 @@
import logging
import core.builtin_helpers
import core.utils
from core.builtin_concepts import BuiltinConcepts, ErrorConcept, ReturnValueConcept, BuiltinErrors, BuiltinUnique, \
UnknownConcept
from core.concept import Concept, ConceptParts, PROPERTIES_FOR_NEW
@@ -9,13 +13,10 @@ from core.sheerka.Services.SheerkaExecute import SheerkaExecute
from core.sheerka.Services.SheerkaHistoryManager import SheerkaHistoryManager
from core.sheerka.Services.SheerkaModifyConcept import SheerkaModifyConcept
from core.sheerka.Services.SheerkaSetsManager import SheerkaSetsManager
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
import core.utils
import core.builtin_helpers
from core.sheerka.Services.SheerkaVariableManager import SheerkaVariableManager
from core.sheerka_logger import console_handler
import logging
from printer.SheerkaPrinter import SheerkaPrinter
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
CONCEPT_LEXER_PARSER_CLASS = "parsers.BnfNodeParser.BnfNodeParser"
BNF_PARSER_CLASS = "parsers.BnfParser.BnfParser"
@@ -93,6 +94,8 @@ class Sheerka(Concept):
self.sets_handler = SheerkaSetsManager(self)
self.evaluate_concept_handler = SheerkaEvaluateConcept(self)
self.history_handler = SheerkaHistoryManager(self)
self.printer_handler = SheerkaPrinter(self)
self.variable_handler = SheerkaVariableManager(self)
self.during_restore = False
self._builtins_classes_cache = None
@@ -127,7 +130,7 @@ class Sheerka(Concept):
exec_context.add_values(return_values=res)
if not self.skip_builtins_in_db:
self.sdp.save_result(exec_context)
self.sdp.save_result(exec_context, is_admin=True)
self.init_log.debug(f"Sheerka successfully initialized")
except IOError as e:
@@ -299,9 +302,26 @@ class Sheerka(Concept):
# if len(ret) == 1 and ret[0].status and self.isinstance(ret[0].value, BuiltinConcepts.NEW_CONCEPT):
# with open(CONCEPTS_FILE, "a") as f:
# f.write(text + "\n")
return ret
def print(self, result, instructions=None):
"""
Print the result to output
:param result:
:param instructions:
:return:
"""
self.printer_handler.print(result, instructions)
def record(self, context, who, key, value):
return self.variable_handler.record(context, who, key, value)
def load(self, who, key):
return self.variable_handler.load(who, key)
def delete(self, context, who, key):
return self.variable_handler.delete(context, who, key)
def execute(self, execution_context, return_values, execution_steps):
"""
Executes process for all initial contexts
@@ -639,12 +659,27 @@ class Sheerka(Concept):
return self.value(body_to_use)
def value_by_concept(self, obj, concept):
if obj is None:
return None
if not isinstance(obj, Concept):
return None
if isinstance(concept, tuple) and obj.key in [str(key) for key in concept]:
return obj
if obj.key == str(concept):
return obj
return self.value_by_concept(obj.body, concept)
def get_error(self, obj):
if isinstance(obj, Concept) and obj.metadata.is_builtin and obj.key in BuiltinErrors:
return obj
if isinstance(obj, list):
return obj
return obj
if self.isinstance(obj, BuiltinConcepts.RETURN_VALUE):
if obj.status: