99 lines
3.8 KiB
Python
99 lines
3.8 KiB
Python
from core.builtin_concepts import BuiltinConcepts
|
|
from core.sheerka.services.sheerka_service import BaseService
|
|
from core.utils import as_bag
|
|
from out.ConsoleVisistor import ConsoleVisitor
|
|
from out.DeveloperVisitor import DeveloperVisitor
|
|
|
|
|
|
class SheerkaOut(BaseService):
|
|
NAME = "Out"
|
|
|
|
def __init__(self, sheerka):
|
|
super().__init__(sheerka)
|
|
self.out_visitors = [ConsoleVisitor(expand_mode="all_but_first")]
|
|
|
|
def initialize(self):
|
|
self.sheerka.bind_service_method(self.process_return_values, False)
|
|
|
|
def create_out_tree(self, context, obj):
|
|
debugger = context.get_debugger("Out.visitor", "create_out_tree")
|
|
return self.create_out_tree_recursive(context, {'__obj': obj}, DeveloperVisitor(self, debugger, set(), 0))
|
|
|
|
def create_out_tree_recursive(self, context, bag, visitor):
|
|
debugger = context.get_debugger(SheerkaOut.NAME, "create_out_tree")
|
|
debugger.debug_entering(bag=bag)
|
|
|
|
current_obj = bag["__obj"]
|
|
bag = self.update_bag(bag, visitor.list_recursion_depth)
|
|
|
|
valid_rules = self.sheerka.evaluate_format_rules(context, bag, visitor.already_seen).get(True, None)
|
|
res = None
|
|
if valid_rules:
|
|
if len(valid_rules) > 1:
|
|
# TODO manage when too many rules
|
|
pass
|
|
|
|
rule = valid_rules[0]
|
|
if rule.id in visitor.already_seen:
|
|
debugger.debug_log(f"Rule #{rule.id} already fired.")
|
|
else:
|
|
debugger.debug_log(f"Applying rule {rule}.")
|
|
visitor.already_seen.add(rule.id)
|
|
|
|
bag.update(as_bag(current_obj)) # update with the current obj attributes
|
|
res = visitor.visit(context, rule.compiled_action, bag)
|
|
|
|
if res is None:
|
|
debugger.debug_log(f"No matching rule.")
|
|
res = current_obj
|
|
|
|
debugger.debug_var("out_tree", res)
|
|
|
|
return res
|
|
|
|
def process_return_values(self, context, ret):
|
|
with context.push(BuiltinConcepts.BEFORE_RENDERING,
|
|
None,
|
|
desc=f"step='{BuiltinConcepts.BEFORE_RENDERING}'") as sub_context:
|
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
|
# sub_context.deactivate_push()
|
|
|
|
out_tree = self.create_out_tree(sub_context, ret)
|
|
|
|
# sub_context.activate_push()
|
|
|
|
if out_tree:
|
|
for visitor in self.out_visitors:
|
|
visitor.visit(out_tree)
|
|
|
|
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
|
return self.sheerka.ret(self.NAME, False, self.sheerka.new(BuiltinConcepts.NO_RESULT))
|
|
|
|
def update_bag(self, bag, depth):
|
|
obj = bag["__obj"]
|
|
bag["__tab"] = " " * depth
|
|
|
|
if self.sheerka.isinstance(obj, BuiltinConcepts.RETURN_VALUE):
|
|
bag["__ret"] = obj
|
|
if self.sheerka.is_container(obj.body):
|
|
bag["__ret_container"] = obj.body
|
|
bag["__ret_value"] = self.simplify_list(obj.body.body)
|
|
bag["__ret_val"] = bag["__ret_value"]
|
|
else:
|
|
bag["__ret_value"] = self.simplify_list(obj.body)
|
|
bag["__ret_val"] = bag["__ret_value"]
|
|
elif isinstance(obj, list) and len(obj) > 0 and self.sheerka.isinstance(obj[0], BuiltinConcepts.RETURN_VALUE):
|
|
bag["__rets"] = obj
|
|
|
|
return bag
|
|
|
|
@staticmethod
|
|
def simplify_list(item):
|
|
try:
|
|
return item[0] if hasattr(item, "__len__") and len(item) == 1 else item
|
|
except KeyError:
|
|
return item # Caution. it's a dict, not a list !
|