Added simple form of concept composition
This commit is contained in:
+68
-41
@@ -258,6 +258,7 @@ class Sheerka(Concept):
|
||||
# execution_context.log(logger or self.log, f"Parsing {debug_text}")
|
||||
|
||||
with execution_context.push(desc=f"Parsing using {parser.name}") as sub_context:
|
||||
sub_context.add_inputs(to_parse=to_parse)
|
||||
res = parser.parse(sub_context, to_parse)
|
||||
if res is not None:
|
||||
if hasattr(res, "__iter__"):
|
||||
@@ -278,6 +279,7 @@ class Sheerka(Concept):
|
||||
to_process.append(res)
|
||||
if res.status:
|
||||
return_value_success_found = True
|
||||
sub_context.add_values(return_values=res)
|
||||
|
||||
if return_value_success_found:
|
||||
stop_processing = True
|
||||
@@ -347,51 +349,69 @@ class Sheerka(Concept):
|
||||
sorted_priorities = sorted(grouped_evaluators.keys(), reverse=True)
|
||||
|
||||
# process
|
||||
iteration = 0
|
||||
while True:
|
||||
simple_digest = return_values[:]
|
||||
with execution_context.push(desc=f"iteration #{iteration}", iteration=iteration) as iteration_context:
|
||||
simple_digest = return_values[:]
|
||||
iteration_context.add_inputs(return_values=simple_digest)
|
||||
|
||||
for priority in sorted_priorities:
|
||||
for priority in sorted_priorities:
|
||||
|
||||
original_items = return_values[:]
|
||||
evaluated_items = []
|
||||
to_delete = []
|
||||
for evaluator in grouped_evaluators[priority]:
|
||||
evaluator = _preprocess_evaluators(execution_context, evaluator.__class__()) # fresh copy
|
||||
original_items = return_values[:]
|
||||
evaluated_items = []
|
||||
to_delete = []
|
||||
for evaluator in grouped_evaluators[priority]:
|
||||
evaluator = _preprocess_evaluators(execution_context, evaluator.__class__()) # fresh copy
|
||||
|
||||
# process evaluators that work on return value
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
if isinstance(evaluator, OneReturnValueEvaluator):
|
||||
for item in original_items:
|
||||
if evaluator.matches(execution_context, item):
|
||||
result = evaluator.eval(execution_context, item)
|
||||
if result is None:
|
||||
continue
|
||||
elif isinstance(result, list):
|
||||
evaluated_items.extend(result)
|
||||
to_delete.append(item)
|
||||
elif isinstance(result, ReturnValueConcept):
|
||||
evaluated_items.append(result)
|
||||
to_delete.append(item)
|
||||
sub_context_desc = f"Evaluating using {evaluator.name} ({priority=})"
|
||||
with iteration_context.push(desc=sub_context_desc) as sub_context:
|
||||
sub_context.add_inputs(return_values=original_items)
|
||||
|
||||
# process evaluators that work on one simple return value at the time
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
if isinstance(evaluator, OneReturnValueEvaluator):
|
||||
debug_result = []
|
||||
for item in original_items:
|
||||
if evaluator.matches(sub_context, item):
|
||||
result = evaluator.eval(sub_context, item)
|
||||
if result is None:
|
||||
debug_result.append({"input": item, "return_value": None})
|
||||
continue
|
||||
|
||||
to_delete.append(item)
|
||||
if isinstance(result, list):
|
||||
evaluated_items.extend(result)
|
||||
elif isinstance(result, ReturnValueConcept):
|
||||
evaluated_items.append(result)
|
||||
else:
|
||||
error = self.new(BuiltinConcepts.INVALID_RETURN_VALUE, body=result,
|
||||
evaluator=evaluator)
|
||||
result = self.ret("sheerka.process", False, error, parents=[item])
|
||||
evaluated_items.append(result)
|
||||
debug_result.append({"input": item, "return_value": result})
|
||||
else:
|
||||
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
|
||||
else:
|
||||
if evaluator.matches(sub_context, original_items):
|
||||
results = evaluator.eval(sub_context, original_items)
|
||||
if results is None:
|
||||
continue
|
||||
if not isinstance(results, list):
|
||||
results = [results]
|
||||
for result in results:
|
||||
evaluated_items.append(result)
|
||||
to_delete.extend(result.parents)
|
||||
sub_context.add_values(return_values=results)
|
||||
else:
|
||||
error = self.new(BuiltinConcepts.INVALID_RETURN_VALUE, body=result,
|
||||
evaluator=evaluator)
|
||||
evaluated_items.append(self.ret("sheerka.process", False, error, parents=[item]))
|
||||
to_delete.append(item)
|
||||
sub_context.add_values(return_values="** No Match **")
|
||||
|
||||
# process evaluators that work on all return values
|
||||
else:
|
||||
if evaluator.matches(execution_context, original_items):
|
||||
results = evaluator.eval(execution_context, original_items)
|
||||
if results is None:
|
||||
continue
|
||||
if not isinstance(results, list):
|
||||
results = [results]
|
||||
for result in results:
|
||||
evaluated_items.append(result)
|
||||
to_delete.extend(result.parents)
|
||||
return_values = evaluated_items
|
||||
return_values.extend([item for item in original_items if item not in to_delete])
|
||||
|
||||
return_values = evaluated_items
|
||||
return_values.extend([item for item in original_items if item not in to_delete])
|
||||
iteration_context.add_values(return_values=return_values[:])
|
||||
|
||||
# have we done something ?
|
||||
to_compare = return_values[:]
|
||||
@@ -399,7 +419,7 @@ class Sheerka(Concept):
|
||||
break
|
||||
|
||||
# inc the iteration and continue
|
||||
execution_context = execution_context.push(iteration=execution_context.iteration + 1)
|
||||
iteration += 1
|
||||
|
||||
# remove all evaluation context that are not reduced
|
||||
return_values = core.utils.remove_list_from_list(return_values, evaluation_return_values)
|
||||
@@ -879,11 +899,11 @@ class Sheerka(Concept):
|
||||
|
||||
return obj
|
||||
|
||||
def is_unknown(self, obj):
|
||||
def is_known(self, obj):
|
||||
if not isinstance(obj, Concept):
|
||||
return True
|
||||
|
||||
return obj.key == BuiltinConcepts.UNKNOWN_CONCEPT
|
||||
return obj.key != str(BuiltinConcepts.UNKNOWN_CONCEPT)
|
||||
|
||||
def isinstance(self, a, b):
|
||||
"""
|
||||
@@ -1049,6 +1069,8 @@ class ExecutionContext:
|
||||
self.desc = desc # human description of what is going on
|
||||
self.children = []
|
||||
self.preprocess = None
|
||||
|
||||
self.inputs = {} # what was the parameters of the execution context
|
||||
self.values = {} # what was produced by the execution context
|
||||
|
||||
self.obj = kwargs.pop("obj", None)
|
||||
@@ -1105,6 +1127,11 @@ class ExecutionContext:
|
||||
self.preprocess.add(preprocess)
|
||||
return self
|
||||
|
||||
def add_inputs(self, **kwargs):
|
||||
for k, v in kwargs.items():
|
||||
self.inputs[k] = v
|
||||
return self
|
||||
|
||||
def add_values(self, **kwargs):
|
||||
for k, v in kwargs.items():
|
||||
self.values[k] = v
|
||||
|
||||
@@ -48,7 +48,7 @@ class SheerkaTransform:
|
||||
self.ids[obj] = self.id_count
|
||||
|
||||
if isinstance(obj, Concept):
|
||||
return self.context_to_dict(obj)
|
||||
return self.concept_to_dict(obj)
|
||||
|
||||
elif isinstance(obj, ExecutionContext):
|
||||
return self.execution_context_to_dict(obj)
|
||||
@@ -104,7 +104,7 @@ class SheerkaTransform:
|
||||
else:
|
||||
return obj
|
||||
|
||||
def context_to_dict(self, obj: Concept):
|
||||
def concept_to_dict(self, obj: Concept):
|
||||
to_dict = {
|
||||
OBJ_TYPE_KEY: SheerkaTransformType.Concept,
|
||||
OBJ_ID_KEY: self.id_count,
|
||||
|
||||
@@ -37,6 +37,8 @@ class TokenKind(Enum):
|
||||
BACK_SLASH = "bslash" # \
|
||||
CARAT = "carat" # ^
|
||||
DOLLAR = "dollar" # $
|
||||
EURO = "dollar" # €
|
||||
STERLING = "steling" # £
|
||||
EMARK = "emark" # !
|
||||
GREATER = "greater" # >
|
||||
LESS = "less" # <
|
||||
@@ -128,6 +130,18 @@ class Tokenizer:
|
||||
yield Token(TokenKind.MINUS, "-", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "_":
|
||||
if self.i + 1 < self.text_len and self.text[self.i + 1].isalpha():
|
||||
identifier = self.eat_identifier(self.i)
|
||||
token_type = TokenKind.KEYWORD if identifier in self.KEYWORDS else TokenKind.IDENTIFIER
|
||||
value = Keywords(identifier) if identifier in self.KEYWORDS else identifier
|
||||
yield Token(token_type, value, self.i, self.line, self.column)
|
||||
self.i += len(identifier)
|
||||
self.column += len(identifier)
|
||||
else:
|
||||
yield Token(TokenKind.UNDERSCORE, "_", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "/":
|
||||
yield Token(TokenKind.SLASH, "/", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
@@ -205,6 +219,46 @@ class Tokenizer:
|
||||
yield Token(TokenKind.GREATER, ">", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "!":
|
||||
yield Token(TokenKind.EMARK, "!", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "`":
|
||||
yield Token(TokenKind.BACK_QUOTE, "`", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "\\":
|
||||
yield Token(TokenKind.BACK_SLASH, "\\", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "^":
|
||||
yield Token(TokenKind.CARAT, "^", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "$":
|
||||
yield Token(TokenKind.DOLLAR, "$", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "€":
|
||||
yield Token(TokenKind.EURO, "€", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "£":
|
||||
yield Token(TokenKind.STERLING, "£", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "#":
|
||||
yield Token(TokenKind.HASH, "#", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "°":
|
||||
yield Token(TokenKind.DEGREE, "°", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "~":
|
||||
yield Token(TokenKind.TILDE, "~", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
elif c == "\n" or c == "\r":
|
||||
newline = self.eat_newline(self.i)
|
||||
yield Token(TokenKind.NEWLINE, newline, self.i, self.line, self.column)
|
||||
@@ -234,6 +288,10 @@ class Tokenizer:
|
||||
self.i += len(string)
|
||||
self.column = 1 if newlines > 0 else self.column + len(string)
|
||||
self.line += newlines
|
||||
elif c == "_":
|
||||
yield Token(TokenKind.UNDERSCORE, "_", self.i, self.line, self.column)
|
||||
self.i += 1
|
||||
self.column += 1
|
||||
else:
|
||||
raise LexerError(f"Unknown token '{c}'", self.text, self.i, self.line, self.column)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user