Logger is now an attribute of the execution context
This commit is contained in:
@@ -32,13 +32,12 @@ def is_same_success(sheerka, return_values):
|
||||
return True
|
||||
|
||||
|
||||
def expect_one(context, return_values, logger=None):
|
||||
def expect_one(context, return_values):
|
||||
"""
|
||||
Checks if there is at least one success return value
|
||||
If there is more than one, check if it's the same value
|
||||
:param context:
|
||||
:param return_values:
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
|
||||
@@ -75,10 +74,10 @@ def expect_one(context, return_values, logger=None):
|
||||
successful_results[0].value,
|
||||
parents=return_values)
|
||||
else:
|
||||
if logger and logger.isEnabledFor(logging.DEBUG):
|
||||
context.log(logger, f"Too many successful results found by expect_one()", context.who)
|
||||
if context.logger and context.logger.isEnabledFor(logging.DEBUG):
|
||||
context.log(f"Too many successful results found by expect_one()", context.who)
|
||||
for s in successful_results:
|
||||
context.log(logger, f"-> {s}", context.who)
|
||||
context.log(f"-> {s}", context.who)
|
||||
return sheerka.ret(
|
||||
context.who,
|
||||
False,
|
||||
@@ -86,10 +85,10 @@ def expect_one(context, return_values, logger=None):
|
||||
parents=return_values)
|
||||
|
||||
# only errors, i cannot help you
|
||||
if logger and logger.isEnabledFor(logging.DEBUG):
|
||||
context.log(logger, f"Too many errors found by expect_one()", context.who)
|
||||
if context.logger and context.logger.isEnabledFor(logging.DEBUG):
|
||||
context.log(f"Too many errors found by expect_one()", context.who)
|
||||
for s in successful_results:
|
||||
context.log(logger, f"-> {s}", context.who)
|
||||
context.log(f"-> {s}", context.who)
|
||||
|
||||
if len(return_values) == 1:
|
||||
return sheerka.ret(
|
||||
|
||||
@@ -3,8 +3,8 @@ import time
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.sheerka_logger import get_logger
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
from sheerkapickle.SheerkaPickler import SheerkaPickler
|
||||
|
||||
DEBUG_TAB_SIZE = 4
|
||||
|
||||
@@ -21,6 +21,8 @@ PROPERTIES_TO_SERIALIZE = ("_id",
|
||||
"concepts")
|
||||
|
||||
|
||||
|
||||
|
||||
class ExecutionContext:
|
||||
"""
|
||||
To keep track of the execution of a request
|
||||
@@ -41,6 +43,7 @@ class ExecutionContext:
|
||||
event: Event,
|
||||
sheerka,
|
||||
desc: str = None,
|
||||
logger=None,
|
||||
**kwargs):
|
||||
|
||||
self._parent = None
|
||||
@@ -56,6 +59,7 @@ class ExecutionContext:
|
||||
self.desc = desc # human description of what is going on
|
||||
self.children = []
|
||||
self.preprocess = None
|
||||
self.logger = logger
|
||||
|
||||
self.inputs = {} # what was the parameters of the execution context
|
||||
self.values = {} # what was produced by the execution context
|
||||
@@ -66,6 +70,9 @@ class ExecutionContext:
|
||||
for k, v in kwargs.items():
|
||||
self._bag[k] = v
|
||||
|
||||
self.stat_log = get_logger("stats")
|
||||
self.show_stats = False
|
||||
|
||||
@property
|
||||
def elapsed(self):
|
||||
if self._start == 0:
|
||||
@@ -91,10 +98,13 @@ class ExecutionContext:
|
||||
|
||||
def __enter__(self):
|
||||
self._start = time.time_ns()
|
||||
self.log_new()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self._stop = time.time_ns()
|
||||
if self.show_stats:
|
||||
self.stat_log.debug(f"[{self._id:2}]" + self._tab + "Execution time: " + self.elapsed_str)
|
||||
|
||||
def __repr__(self):
|
||||
msg = f"ExecutionContext(who={self.who}, id={self._id}"
|
||||
@@ -103,6 +113,11 @@ class ExecutionContext:
|
||||
msg += ")"
|
||||
return msg
|
||||
|
||||
def __str__(self):
|
||||
msg = self.desc or "New Context"
|
||||
msg += f", who={self.who}, id={self.id}"
|
||||
return msg
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
@@ -183,8 +198,9 @@ class ExecutionContext:
|
||||
|
||||
return self.sheerka.new(key, **kwargs)
|
||||
|
||||
def push(self, who=None, desc=None, **kwargs):
|
||||
def push(self, who=None, desc=None, logger=None, **kwargs):
|
||||
who = who or self.who
|
||||
logger = logger or self.logger
|
||||
_kwargs = {"obj": self.obj, "concepts": self.concepts}
|
||||
_kwargs.update(self._bag)
|
||||
_kwargs.update(kwargs)
|
||||
@@ -193,6 +209,7 @@ class ExecutionContext:
|
||||
self.event,
|
||||
self.sheerka,
|
||||
desc,
|
||||
logger,
|
||||
**_kwargs,
|
||||
)
|
||||
new._parent = self
|
||||
@@ -202,25 +219,29 @@ class ExecutionContext:
|
||||
self.children.append(new)
|
||||
return new
|
||||
|
||||
def log_new(self, logger):
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + str(self))
|
||||
def log_new(self):
|
||||
if self.logger and not self.logger.disabled:
|
||||
self.logger.debug(f"[{self._id:2}]" + self._tab + str(self))
|
||||
self.show_stats = True
|
||||
|
||||
def log(self, logger, message, who=None):
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
def log(self, message, who=None):
|
||||
if self.logger and not self.logger.disabled:
|
||||
self.logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
|
||||
def log_error(self, logger, message, who=None):
|
||||
logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
def log_error(self, message, who=None):
|
||||
if self.logger and not self.logger.disabled:
|
||||
self.logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
|
||||
def log_result(self, logger, return_values):
|
||||
if not logger.isEnabledFor(logging.DEBUG):
|
||||
def log_result(self, return_values):
|
||||
if not self.logger or not self.logger.isEnabledFor(logging.DEBUG):
|
||||
return
|
||||
|
||||
if len(return_values) == 0:
|
||||
logger.debug(self._tab + "No return value")
|
||||
self.logger.debug(self._tab + "No return value")
|
||||
|
||||
for r in return_values:
|
||||
to_str = self.return_value_to_str(r)
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
|
||||
self.logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
|
||||
|
||||
def get_parent(self):
|
||||
return self._parent
|
||||
|
||||
@@ -14,7 +14,7 @@ class SheerkaCreateNewConcept:
|
||||
self.sheerka = sheerka
|
||||
self.logger_name = self.create_new_concept.__name__
|
||||
|
||||
def create_new_concept(self, context, concept: Concept, logger=None):
|
||||
def create_new_concept(self, context, concept: Concept):
|
||||
"""
|
||||
Adds a new concept to the system
|
||||
:param context:
|
||||
@@ -23,8 +23,6 @@ class SheerkaCreateNewConcept:
|
||||
:return: digest of the new concept
|
||||
"""
|
||||
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
concept.init_key()
|
||||
concepts_definitions = None
|
||||
init_ret_value = None
|
||||
@@ -52,7 +50,6 @@ class SheerkaCreateNewConcept:
|
||||
concept_lexer_parser = self.sheerka.parsers[CONCEPT_LEXER_PARSER_CLASS]()
|
||||
with context.push(self.sheerka.name, desc=f"Initializing concept definition for {concept}") as sub_context:
|
||||
sub_context.concepts[concept.key] = concept # the concept is not in the real cache yet
|
||||
sub_context.log_new(logger)
|
||||
init_ret_value = concept_lexer_parser.initialize(sub_context, concepts_definitions)
|
||||
sub_context.add_values(return_values=init_ret_value)
|
||||
if not init_ret_value.status:
|
||||
@@ -83,7 +80,7 @@ class SheerkaCreateNewConcept:
|
||||
use_ref=True)
|
||||
self.sheerka.concepts_definitions_cache = None # invalidate cache
|
||||
except SheerkaDataProviderDuplicateKeyError as error:
|
||||
context.log_error(logger, "Failed to create a new concept.", who=self.logger_name)
|
||||
context.log_error("Failed to create a new concept.", who=self.logger_name)
|
||||
return self.sheerka.ret(
|
||||
self.logger_name,
|
||||
False,
|
||||
|
||||
@@ -58,6 +58,11 @@ class SheerkaDump:
|
||||
self.sheerka.log.info(f"body : {c.metadata.body}")
|
||||
if eval:
|
||||
self.sheerka.log.info(f"value : {value}")
|
||||
for p in c.props:
|
||||
self.sheerka.log.info(f"{p}: {c.get_prop(p)}")
|
||||
else:
|
||||
self.sheerka.log.info("No property")
|
||||
|
||||
self.sheerka.log.info(f"digest : {c.get_digest()}")
|
||||
|
||||
if self.sheerka.isaset(context, c):
|
||||
|
||||
@@ -62,7 +62,7 @@ class SheerkaEvaluateConcept:
|
||||
False,
|
||||
self.sheerka.new(BuiltinConcepts.CHICKEN_AND_EGG, body=concepts_found))
|
||||
|
||||
def initialize_concept_asts(self, context, concept: Concept, logger=None):
|
||||
def initialize_concept_asts(self, context, concept: Concept):
|
||||
"""
|
||||
Updates the codes of the newly created concept
|
||||
Basically, it runs the parsers on all parts
|
||||
@@ -84,11 +84,10 @@ class SheerkaEvaluateConcept:
|
||||
concept.compiled[part_key] = DoNotResolve(source)
|
||||
else:
|
||||
with context.push(desc=f"Initializing compiled for {part_key}") as sub_context:
|
||||
sub_context.log_new(logger)
|
||||
sub_context.add_inputs(source=source)
|
||||
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, logger)
|
||||
res = self.sheerka.execute(sub_context, to_parse, steps)
|
||||
concept.compiled[part_key] = res
|
||||
sub_context.add_values(return_values=res)
|
||||
|
||||
@@ -103,7 +102,6 @@ class SheerkaEvaluateConcept:
|
||||
concept.compiled[prop] = DoNotResolve(default_value)
|
||||
else:
|
||||
with context.push(desc=f"Initializing AST for property {prop}") as sub_context:
|
||||
sub_context.log_new(logger)
|
||||
sub_context.add_inputs(source=default_value)
|
||||
to_parse = self.sheerka.ret(context.who, True,
|
||||
self.sheerka.new(BuiltinConcepts.USER_INPUT, body=default_value))
|
||||
@@ -120,7 +118,7 @@ class SheerkaEvaluateConcept:
|
||||
else:
|
||||
self.sheerka.cache_by_key[concept.key].compiled = concept.compiled
|
||||
|
||||
def resolve(self, context, to_resolve, current_prop, current_concept, logger):
|
||||
def resolve(self, context, to_resolve, current_prop, current_concept):
|
||||
if isinstance(to_resolve, DoNotResolve):
|
||||
return to_resolve.value
|
||||
|
||||
@@ -128,20 +126,18 @@ class SheerkaEvaluateConcept:
|
||||
if self.infinite_recursion_detected(context, current_concept):
|
||||
with context.push(desc="Infinite recursion detected", obj=current_concept) as sub_context:
|
||||
# I create a sub context in order to log what happened
|
||||
sub_context.log_new(logger)
|
||||
ret_val = self.manage_infinite_recursion(context)
|
||||
sub_context.add_values(return_values=ret_val)
|
||||
return ret_val.body
|
||||
|
||||
desc = f"Evaluating {current_prop} (concept={current_concept})"
|
||||
context.log(logger, desc, self.logger_name)
|
||||
context.log(desc, self.logger_name)
|
||||
with context.push(desc=desc, obj=current_concept) as sub_context:
|
||||
sub_context.log_new(logger)
|
||||
|
||||
# when it's a concept, evaluate it
|
||||
if isinstance(to_resolve, Concept) and \
|
||||
not context.sheerka.isinstance(to_resolve, BuiltinConcepts.RETURN_VALUE):
|
||||
evaluated = self.evaluate_concept(sub_context, to_resolve, logger)
|
||||
evaluated = self.evaluate_concept(sub_context, to_resolve)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
if evaluated.key == to_resolve.key:
|
||||
return evaluated
|
||||
@@ -151,7 +147,7 @@ class SheerkaEvaluateConcept:
|
||||
# otherwise, execute all return values to find out what is the value
|
||||
else:
|
||||
use_copy = [r for r in to_resolve] if hasattr(to_resolve, "__iter__") else to_resolve
|
||||
r = self.sheerka.execute(sub_context, use_copy, CONCEPT_EVALUATION_STEPS, logger)
|
||||
r = self.sheerka.execute(sub_context, use_copy, CONCEPT_EVALUATION_STEPS)
|
||||
one_r = core.builtin_helpers.expect_one(context, r)
|
||||
sub_context.add_values(return_values=one_r)
|
||||
if one_r.status:
|
||||
@@ -165,7 +161,7 @@ class SheerkaEvaluateConcept:
|
||||
concept=current_concept,
|
||||
property_name=current_prop)
|
||||
|
||||
def resolve_list(self, context, list_to_resolve, current_prop, current_concept, logger):
|
||||
def resolve_list(self, context, list_to_resolve, current_prop, current_concept):
|
||||
"""When dealing with a list, there are two possibilities"""
|
||||
# It may be a list of ReturnValueConcept to execute (always the case for metadata)
|
||||
# or a list of single values (may be the case for properties)
|
||||
@@ -174,7 +170,7 @@ class SheerkaEvaluateConcept:
|
||||
return []
|
||||
|
||||
if self.sheerka.isinstance(list_to_resolve[0], BuiltinConcepts.RETURN_VALUE):
|
||||
return self.resolve(context, list_to_resolve, current_prop, current_concept, logger)
|
||||
return self.resolve(context, list_to_resolve, current_prop, current_concept)
|
||||
|
||||
res = []
|
||||
for to_resolve in list_to_resolve:
|
||||
@@ -185,14 +181,14 @@ class SheerkaEvaluateConcept:
|
||||
concept=current_concept,
|
||||
property_name=current_prop)
|
||||
|
||||
r = self.resolve(context, to_resolve, current_prop, current_concept, logger)
|
||||
r = self.resolve(context, to_resolve, current_prop, current_concept)
|
||||
if self.sheerka.isinstance(r, BuiltinConcepts.CONCEPT_EVAL_ERROR):
|
||||
return r
|
||||
res.append(r)
|
||||
|
||||
return res
|
||||
|
||||
def evaluate_concept(self, context, concept: Concept, logger=None):
|
||||
def evaluate_concept(self, context, concept: Concept):
|
||||
"""
|
||||
Evaluation a concept
|
||||
It means that if the where clause is True, will evaluate the body
|
||||
@@ -202,8 +198,6 @@ class SheerkaEvaluateConcept:
|
||||
:return: value of the evaluation or error
|
||||
"""
|
||||
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
if concept.metadata.is_evaluated:
|
||||
return concept
|
||||
|
||||
@@ -211,7 +205,7 @@ class SheerkaEvaluateConcept:
|
||||
# TODO : Validate the PRE condition
|
||||
#
|
||||
|
||||
self.initialize_concept_asts(context, concept, logger)
|
||||
self.initialize_concept_asts(context, concept)
|
||||
|
||||
# to make sure of the order, it don't use ConceptParts.get_parts()
|
||||
# props must be evaluated first, body must be evaluated before where
|
||||
@@ -224,10 +218,10 @@ class SheerkaEvaluateConcept:
|
||||
|
||||
if isinstance(prop_ast, list):
|
||||
# Do not send the current concept for the properties
|
||||
resolved = self.resolve_list(context, prop_ast, prop_name, None, logger)
|
||||
resolved = self.resolve_list(context, prop_ast, prop_name, None)
|
||||
else:
|
||||
# Do not send the current concept for the properties
|
||||
resolved = self.resolve(context, prop_ast, prop_name, None, logger)
|
||||
resolved = self.resolve(context, prop_ast, prop_name, None)
|
||||
if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved):
|
||||
resolved.set_prop("concept", concept) # since current concept was not sent
|
||||
return resolved
|
||||
@@ -243,7 +237,7 @@ class SheerkaEvaluateConcept:
|
||||
|
||||
if part_key in concept.compiled and concept.compiled[part_key] is not None:
|
||||
metadata_ast = concept.compiled[part_key]
|
||||
resolved = self.resolve(context, metadata_ast, part_key, concept, logger)
|
||||
resolved = self.resolve(context, metadata_ast, part_key, concept)
|
||||
if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved):
|
||||
return resolved
|
||||
else:
|
||||
|
||||
@@ -10,7 +10,7 @@ class SheerkaExecute:
|
||||
def __init__(self, sheerka):
|
||||
self.sheerka = sheerka
|
||||
|
||||
def call_parsers(self, execution_context, return_values, logger=None):
|
||||
def call_parsers(self, execution_context, return_values):
|
||||
|
||||
# return_values must be a list
|
||||
if not isinstance(return_values, list):
|
||||
@@ -35,8 +35,6 @@ class SheerkaExecute:
|
||||
instantiated_parsers = [parser(sheerka=self.sheerka) for parser in self.sheerka.parsers.values()]
|
||||
grouped_parsers = {}
|
||||
for parser in [p for p in instantiated_parsers if p.enabled]:
|
||||
if logger:
|
||||
parser.log = logger
|
||||
grouped_parsers.setdefault(parser.priority, []).append(parser)
|
||||
sorted_priorities = sorted(grouped_parsers.keys(), reverse=True)
|
||||
|
||||
@@ -56,9 +54,9 @@ class SheerkaExecute:
|
||||
# if self.sheerka.log.isEnabledFor(logging.DEBUG):
|
||||
# debug_text = "'" + to_parse + "'" if isinstance(to_parse, str) \
|
||||
# else "'" + BaseParser.get_text_from_tokens(to_parse) + "' as tokens"
|
||||
# execution_context.log(logger or self.sheerka.log, f"Parsing {debug_text}")
|
||||
# execution_context.log(f"Parsing {debug_text}")
|
||||
|
||||
with execution_context.push(desc=f"Parsing using {parser.name}") as sub_context:
|
||||
with execution_context.push(desc=f"Parsing using {parser.name}", logger=parser.verbose_log) as sub_context:
|
||||
sub_context.add_inputs(to_parse=to_parse)
|
||||
res = parser.parse(sub_context, to_parse)
|
||||
if res is not None:
|
||||
@@ -92,7 +90,7 @@ class SheerkaExecute:
|
||||
result = core.utils.remove_list_from_list(result, user_inputs)
|
||||
return result
|
||||
|
||||
def call_evaluators(self, execution_context, return_values, process_step, evaluation_context=None, logger=None):
|
||||
def call_evaluators(self, execution_context, return_values, process_step, evaluation_context=None):
|
||||
|
||||
# return_values must be a list
|
||||
if not isinstance(return_values, list):
|
||||
@@ -122,8 +120,6 @@ class SheerkaExecute:
|
||||
instantiated_evaluators = self._preprocess_evaluators(execution_context, instantiated_evaluators)
|
||||
|
||||
for evaluator in [e for e in instantiated_evaluators if e.enabled and process_step in e.steps]:
|
||||
if logger:
|
||||
evaluator.log = logger
|
||||
grouped_evaluators.setdefault(evaluator.priority, []).append(evaluator)
|
||||
|
||||
# order the groups by priority, the higher first
|
||||
@@ -145,7 +141,7 @@ class SheerkaExecute:
|
||||
evaluator = self._preprocess_evaluators(execution_context, evaluator.__class__()) # fresh copy
|
||||
|
||||
sub_context_desc = f"Evaluating using {evaluator.name} ({priority=})"
|
||||
with iteration_context.push(desc=sub_context_desc) as sub_context:
|
||||
with iteration_context.push(desc=sub_context_desc, logger=evaluator.verbose_log) as sub_context:
|
||||
sub_context.add_inputs(return_values=original_items)
|
||||
|
||||
# process evaluators that work on one simple return value at the time
|
||||
@@ -206,28 +202,26 @@ class SheerkaExecute:
|
||||
return_values = core.utils.remove_list_from_list(return_values, evaluation_return_values)
|
||||
return return_values
|
||||
|
||||
def execute(self, execution_context, return_values, execution_steps, logger=None):
|
||||
def execute(self, execution_context, return_values, execution_steps):
|
||||
"""
|
||||
Executes process for all initial contexts
|
||||
:param execution_context:
|
||||
:param return_values:
|
||||
:param execution_steps:
|
||||
:param logger: logger to use (if not directly called by sheerka)
|
||||
:return:
|
||||
"""
|
||||
|
||||
for step in execution_steps:
|
||||
copy = return_values[:] if hasattr(return_values, "__iter__") else [return_values]
|
||||
with execution_context.push(step=step, iteration=0, desc=f"{step=}") as sub_context:
|
||||
sub_context.log(logger or self.sheerka.log, f"{step=}, context='{sub_context}'")
|
||||
|
||||
if step == BuiltinConcepts.PARSING:
|
||||
return_values = self.call_parsers(sub_context, return_values, logger)
|
||||
return_values = self.call_parsers(sub_context, return_values)
|
||||
else:
|
||||
return_values = self.call_evaluators(sub_context, return_values, step, None, logger)
|
||||
return_values = self.call_evaluators(sub_context, return_values, step, None)
|
||||
|
||||
if copy != return_values:
|
||||
sub_context.log_result(logger or self.sheerka.log, return_values)
|
||||
sub_context.log_result(return_values)
|
||||
|
||||
sub_context.add_values(return_values=return_values)
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ class SheerkaModifyConcept:
|
||||
self.sheerka = sheerka
|
||||
self.logger_name = self.modify_concept.__name__
|
||||
|
||||
def modify_concept(self, context, concept, logger=None):
|
||||
logger = logger or self.sheerka.log
|
||||
def modify_concept(self, context, concept):
|
||||
|
||||
self.sheerka.sdp.modify(context.event.get_digest(), self.sheerka.CONCEPTS_ENTRY, concept.key, concept)
|
||||
|
||||
|
||||
@@ -11,42 +11,38 @@ class SheerkaSetsManager:
|
||||
self.sheerka = sheerka
|
||||
self.logger_name = self.add_concept_to_set.__name__
|
||||
|
||||
def set_isa(self, context, concept, concept_set, logger=None):
|
||||
def set_isa(self, context, concept, concept_set):
|
||||
"""
|
||||
Defines that concept a is b is another concept
|
||||
:param context:
|
||||
:param concept:
|
||||
:param concept_set:
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
|
||||
logger = logger or self.sheerka.log
|
||||
context.log(logger, f"Setting that concept {concept} is a {concept_set}", who=self.logger_name)
|
||||
context.log(f"Setting that concept {concept} is a {concept_set}", who=self.logger_name)
|
||||
|
||||
isa = [] if BuiltinConcepts.ISA not in concept.props else concept.get_prop(BuiltinConcepts.ISA)
|
||||
if concept_set not in isa:
|
||||
isa.append(concept_set)
|
||||
|
||||
concept.set_prop(BuiltinConcepts.ISA, isa)
|
||||
res = self.sheerka.modify_concept(context, concept, logger)
|
||||
res = self.sheerka.modify_concept(context, concept)
|
||||
if not res.status:
|
||||
return res
|
||||
|
||||
return self.add_concept_to_set(context, concept, concept_set, logger)
|
||||
return self.add_concept_to_set(context, concept, concept_set)
|
||||
|
||||
def add_concept_to_set(self, context, concept, concept_set, logger=None):
|
||||
def add_concept_to_set(self, context, concept, concept_set):
|
||||
"""
|
||||
Add an entry in sdp to tell that concept isa concept_set
|
||||
:param context:
|
||||
:param concept:
|
||||
:param concept_set:
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
context.log(logger, f"Adding concept {concept} to set {concept_set}", who=self.logger_name)
|
||||
context.log(f"Adding concept {concept} to set {concept_set}", who=self.logger_name)
|
||||
|
||||
assert concept.id
|
||||
assert concept_set.id
|
||||
@@ -61,14 +57,13 @@ class SheerkaSetsManager:
|
||||
else:
|
||||
return self.sheerka.ret(self.logger_name, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
except Exception as error:
|
||||
context.log_error(logger, "Failed to add to set.", who=self.logger_name)
|
||||
context.log_error("Failed to add to set.", who=self.logger_name)
|
||||
return self.sheerka.ret(self.logger_name, False, ErrorConcept(error), error.args[0])
|
||||
|
||||
def add_concepts_to_set(self, context, concepts, concept_set, logger=None):
|
||||
def add_concepts_to_set(self, context, concepts, concept_set):
|
||||
"""Adding multiple concepts at the same time"""
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
context.log(logger, f"Adding concepts {concepts} to set {concept_set}", who=self.logger_name)
|
||||
context.log(f"Adding concepts {concepts} to set {concept_set}", who=self.logger_name)
|
||||
previous = self.sheerka.sdp.get_safe(GROUP_PREFIX + concept_set.id)
|
||||
|
||||
new_ids = [c.id for c in concepts] if previous is None else previous + [c.id for c in concepts]
|
||||
@@ -76,21 +71,18 @@ class SheerkaSetsManager:
|
||||
self.sheerka.sdp.set(context.event.get_digest(), GROUP_PREFIX + concept_set.id, new_ids)
|
||||
return self.sheerka.ret(self.logger_name, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||
except Exception as error:
|
||||
context.log_error(logger, "Failed to add to set.", who=self.logger_name)
|
||||
context.log_error("Failed to add to set.", who=self.logger_name)
|
||||
return self.sheerka.ret(self.logger_name, False, ErrorConcept(error), error.args[0])
|
||||
|
||||
def get_set_elements(self, context, concept, logger=None):
|
||||
def get_set_elements(self, context, concept):
|
||||
"""
|
||||
Concept is supposed to be a set
|
||||
Returns all elements if the set
|
||||
:param context:
|
||||
:param concept:
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def _get_set_elements(context, concept, sub_concept):
|
||||
if not (isinstance(sub_concept, Concept) and sub_concept.id):
|
||||
@@ -105,13 +97,13 @@ class SheerkaSetsManager:
|
||||
else:
|
||||
# This methods sucks, but I don't have enough tools (like proper AST manipulation functions)
|
||||
# to do it properly now. It will be enhanced later
|
||||
concepts = self._get_concepts(context, ids, True, logger)
|
||||
concepts = self._get_concepts(context, ids, True)
|
||||
globals_ = {"xx__concepts__xx": concepts, "sheerka": self.sheerka}
|
||||
locals_ = {}
|
||||
exec(new_condition, globals_, locals_)
|
||||
return locals_["result"]
|
||||
else:
|
||||
return self._get_concepts(context, ids, False, logger)
|
||||
return self._get_concepts(context, ids, False)
|
||||
|
||||
# it may be a concept that references a set
|
||||
if not sub_concept.metadata.is_evaluated:
|
||||
@@ -160,30 +152,27 @@ class SheerkaSetsManager:
|
||||
|
||||
return False
|
||||
|
||||
def isaset(self, context, concept, logger=None):
|
||||
def isaset(self, context, concept):
|
||||
"""
|
||||
True if exists All_<concept_id> in sdp or if concept references to a concept that has all_<concept_id>
|
||||
:param context:
|
||||
:param concept:
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
""""""
|
||||
|
||||
logger = logger or self.sheerka.log
|
||||
|
||||
if not (isinstance(concept, Concept) and concept.id):
|
||||
return None
|
||||
|
||||
# it may be a concept that references a set
|
||||
if not concept.metadata.is_evaluated:
|
||||
with context.push(desc=f"Evaluating concept {concept}") as sub_context:
|
||||
evaluated = self.sheerka.evaluate_concept(sub_context, concept, logger)
|
||||
evaluated = self.sheerka.evaluate_concept(sub_context, concept)
|
||||
if evaluated.key != concept.key:
|
||||
return False
|
||||
|
||||
if concept.body:
|
||||
return self.isaset(context, concept.body, logger)
|
||||
return self.isaset(context, concept.body)
|
||||
|
||||
res = self.sheerka.sdp.get_safe(GROUP_PREFIX + concept.id)
|
||||
return res is not None
|
||||
@@ -211,7 +200,7 @@ for x in xx__concepts__xx:
|
||||
"""
|
||||
return expression
|
||||
|
||||
def _get_concepts(self, context, ids, evaluate, logger):
|
||||
def _get_concepts(self, context, ids, evaluate):
|
||||
"""
|
||||
Gets concepts from a list of concepts ids
|
||||
:param ids:
|
||||
@@ -229,7 +218,7 @@ for x in xx__concepts__xx:
|
||||
with context.push(desc=f"Evaluating concepts of a set") as sub_context:
|
||||
for element_id in ids:
|
||||
concept = self.sheerka.get_by_id(element_id)
|
||||
evaluated = self.sheerka.evaluate_concept(context, concept, logger)
|
||||
evaluated = self.sheerka.evaluate_concept(context, concept)
|
||||
result.append(evaluated)
|
||||
|
||||
return result
|
||||
|
||||
+34
-29
@@ -40,6 +40,7 @@ class Sheerka(Concept):
|
||||
|
||||
def __init__(self, skip_builtins_in_db=False, debug=False, loggers=None):
|
||||
self.init_logging(debug, loggers)
|
||||
self.loggers = loggers
|
||||
|
||||
super().__init__(BuiltinConcepts.SHEERKA, True, True, BuiltinConcepts.SHEERKA)
|
||||
self.log.debug("Starting Sheerka.")
|
||||
@@ -110,17 +111,18 @@ class Sheerka(Concept):
|
||||
|
||||
event = Event("Initializing Sheerka.", user=self.name)
|
||||
self.sdp.save_event(event)
|
||||
exec_context = ExecutionContext(self.key, event, self)
|
||||
with ExecutionContext(self.key, event, self, "Initializing Sheerka.", self.init_log) as exec_context:
|
||||
|
||||
self.initialize_builtin_concepts()
|
||||
self.initialize_builtin_parsers()
|
||||
self.initialize_builtin_evaluators()
|
||||
self.initialize_concepts_definitions(exec_context)
|
||||
res = ReturnValueConcept(self, True, self)
|
||||
self.initialize_builtin_concepts()
|
||||
self.initialize_builtin_parsers()
|
||||
self.initialize_builtin_evaluators()
|
||||
self.initialize_concepts_definitions(exec_context)
|
||||
res = ReturnValueConcept(self, True, self)
|
||||
|
||||
exec_context.add_values(return_values=res)
|
||||
if not self.skip_builtins_in_db:
|
||||
self.sdp.save_result(exec_context)
|
||||
exec_context.add_values(return_values=res)
|
||||
if not self.skip_builtins_in_db:
|
||||
self.sdp.save_result(exec_context)
|
||||
self.init_log.debug(f"Sheerka successfully initialized")
|
||||
|
||||
except IOError as e:
|
||||
res = ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e)
|
||||
@@ -191,8 +193,7 @@ class Sheerka(Concept):
|
||||
self.evaluators.append(evaluator)
|
||||
|
||||
def initialize_concepts_definitions(self, execution_context):
|
||||
self.init_log.debug("Initializing concepts definitions")
|
||||
# definitions = self.sdp.get_safe(self.CONCEPTS_DEFINITIONS_ENTRY, load_origin=False)
|
||||
self.init_log.debug("Initializing concepts grammars.")
|
||||
definitions = self.get_concepts_definitions(execution_context)
|
||||
|
||||
if definitions is None:
|
||||
@@ -234,7 +235,7 @@ class Sheerka(Concept):
|
||||
evt_digest = self.sdp.save_event(event)
|
||||
self.log.debug(f"{evt_digest=}")
|
||||
|
||||
with ExecutionContext(self.key, event, self, f"Evaluating '{text}'") as execution_context:
|
||||
with ExecutionContext(self.key, event, self, f"Evaluating '{text}'", self.log) as execution_context:
|
||||
user_input = self.ret(self.name, True, self.new(BuiltinConcepts.USER_INPUT, body=text, user_name=user_name))
|
||||
reduce_requested = self.ret(self.name, True, self.new(BuiltinConcepts.REDUCE_REQUESTED))
|
||||
|
||||
@@ -261,7 +262,7 @@ class Sheerka(Concept):
|
||||
|
||||
return ret
|
||||
|
||||
def execute(self, execution_context, return_values, execution_steps, logger=None):
|
||||
def execute(self, execution_context, return_values, execution_steps):
|
||||
"""
|
||||
Executes process for all initial contexts
|
||||
:param execution_context:
|
||||
@@ -270,7 +271,7 @@ class Sheerka(Concept):
|
||||
:param logger: logger to use (if not directly called by sheerka)
|
||||
:return:
|
||||
"""
|
||||
return self.execute_handler.execute(execution_context, return_values, execution_steps, logger)
|
||||
return self.execute_handler.execute(execution_context, return_values, execution_steps)
|
||||
|
||||
def set_id_if_needed(self, obj: Concept, is_builtin: bool):
|
||||
"""
|
||||
@@ -287,7 +288,7 @@ class Sheerka(Concept):
|
||||
obj.metadata.id = self.sdp.get_next_key(entry)
|
||||
self.log.debug(f"Setting id '{obj.metadata.id}' to concept '{obj.metadata.name}'.")
|
||||
|
||||
def create_new_concept(self, context, concept: Concept, logger=None):
|
||||
def create_new_concept(self, context, concept: Concept):
|
||||
"""
|
||||
Adds a new concept to the system
|
||||
:param context:
|
||||
@@ -296,12 +297,12 @@ class Sheerka(Concept):
|
||||
:return: digest of the new concept
|
||||
"""
|
||||
|
||||
return self.create_new_concept_handler.create_new_concept(context, concept, logger)
|
||||
return self.create_new_concept_handler.create_new_concept(context, concept)
|
||||
|
||||
def modify_concept(self, context, concept: Concept, logger):
|
||||
return self.modify_concept_handler.modify_concept(context, concept, logger)
|
||||
def modify_concept(self, context, concept: Concept):
|
||||
return self.modify_concept_handler.modify_concept(context, concept)
|
||||
|
||||
def add_concept_to_set(self, context, concept, concept_set, logger=None):
|
||||
def add_concept_to_set(self, context, concept, concept_set):
|
||||
"""
|
||||
Add an entry in sdp to tell that concept isa concept_set
|
||||
:param context:
|
||||
@@ -310,9 +311,9 @@ class Sheerka(Concept):
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
return self.sets_handler.add_concept_to_set(context, concept, concept_set, logger)
|
||||
return self.sets_handler.add_concept_to_set(context, concept, concept_set)
|
||||
|
||||
def set_isa(self, context, concept, concept_set, logger=None):
|
||||
def set_isa(self, context, concept, concept_set):
|
||||
"""
|
||||
|
||||
:param context:
|
||||
@@ -321,7 +322,7 @@ class Sheerka(Concept):
|
||||
:param logger:
|
||||
:return:
|
||||
"""
|
||||
return self.sets_handler.set_isa(context, concept, concept_set, logger)
|
||||
return self.sets_handler.set_isa(context, concept, concept_set)
|
||||
|
||||
def get_set_elements(self, context, concept):
|
||||
"""
|
||||
@@ -334,7 +335,7 @@ class Sheerka(Concept):
|
||||
|
||||
return self.sets_handler.get_set_elements(context, concept)
|
||||
|
||||
def evaluate_concept(self, context, concept: Concept, logger=None):
|
||||
def evaluate_concept(self, context, concept: Concept):
|
||||
"""
|
||||
Evaluation a concept
|
||||
It means that if the where clause is True, will evaluate the body
|
||||
@@ -343,7 +344,7 @@ class Sheerka(Concept):
|
||||
:param logger:
|
||||
:return: value of the evaluation or error
|
||||
"""
|
||||
return self.evaluate_concept_handler.evaluate_concept(context, concept, logger)
|
||||
return self.evaluate_concept_handler.evaluate_concept(context, concept)
|
||||
|
||||
def add_in_cache(self, concept: Concept):
|
||||
"""
|
||||
@@ -424,18 +425,20 @@ class Sheerka(Concept):
|
||||
return result
|
||||
|
||||
def get_concepts_definitions(self, context):
|
||||
|
||||
if self.concepts_definitions_cache:
|
||||
return self.concepts_definitions_cache
|
||||
|
||||
encoded = self.sdp.get_safe(
|
||||
encoded_bnf = self.sdp.get_safe(
|
||||
self.CONCEPTS_DEFINITIONS_ENTRY,
|
||||
load_origin=False) or {}
|
||||
|
||||
self.concepts_definitions_cache = {}
|
||||
bnf_parser = self.parsers[BNF_PARSER_CLASS]()
|
||||
for k, v in encoded.items():
|
||||
for k, v in encoded_bnf.items():
|
||||
key, id_ = core.utils.unstr_concept(k)
|
||||
concept = self.new((key, id_))
|
||||
context.log(f"Parsing BNF definition for {concept}", context.who)
|
||||
rule_result = bnf_parser.parse(context, v)
|
||||
if rule_result.status:
|
||||
self.concepts_definitions_cache[concept] = rule_result.value.value
|
||||
@@ -681,10 +684,12 @@ class Sheerka(Concept):
|
||||
|
||||
@staticmethod
|
||||
def init_logging(debug, loggers):
|
||||
core.sheerka_logger.set_enabled(loggers)
|
||||
core.sheerka_logger.init_config(loggers)
|
||||
if debug:
|
||||
# log_format = "%(asctime)s %(name)s [%(levelname)s] %(message)s"
|
||||
log_format = "%(asctime)s [%(levelname)s] %(message)s"
|
||||
log_format = "%(asctime)s"
|
||||
if "show-name" in loggers:
|
||||
log_format += " %(name)s"
|
||||
log_format += " [%(levelname)s] %(message)s"
|
||||
log_level = logging.DEBUG
|
||||
else:
|
||||
log_format = "%(message)s"
|
||||
|
||||
@@ -2,21 +2,32 @@ import logging
|
||||
import sys
|
||||
|
||||
enabled = []
|
||||
disabled = ["init", "sdp", "parsers", "evaluators", "verbose"]
|
||||
disabled = ["init", "sdp", "parsers", "evaluators", "verbose", "stats"]
|
||||
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
|
||||
all_loggers = {}
|
||||
|
||||
|
||||
def set_enabled(to_enable):
|
||||
if to_enable is None:
|
||||
def init_config(loggers):
|
||||
if loggers is None:
|
||||
return
|
||||
|
||||
if not hasattr(to_enable, "__iter__"):
|
||||
to_enable = [to_enable]
|
||||
if not hasattr(loggers, "__iter__"):
|
||||
loggers = [loggers]
|
||||
|
||||
enabled.extend(to_enable)
|
||||
if "all" in loggers:
|
||||
disabled.clear()
|
||||
|
||||
for logger in loggers:
|
||||
if logger == "all":
|
||||
continue
|
||||
|
||||
if logger.startswith("-"):
|
||||
disabled.append(logger[1:])
|
||||
elif logger.startswith("+"):
|
||||
enabled.append(logger[1:])
|
||||
else:
|
||||
enabled.append(logger)
|
||||
|
||||
|
||||
def to_discard(logger_class):
|
||||
@@ -40,7 +51,7 @@ def get_logger(logger_name):
|
||||
all_loggers[logger_name] = logger
|
||||
|
||||
for d in disabled:
|
||||
if logger_name.startswith(d + ".") and to_discard(d):
|
||||
if (logger_name == d or logger_name.startswith(d + ".")) and to_discard(d):
|
||||
logger.disabled = True
|
||||
|
||||
for e in enabled:
|
||||
|
||||
@@ -47,7 +47,7 @@ class AddConceptEvaluator(OneReturnValueEvaluator):
|
||||
isinstance(return_value.value.value, DefConceptNode)
|
||||
|
||||
def eval(self, context, return_value):
|
||||
context.log(self.log, "Adding a new concept", self.name)
|
||||
context.log("Adding a new concept", self.name)
|
||||
def_concept_node = return_value.value.value
|
||||
sheerka = context.sheerka
|
||||
|
||||
@@ -86,10 +86,10 @@ class AddConceptEvaluator(OneReturnValueEvaluator):
|
||||
sheerka.is_success(def_concept_node.definition):
|
||||
concept.bnf = def_concept_node.definition.value.value
|
||||
|
||||
ret = sheerka.create_new_concept(context, concept, self.verbose_log)
|
||||
ret = sheerka.create_new_concept(context, concept)
|
||||
if not ret.status:
|
||||
error_cause = sheerka.value(ret.body)
|
||||
context.log(self.log, f"Failed to add concept '{concept.name}'. Reason: {error_cause}", self.name)
|
||||
context.log(f"Failed to add concept '{concept.name}'. Reason: {error_cause}", self.name)
|
||||
return sheerka.ret(self.name, ret.status, ret.value, parents=[return_value])
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -34,14 +34,14 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator):
|
||||
sheerka.new(BuiltinConcepts.USER_INPUT, body=name_node.tokens, user_name="N/A"))
|
||||
|
||||
with context.push(desc=f"Recognizing '{name_node}'") as sub_context:
|
||||
r = sheerka.execute(sub_context, ret_val, ALL_STEPS, self.verbose_log)
|
||||
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)
|
||||
return one_r
|
||||
|
||||
isa_node = return_value.value.value
|
||||
sheerka = context.sheerka
|
||||
context.log(self.log, f"Adding a concept {isa_node.concept} to set {isa_node.set}", self.name)
|
||||
context.log(f"Adding concept '{isa_node.concept}' to set '{isa_node.set}'", self.name)
|
||||
|
||||
# Try to recognize the concept
|
||||
res = _resolve(isa_node.concept)
|
||||
@@ -62,11 +62,11 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator):
|
||||
parents=[return_value])
|
||||
concept_set = res.value
|
||||
|
||||
res = sheerka.add_concept_to_set(context, concept, concept_set, self.verbose_log)
|
||||
res = sheerka.set_isa(context, concept, concept_set)
|
||||
if not res.status:
|
||||
context.log(self.log, f"Failed. Reason: {sheerka.value(res.body)}.", self.name)
|
||||
context.log(f"Failed. Reason: {sheerka.value(res.body)}.", self.name)
|
||||
else:
|
||||
context.log(self.log, f"Concept added.", self.name)
|
||||
context.log(f"Concept added.", self.name)
|
||||
|
||||
return sheerka.ret(
|
||||
self.name,
|
||||
|
||||
@@ -24,7 +24,7 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
||||
def eval(self, context, return_value):
|
||||
sheerka = context.sheerka
|
||||
concept = return_value.value.value
|
||||
context.log(self.verbose_log, f"Evaluating concept {concept}.", self.name)
|
||||
context.log(f"Evaluating concept {concept}.", self.name)
|
||||
|
||||
# If the concept that is requested is in the context(at least its name), drop the call.
|
||||
# Why ?
|
||||
@@ -32,11 +32,11 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
||||
# The body should be 'property_a', and not a concept called 'a'
|
||||
if context.obj and concept.name in context.obj.props:
|
||||
value = context.obj.props[concept.name].value
|
||||
context.log(self.verbose_log, f"{concept.name} is a property. Returning value '{value}'.", self.name)
|
||||
context.log(f"{concept.name} is a property. Returning value '{value}'.", self.name)
|
||||
|
||||
return sheerka.ret(self.name, True, value, parents=[return_value])
|
||||
|
||||
evaluated = sheerka.evaluate_concept(context, concept, self.verbose_log)
|
||||
evaluated = sheerka.evaluate_concept(context, concept)
|
||||
|
||||
if evaluated.key != concept.key:
|
||||
# evaluated.key != concept.key means that we have transformed the concept
|
||||
|
||||
@@ -29,10 +29,10 @@ class EvalEvaluator(AllReturnValuesEvaluator):
|
||||
|
||||
for ret_val in return_values:
|
||||
if ret_val.status and isinstance(ret_val.body, Concept) and ret_val.body.body:
|
||||
context.log(self.verbose_log, f"Evaluating {ret_val.body}", who=self)
|
||||
context.log(f"Evaluating {ret_val.body}", who=self)
|
||||
result.append(sheerka.ret(self.name, True, ret_val.body.body, parents=[ret_val, self.eval_requested]))
|
||||
elif ret_val.status and sheerka.isaset(context, ret_val.body):
|
||||
context.log(self.verbose_log, f"Evaluating set {ret_val.body}", who=self)
|
||||
context.log(f"Evaluating set {ret_val.body}", who=self)
|
||||
result.append(sheerka.ret(
|
||||
self.name,
|
||||
True,
|
||||
|
||||
@@ -44,7 +44,7 @@ class LexerNodeEvaluator(OneReturnValueEvaluator):
|
||||
if not hasattr(nodes, "__iter__"):
|
||||
nodes = [nodes]
|
||||
|
||||
context.log(self.verbose_log, f"{nodes=}", self.name)
|
||||
context.log(f"{nodes=}", self.name)
|
||||
|
||||
for node in nodes:
|
||||
if isinstance(node, SourceCodeNode):
|
||||
|
||||
@@ -45,9 +45,9 @@ class MultipleSameSuccessEvaluator(AllReturnValuesEvaluator):
|
||||
|
||||
def eval(self, context, return_values):
|
||||
sheerka = context.sheerka
|
||||
context.log(self.verbose_log, f"{len(self.success)} successful return value(s)", who=self)
|
||||
context.log(f"{len(self.success)} successful return value(s)", who=self)
|
||||
for s in self.success:
|
||||
context.log(self.verbose_log, f"{s}", who=self)
|
||||
context.log(f"{s}", who=self)
|
||||
|
||||
if not core.builtin_helpers.is_same_success(sheerka, self.success):
|
||||
return None
|
||||
|
||||
@@ -35,8 +35,8 @@ class OneErrorEvaluator(AllReturnValuesEvaluator):
|
||||
return to_process and nb_evaluators_in_error == 1
|
||||
|
||||
def eval(self, context, return_values):
|
||||
context.log(self.verbose_log, f"1 return value in error, {len(self.eaten)} item(s) eaten", who=self)
|
||||
context.log(self.verbose_log, f"{self.return_value_in_error}", who=self)
|
||||
context.log(f"1 return value in error, {len(self.eaten)} item(s) eaten", who=self)
|
||||
context.log(f"{self.return_value_in_error}", who=self)
|
||||
|
||||
sheerka = context.sheerka
|
||||
return sheerka.ret(self.name, False, self.return_value_in_error.value, parents=self.eaten)
|
||||
|
||||
@@ -37,8 +37,8 @@ class OneSuccessEvaluator(AllReturnValuesEvaluator):
|
||||
return to_process and nb_successful_evaluators == 1
|
||||
|
||||
def eval(self, context, return_values):
|
||||
context.log(self.verbose_log, f"1 successful return value, {len(self.eaten)} item(s) eaten", who=self)
|
||||
context.log(self.verbose_log, f"{self.successful_return_value}", who=self)
|
||||
context.log(f"1 successful return value, {len(self.eaten)} item(s) eaten", who=self)
|
||||
context.log(f"{self.successful_return_value}", who=self)
|
||||
|
||||
sheerka = context.sheerka
|
||||
return sheerka.ret(self.name, True, self.successful_return_value.value, parents=self.eaten)
|
||||
|
||||
@@ -31,35 +31,35 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
sheerka = context.sheerka
|
||||
node = return_value.value.value
|
||||
try:
|
||||
context.log(self.verbose_log, f"Evaluating python node {node}.", self.name)
|
||||
context.log(f"Evaluating python node {node}.", self.name)
|
||||
|
||||
# Do not evaluate if the ast refers to a concept (leave it to ConceptEvaluator)
|
||||
if isinstance(node.ast_, ast.Expression) and isinstance(node.ast_.body, ast.Name):
|
||||
c = context.sheerka.get(node.ast_.body.id)
|
||||
if not context.sheerka.isinstance(c, BuiltinConcepts.UNKNOWN_CONCEPT):
|
||||
context.log(self.verbose_log, "It's a simple concept. Not for me.", self.name)
|
||||
context.log("It's a simple concept. Not for me.", self.name)
|
||||
not_for_me = context.sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=node)
|
||||
return sheerka.ret(self.name, False, not_for_me, parents=[return_value])
|
||||
|
||||
# get locals
|
||||
my_globals = self.get_globals(context, node)
|
||||
my_locals = {}
|
||||
context.log(self.verbose_log, f"globals={my_globals}", self.name)
|
||||
context.log(f"globals={my_globals}", self.name)
|
||||
|
||||
# eval
|
||||
if isinstance(node.ast_, ast.Expression):
|
||||
context.log(self.verbose_log, "Evaluating using 'eval'.", self.name)
|
||||
context.log("Evaluating using 'eval'.", self.name)
|
||||
compiled = compile(node.ast_, "<string>", "eval")
|
||||
evaluated = eval(compiled, my_globals, my_locals)
|
||||
else:
|
||||
context.log(self.verbose_log, "Evaluating using 'exec'.", self.name)
|
||||
context.log("Evaluating using 'exec'.", self.name)
|
||||
evaluated = self.exec_with_return(node.ast_, my_globals, my_locals)
|
||||
|
||||
context.log(self.verbose_log, f"{evaluated=}", self.name)
|
||||
context.log(f"{evaluated=}", self.name)
|
||||
return sheerka.ret(self.name, True, evaluated, parents=[return_value])
|
||||
|
||||
except Exception as error:
|
||||
context.log_error(self.verbose_log, error, self.name)
|
||||
context.log_error(error, self.name)
|
||||
error = sheerka.new(BuiltinConcepts.ERROR, body=error)
|
||||
return sheerka.ret(self.name, False, error, parents=[return_value])
|
||||
|
||||
@@ -74,8 +74,7 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
"Concept": core.concept.Concept
|
||||
}
|
||||
if context.obj:
|
||||
context.log(self.verbose_log,
|
||||
f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name)
|
||||
context.log(f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name)
|
||||
|
||||
for prop_name, prop_value in context.obj.props.items():
|
||||
if isinstance(prop_value.value, Concept):
|
||||
@@ -90,10 +89,10 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
unreferenced_names_visitor.visit(node_concept)
|
||||
|
||||
for name in unreferenced_names_visitor.names:
|
||||
context.log(self.verbose_log, f"Resolving '{name}'.", self.name)
|
||||
context.log(f"Resolving '{name}'.", self.name)
|
||||
|
||||
if name in node.concepts:
|
||||
context.log(self.verbose_log, f"Using value from node.", self.name)
|
||||
context.log(f"Using value from node.", self.name)
|
||||
concept = node.concepts[name]
|
||||
return_concept = False
|
||||
|
||||
@@ -101,20 +100,19 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
c_key, c_id, return_concept = self.resolve_name(name)
|
||||
|
||||
if c_key in my_locals:
|
||||
context.log(self.verbose_log, f"Using value from property.", self.name)
|
||||
context.log(f"Using value from property.", self.name)
|
||||
continue
|
||||
|
||||
context.log(self.verbose_log, f"Instantiating new concept with {c_key=}, {c_id=}.", self.name)
|
||||
context.log(f"Instantiating new concept with {c_key=}, {c_id=}.", self.name)
|
||||
new = context.sheerka.new
|
||||
concept = new((None, c_id)) if c_id else new(c_key)
|
||||
if context.sheerka.isinstance(concept, BuiltinConcepts.UNKNOWN_CONCEPT):
|
||||
context.log(self.verbose_log, f"({c_key=}, {c_id=}) is not a concept. Skipping.", self.name)
|
||||
context.log(f"({c_key=}, {c_id=}) is not a concept. Skipping.", self.name)
|
||||
continue
|
||||
|
||||
context.log(self.verbose_log, f"Evaluating '{concept}'", self.name)
|
||||
context.log(f"Evaluating '{concept}'", self.name)
|
||||
with context.push(self.name, desc=f"Evaluating '{concept}'", obj=concept) as sub_context:
|
||||
sub_context.log_new(self.verbose_log)
|
||||
evaluated = context.sheerka.evaluate_concept(sub_context, concept, self.verbose_log)
|
||||
evaluated = context.sheerka.evaluate_concept(sub_context, concept)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
|
||||
if evaluated.key == concept.key:
|
||||
@@ -141,47 +139,7 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
return key, id_, use_concept
|
||||
else:
|
||||
return to_resolve, None, False
|
||||
#
|
||||
# if not to_resolve.startswith("__C__"):
|
||||
# return to_resolve, None, False
|
||||
#
|
||||
# context.log(self.verbose_log, f"Resolving name '{to_resolve}'.", self.name)
|
||||
#
|
||||
# if len(to_resolve) >= 18 and to_resolve[:18] == "__C__USE_CONCEPT__":
|
||||
# use_concept = True
|
||||
# index = 18
|
||||
# else:
|
||||
# use_concept = False
|
||||
# index = 5
|
||||
#
|
||||
# try:
|
||||
# next_index = to_resolve.index("__", index)
|
||||
# if next_index == index:
|
||||
# context.log(self.verbose_log, f"Error: no key between '__'.", self.name)
|
||||
# return None
|
||||
# concept_key = to_resolve[index: next_index]
|
||||
# except ValueError:
|
||||
# context.log(self.verbose_log, f"Error: Missing trailing '__'.", self.name)
|
||||
# return None
|
||||
#
|
||||
# if next_index == len(to_resolve) - 5:
|
||||
# context.log(self.verbose_log, f"Recognized concept '{concept_key}'", self.name)
|
||||
# return concept_key, None, use_concept
|
||||
#
|
||||
# index = next_index + 2
|
||||
# try:
|
||||
# next_index = to_resolve.index("__", index)
|
||||
# if next_index == index:
|
||||
# context.log(self.verbose_log, f"Error: no id between '__'.", self.name)
|
||||
# return None
|
||||
#
|
||||
# concept_id = to_resolve[index: next_index]
|
||||
# except ValueError:
|
||||
# context.log(self.verbose_log, f"Recognized concept '{concept_key}'.", self.name)
|
||||
# return concept_key, None, use_concept
|
||||
#
|
||||
# context.log(self.verbose_log, f"Recognized concept '{concept_key}' (id='{concept_id}').", self.name)
|
||||
# return concept_key, concept_id, use_concept
|
||||
|
||||
|
||||
@staticmethod
|
||||
def expr_to_expression(expr):
|
||||
|
||||
@@ -41,14 +41,13 @@ class TooManySuccessEvaluator(AllReturnValuesEvaluator):
|
||||
sheerka = context.sheerka
|
||||
if self.verbose_log.isEnabledFor(logging.DEBUG):
|
||||
for s in self.success:
|
||||
context.log(self.verbose_log, s, self.name)
|
||||
context.log(self.verbose_log, f"value={sheerka.value(s.value)}", self.name)
|
||||
context.log(s, self.name)
|
||||
context.log(f"value={sheerka.value(s.value)}", self.name)
|
||||
|
||||
if not core.builtin_helpers.is_same_success(sheerka, self.success):
|
||||
context.log(self.verbose_log,
|
||||
f"Values are different. Raising {BuiltinConcepts.TOO_MANY_SUCCESS}.", self.name)
|
||||
context.log(f"Values are different. Raising {BuiltinConcepts.TOO_MANY_SUCCESS}.", self.name)
|
||||
too_many_success = sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, body=self.success)
|
||||
return sheerka.ret(self.name, False, too_many_success, parents=self.eaten)
|
||||
|
||||
context.log(self.verbose_log, f"Values are the same. Nothing to do.", self.name)
|
||||
context.log(f"Values are the same. Nothing to do.", self.name)
|
||||
return None
|
||||
|
||||
@@ -100,20 +100,28 @@ class BaseParser:
|
||||
|
||||
if ret.status:
|
||||
value = context.return_value_to_str(ret)
|
||||
context.log(self.log, f"Recognized '{source}' as {value}", self.name)
|
||||
context.log(f"Recognized '{source}' as {value}", self.name)
|
||||
else:
|
||||
context.log(self.log, f"Failed to recognize '{source}'", self.name)
|
||||
context.log(f"Failed to recognize '{source}'", self.name)
|
||||
|
||||
def log_multiple_results(self, context, source, list_of_ret):
|
||||
if not self.log.isEnabledFor(logging.DEBUG):
|
||||
return
|
||||
|
||||
context.log(self.log, f"Recognized '{source}' as multiple concepts", self.name)
|
||||
context.log(f"Recognized '{source}' as multiple concepts", self.name)
|
||||
for r in list_of_ret:
|
||||
value = context.return_value_to_str(r)
|
||||
context.log(self.log, f" Recognized '{value}'", self.name)
|
||||
context.log(f" Recognized '{value}'", self.name)
|
||||
|
||||
def get_return_value_body(self, sheerka, source, tree, try_parse):
|
||||
"""
|
||||
All parsers must return their result in a standard way
|
||||
:param sheerka:
|
||||
:param source:
|
||||
:param tree:
|
||||
:param try_parse:
|
||||
:return:
|
||||
"""
|
||||
if len(self.error_sink) == 1 and isinstance(self.error_sink[0], Concept):
|
||||
return self.error_sink[0]
|
||||
|
||||
|
||||
@@ -665,8 +665,9 @@ class ConceptLexerParser(BaseParser):
|
||||
self.sheerka = context.sheerka
|
||||
concepts_to_resolve = set()
|
||||
|
||||
# ## Gets the grammars
|
||||
for concept, concept_def in concepts_definitions.items():
|
||||
# ## Gets the grammars
|
||||
context.log(f"Resolving grammar for '{concept}'", context.who)
|
||||
concept.init_key() # make sure that the key is initialized
|
||||
grammar = self.get_model(concept_def, concepts_to_resolve)
|
||||
self.concepts_grammars[concept] = grammar
|
||||
|
||||
@@ -56,7 +56,6 @@ class ConceptsWithConceptsParser(BaseParser):
|
||||
prop_name = list(concept.props.keys())[index]
|
||||
concept.compiled[prop_name] = node.concept
|
||||
context.log(
|
||||
self.verbose_log,
|
||||
f"Setting property '{prop_name}='{node.concept}'.",
|
||||
self.name)
|
||||
index += 1
|
||||
@@ -66,7 +65,6 @@ class ConceptsWithConceptsParser(BaseParser):
|
||||
value = sheerka.new(BuiltinConcepts.PARSER_RESULT, parser=self, source=node.source, body=node.node)
|
||||
concept.compiled[prop_name] = [context.sheerka.ret(self.name, True, value)]
|
||||
context.log(
|
||||
self.verbose_log,
|
||||
f"Setting property '{prop_name}'='Python({node.source})'.",
|
||||
self.name)
|
||||
index += 1
|
||||
|
||||
@@ -230,7 +230,7 @@ class DefaultParser(BaseParser):
|
||||
token = self.get_token()
|
||||
if token.value == Keywords.DEF:
|
||||
self.next_token()
|
||||
self.context.log(self.verbose_log, "Keyword DEF found.", self.name)
|
||||
self.context.log("Keyword DEF found.", self.name)
|
||||
return self.parse_def_concept(token)
|
||||
else:
|
||||
return self.parse_isa_concept()
|
||||
@@ -411,14 +411,13 @@ class DefaultParser(BaseParser):
|
||||
|
||||
# ask the other parsers if they recognize the tokens
|
||||
with self.context.push(self.name, desc=f"Parsing {keyword}") as sub_context:
|
||||
sub_context.log_new(self.verbose_log)
|
||||
to_parse = self.sheerka.ret(
|
||||
sub_context.who,
|
||||
True,
|
||||
self.sheerka.new(BuiltinConcepts.USER_INPUT, body=tokens))
|
||||
steps = [BuiltinConcepts.PARSING]
|
||||
parsed = self.sheerka.execute(sub_context, to_parse, steps, self.verbose_log)
|
||||
parsing_result = core.builtin_helpers.expect_one(sub_context, parsed, self.verbose_log)
|
||||
parsed = self.sheerka.execute(sub_context, to_parse, steps)
|
||||
parsing_result = core.builtin_helpers.expect_one(sub_context, parsed)
|
||||
sub_context.add_values(return_values=parsing_result)
|
||||
|
||||
if not parsing_result.status:
|
||||
|
||||
@@ -24,17 +24,17 @@ class ExactConceptParser(BaseParser):
|
||||
:return:
|
||||
"""
|
||||
|
||||
context.log(self.verbose_log, f"Parsing '{text}'", self.name)
|
||||
context.log(f"Parsing '{text}'", self.name)
|
||||
res = []
|
||||
sheerka = context.sheerka
|
||||
try:
|
||||
words = self.get_words(text)
|
||||
except LexerError as e:
|
||||
context.log(self.verbose_log, f"Error found in tokenizer {e}", self.name)
|
||||
context.log(f"Error found in tokenizer {e}", self.name)
|
||||
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.ERROR, body=e))
|
||||
|
||||
if len(words) > self.MAX_WORDS_SIZE:
|
||||
context.log(self.verbose_log, f"Max words reached. Stopping.", self.name)
|
||||
context.log(f"Max words reached. Stopping.", self.name)
|
||||
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, body=text))
|
||||
|
||||
recognized = False
|
||||
@@ -50,7 +50,7 @@ class ExactConceptParser(BaseParser):
|
||||
concepts = result if isinstance(result, list) else [result]
|
||||
|
||||
for concept in concepts:
|
||||
context.log(self.verbose_log, f"Recognized concept {concept}.", self.name)
|
||||
context.log(f"Recognized concept {concept}.", self.name)
|
||||
# update the properties if needed
|
||||
for i, token in enumerate(combination):
|
||||
if token.startswith(VARIABLE_PREFIX):
|
||||
@@ -59,7 +59,6 @@ class ExactConceptParser(BaseParser):
|
||||
if self.verbose_log.isEnabledFor(logging.DEBUG):
|
||||
prop_name = list(concept.props.keys())[index]
|
||||
context.log(
|
||||
self.verbose_log,
|
||||
f"Added property {index}: {prop_name}='{words[i]}'.",
|
||||
self.name)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user