]> hydra-www.ietfng.org Git - dyna2/commitdiff
BUGFIX: properly clear error.
authorTim Vieira <tim.f.vieira@gmail.com>
Sat, 13 Jul 2013 04:26:40 +0000 (00:26 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Sat, 13 Jul 2013 04:26:40 +0000 (00:26 -0400)
run initializers after clearing agenda, if new updates are queued run agenda
again.

src/Dyna/Backend/Python/interpreter.py

index 9943141a13f907086177739e7ef972558ef3d6a2..9a6a70214f31b8d437b2819eec6e4774db01c8ca 100644 (file)
@@ -126,11 +126,10 @@ def rule_error_context():
 
 
 def render_rule_context(rule, ctx, indent=''):
-    # TODO: include an undefined or unknown marker
-    # TODO: can highlight the expression which raise the error.
+    # TODO: highlight expression which caused the error.
     from post.trace import Crux
     c = Crux(head=None, rule=rule, body=None, vs = ctx)
-    return ''.join(indent + line for line in c.format())
+    return '\n'.join(indent + line for line in c.format())
 
 
 class Rule(object):
@@ -140,10 +139,11 @@ class Rule(object):
         self.init = None
         self.updaters = []
         self.query = None
-
         self._span = None
         self._src = None
 
+        self.initialized = False
+
     @property
     def span(self):
         if self._span is None:
@@ -408,9 +408,10 @@ class Interpreter(object):
             print '^C'
             self.dump_charts()
 
-    def _go(self):
+    def _go(self, changed=None):
         "the main loop"
-        changed = {}
+        if changed is None:
+            changed = {}
         agenda = self.agenda
         error = self.error
         while agenda:
@@ -446,19 +447,15 @@ class Interpreter(object):
             if was == now:
                 continue
 
-            was_error = False
-            if item in error:    # clear error
-                was_error = True
-                del error[item]
-
             # TODO: handle `was` and `now` at the same time to avoid the two passes.
             # TODO: will need to propagate was=None when we have question mark
-            if was is not None and not was_error:
+            if was is not None: # and item not in error:
                 # if `was` is marked as an error we know it didn't propagate.
                 # Thus, we can skip the delete-updates.
                 self.update_dispatcher(item, was, delete=True)
 
-            assert now is not True or now is not False  # invalid dyna types.
+            if item in error:     # only care about errors at new value.
+                del error[item]
 
             item.value = now
 
@@ -467,6 +464,12 @@ class Interpreter(object):
 
             changed[item] = now
 
+        if self.uninitialized_rules:
+            self.run_uninitialized()
+
+            if self.agenda:
+                self._go(changed)
+
         return changed
 
     def update_dispatcher(self, item, val, delete):
@@ -483,6 +486,10 @@ class Interpreter(object):
         error = []
 
         for handler in self.updaters[item.fn]:
+
+            if not handler.rule.initialized:
+                continue
+
             try:
                 handler(item, val, emit=t_emit)
             except (TypeError, ZeroDivisionError, KeyboardInterrupt, OverflowError) as e:
@@ -617,25 +624,34 @@ class Interpreter(object):
     def run_uninitialized(self):
 
         q = list(self.uninitialized_rules)
+        failed = []
+
         self.uninitialized_rules = []
+
         while q:
             (_, r) = q.pop()
             try:
+
+                rule = self.rules[r]
+                assert not rule.initialized
+
                 emits = []
                 def _emit(*args):
                     emits.append(args)
 
-                self.rules[r].init(emit=_emit)
+                rule.init(emit=_emit)
 
             except (TypeError, ZeroDivisionError) as e:
                 e.exception_frame = rule_error_context()
-                self.uninitialized_rules.append((e, r))
+                failed.append((e, r))
 
             else:
+                rule.initialized = True
                 # process emits
                 for e in emits:
                     self.emit(*e, delete=False)
 
+        self.uninitialized_rules = failed
 
     def dynac(self, filename):
         filename = path(filename)