]> hydra-www.ietfng.org Git - dyna2/commitdiff
maintain a coarse dependency graph of head->evals and a map functor->rules (all
authorTim Vieira <tim.f.vieira@gmail.com>
Tue, 16 Jul 2013 23:31:01 +0000 (19:31 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Tue, 16 Jul 2013 23:31:01 +0000 (19:31 -0400)
rules [not just BC rules] know their head's functor -- i.e. an overestimate of
what they "create"). These changes are nonfunction, but will facilitate
maintenance, retraction and all that.

src/Dyna/Backend/Python/interpreter.py
src/Dyna/Backend/Python/post/trace.py
src/Dyna/Backend/Python/repl.py
src/Dyna/Backend/Python/stdlib.py

index 99fdbfdb64bbada918054423569d2e2985a583f4..b1545413c5918cafd6b5e641eb99bcb200b16b5f 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-import os, sys, imp, traceback
+import re, os, sys, imp, traceback
 from collections import defaultdict
 from hashlib import sha1
 from path import path
@@ -82,6 +82,11 @@ class Interpreter(object):
             tmp.rmtree()
         tmp.makedirs_p()
 
+        # coarsening of the program shows which rules might depend on each other
+        # (an over estimate -- high recall, low precision).
+        self.coarse_deps = defaultdict(set)
+        self.rule_by_head = defaultdict(list)
+
     def new_fn(self, fn, agg):
         if self.agg_name[fn] is None:
             self.agg_name[fn] = agg
@@ -187,7 +192,6 @@ class Interpreter(object):
 
         if self.uninitialized_rules:
             self.run_uninitialized()
-
             if self.agenda:
                 self.run_agenda(changed)
 
@@ -202,7 +206,7 @@ class Interpreter(object):
         # changes to aggregators.
         emittiers = []
         t_emit = lambda item, val, ruleix, variables: \
-            emittiers.append((item, val, ruleix, variables, delete))
+           emittiers.append((item, val, ruleix, variables, delete))
 
         error = []
 
@@ -314,12 +318,9 @@ class Interpreter(object):
                 rule.init(emit=_emit)
 
             except (ZeroDivisionError, TypeError, KeyboardInterrupt, RuntimeError, OverflowError) as e:
-                # TODO: should put stuff in error table, like everything else.
                 e.exception_frame = rule_error_context()
                 e.traceback = traceback.format_exc()
-
                 self.error[rule] = e
-
                 failed.append(rule)
             else:
                 rule.initialized = True
@@ -332,9 +333,22 @@ class Interpreter(object):
     # Adding/removing rules
 
     def add_rule(self, index, init=None, query=None, head_fn=None, anf=None):
-
+        assert anf is not None
         assert index not in self.rules
 
+        for (x, label, ys) in anf.unifs:
+            if x == anf.head:
+                assert label == '&'
+                fa = '%s/%d' % (ys[0], len(ys) - 1)
+                if head_fn is not None:
+                    assert head_fn == fa
+                head_fn = fa
+                break
+        else:
+            assert False, 'did not find head'
+        assert head_fn is not None
+
+
         span = hide_ugly_filename(parse_attrs(init or query)['Span'])
         dyna_src = strip_comments(parse_attrs(init or query)['rule'])
 
@@ -345,6 +359,8 @@ class Interpreter(object):
         rule.anf = anf
         rule.head_fn = head_fn
 
+        self.update_coarse(rule)
+
         if init:
             rule.init = init
             init.rule = rule
@@ -359,11 +375,11 @@ class Interpreter(object):
             assert False, "Can't add rule with out an initializer or query handler."
 
         # XXX: all rules should eventually have ANF tacked on, but until then...
-        if anf is not None:
-            agg, head, evals, unifs, result = anf[2:]
+        #if anf is not None:
+        if True:
             args = (index,
                     dyna_src,
-                    todyna([head, agg, result, evals, unifs]),
+                    todyna([anf.head, anf.agg, anf.result, anf.evals, anf.unifs]),
                     init,
                     query)
 
@@ -374,6 +390,18 @@ class Interpreter(object):
             rule.item = self.build(fn, *args)
             self.emit(rule.item, true, ruleix=None, variables=None, delete=False)
 
+    def update_coarse(self, rule):
+        self.rule_by_head[rule.head_fn].append(rule)
+        for (_, label, ys) in rule.anf.evals:
+            [(label, _evalix)] = re.findall('^(.*)@(\d+)$', label)  # remove evaluation index
+            self.coarse_deps[rule.head_fn].add('%s/%d' % (label, len(ys)))
+
+    def recompute_coarse(self):
+        self.rule_by_head.clear()
+        self.coarse_deps.clear()
+        for rule in self.rules.values():
+            self.update_coarse(rule)
+
     def retract_rule(self, idx):
         "Retract rule and all of it's edges."
 
@@ -427,6 +455,9 @@ class Interpreter(object):
                     self.agenda[head] = self.time_step
                     self.time_step += 1
 
+        self.recompute_coarse()
+        # todo: need coarse deps transitive closure
+
         return self.run_agenda()
 
     def new_updater(self, fn, ruleix, handler):
index 23cd34afa7a3d87ba6e9192003157081c4c76e8a..2fea1f4f4ab0dd247dbcf854aaa5ce15ddcb5e4c 100644 (file)
@@ -1,9 +1,5 @@
 # -*- coding: utf-8 -*-
 
-"""
-TODO: have ANF output which functors are infix, prefix, nullary, etc.
-"""
-
 import re
 from collections import defaultdict
 
index c965d1e3bc9e6ce57044aaa7426a028ac97eb81e..334c1c3efb8ae886c52faa74ce585e9c6cbbc4aa 100644 (file)
@@ -13,7 +13,6 @@ from stdlib import topython, todyna
 from errors import DynaCompilerError
 from config import dotdynadir
 from errors import show_traceback
-from interpreter import Interpreter, foo, none
 import load, post
 
 
index 688dd35304a04adeb9c0956e18e899d9c4238f7f..c6cdd30bbca98a1f1f911fe03a49cf7568dc0a14 100644 (file)
@@ -102,7 +102,7 @@ def todyna(x):
         return false
 
     elif isinstance(x, dict):
-        return todyna([MapsTo(k,v) for k,v in x.items()])
+        return todyna([MapsTo(todyna(k), todyna(v)) for k,v in x.items()])
 
     elif isinstance(x, (list, tuple)):
         c = Nil