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.NAME, self.process_return_values, False) self.sheerka.register_debug_vars("Visitor", "create_out_tree", "Exception") self.sheerka.register_debug_vars(SheerkaOut.NAME, "create_out_tree", "out_tree") def create_out_tree(self, context, obj): debugger = context.get_debugger("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 print("TODO: 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 !