def run_uninitialized(self): q = set(self.uninitialized_rules) failed = [] # run to fixed point while q: rule = q.pop() try: assert not rule.initialized emits = [] def _emit(*args): emits.append(args) self.clear_error(rule) # clear errors on rule, if any rule.init(emit=_emit) except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e: e.exception_frame = rule_error_context() e.traceback = traceback.format_exc() self.set_error(rule, e) failed.append(rule) else: rule.initialized = True for e in emits: self.emit(*e, delete=False) self.uninitialized_rules = failed
def push(self, item, val, delete): """ Passes update to relevant handlers. Catches errors. """ # store emissions, make sure all of them succeed before propagating # changes to aggregators. emittiers = [] t_emit = lambda item, val, ruleix, variables: \ emittiers.append((item, val, ruleix, variables, delete)) errors = [] for handler in self.updaters[item.fn]: # TODO: should only add update handlers after rule has been initialized. if not handler.rule.initialized: continue try: handler(item, val, emit=t_emit) except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e: e.exception_frame = rule_error_context() e.traceback = traceback.format_exc() errors.append((e, handler)) if errors: self.set_error(item, (val, errors)) return # no exceptions, accept emissions. for e in emittiers: # an error could happen here, but we assume (by contract) that this # is not possible. self.emit(*e)
def force_gbc(self, item): "Skips memo on item check." if item.aggregator is None: # we might not have a rule defining this subgoal. return self.clear_error(item) item.aggregator.clear() emits = [] def t_emit(item, val, ruleix, variables): emits.append((item, val, ruleix, variables, False)) errors = [] for handler in self._gbc[item.fn]: try: handler(*item.args, emit=t_emit) except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e: e.exception_frame = rule_error_context() e.traceback = traceback.format_exc() errors.append((e, handler)) if hasattr(self, 'was') and self.was: was = self.was if item in was: if item.value != was[item]: item.value = was[item] if errors: e = Error() self.push(item, e, delete=False) # Force value to error, since aggregator might ignore it. This is # not correct XREF:agg-error self.replace(item, e) self.set_error(item, (None, errors)) return e else: for e in emits: self.emit(*e) return self.pop(item)