]> hydra-www.ietfng.org Git - dyna2/commitdiff
Many small tweaks.
authorTim Vieira <tim.f.vieira@gmail.com>
Thu, 1 Aug 2013 17:09:18 +0000 (13:09 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Thu, 1 Aug 2013 17:09:18 +0000 (13:09 -0400)
 - fixed argument disposition of tupling operators: `->` and `:`.

 - Compare rules by their index (i.e. equality, hash,q and sort order).

 - Recompilation works like rule initialization

src/Dyna/Backend/Python/dyna_doctest.py
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
src/Dyna/Backend/Python/term.py
src/Dyna/Backend/Python/utils.py
src/Dyna/Term/SurfaceSyntax.hs
test/repl/late-bc.dynadoc

index b7a44e736e5037cf8458a6c97db3e2b54ada7580..a32ebc79d3e2badfc774093ccec07cb2e279d125 100644 (file)
@@ -9,8 +9,10 @@ from utils import bold, red, green, yellow, strip_comments
 def diff(expect, got):
     with file('/tmp/expect','wb') as A:
         A.write(expect)
+        A.write('\n')
     with file('/tmp/got','wb') as B:
         B.write(got)
+        B.write('\n')
     from subprocess import Popen, PIPE
     p = Popen(['colordiff', A.name, B.name], stdout=PIPE, stderr=PIPE)
     return p.communicate()[0]
@@ -18,11 +20,7 @@ def diff(expect, got):
 
 def extract(code):
     for block in re.compile('^> ', re.MULTILINE).split(code):
-        cmd = []
-        expect = []
-
-        reading = True
-
+        cmd, expect, reading = [], [], True
         for i, line in enumerate(block.split('\n')):
             if (line.startswith('|') or i == 0) and reading:
                 if line.startswith('|'):
@@ -31,7 +29,6 @@ def extract(code):
             else:
                 reading = False
                 expect.append(line)
-
         yield '\n'.join(cmd).strip(), '\n'.join(expect).strip()
 
 
index fad8b7d00024a7d163e3abca3785d1e6e21b25c5..cfc5cceef6b664b0c24846bcdb482a7a87f0b2e0 100644 (file)
@@ -8,7 +8,7 @@ from path import path
 from term import Term, Cons, Nil, MapsTo, Error
 from chart import Chart
 from utils import red, parse_attrs, ddict, dynac, read_anf, strip_comments, \
-    _repr, hide_ugly_filename, true, false, parse_parser_state
+    _repr, hide_ugly_filename, true, false, parse_parser_state, magenta, indent
 
 from prioritydict import prioritydict
 from config import dotdynadir
@@ -32,6 +32,18 @@ class Rule(object):
         self.anf = None
         self.head_fn = None
 
+    def __eq__(self, other):
+        return self.index == other.index
+
+    def hash(self):
+        return self.index
+
+    def __cmp__(self, other):
+        try:
+            return cmp(self.index, other.index)
+        except AttributeError:
+            return 1
+
     def __repr__(self):
         return 'Rule(%s, %r)' % (self.index, self.src)
 
@@ -93,7 +105,7 @@ class Interpreter(object):
         for fn in bc:
             if fn not in self._gbc:    # new backchain declaration
                 for r in self.rule_by_head[fn]:
-                    self.recompile.add(r)
+                    self.needs_recompile(r)
 
     def __init__(self):
         # declarations
@@ -180,7 +192,7 @@ class Interpreter(object):
         while agenda:
             item = self.agenda.pop_smallest()
             self.pop(item)
-        # after draining the agenda, try to initialize pending rules.
+        self.run_recompile()
         self.run_uninitialized()
         if self.agenda:
             self._agenda()
@@ -272,14 +284,9 @@ class Interpreter(object):
             self.emit(*e)
 
     def gbc(self, fn, args):
-
         item = self.build(fn, *args)
-
-        # TODO: we will need to distinguish `unknown` from `null` when we move
-        # to mixed chaining.
         if item.value is not None:
             return item.value
-
         return self.force_gbc(item)
 
     def force_gbc(self, item):
@@ -315,7 +322,7 @@ class Interpreter(object):
 
         return self.pop(item)
 
-    def load_plan(self, filename, recurse=True):
+    def load_plan(self, filename):
         """
         Compile, load, and execute new dyna rules.
 
@@ -358,11 +365,6 @@ class Interpreter(object):
         for fn, r, h in env.updaters:
             self.new_updater(fn, r, h)
 
-        if recurse:
-            self.run_recompile()
-
-        # we we don't accumulate all changed rules, new_rules return will be new
-        # rules of top-level call.
         return new_rules
 
     def recompile_rule(self, r):
@@ -378,34 +380,29 @@ class Interpreter(object):
             f.write(code)
         return self.dynac(dyna)
 
+    def needs_recompile(self, r):
+        self.retract_rule(r.index)   # clears errors
+        self.recompile.add(r)
+
     def run_recompile(self):
-        # TODO: it's a bit strange to ignore the error and just print
-        # it. However, since the rules in the recompile list are
-        # syntactically valid (well, they at least they were valid) -- this
-        # means that errors must be planning errors... probably all to do
-        # with missing BC declarations.
-        #
-        # TODO: we probably have to worry about infinite loops -- at the
-        # moment this results in an interpreter crash due to max recursion
-        # limit
-        #
-        # TODO: maybe we should handle recompilation more like we do
-        # uninitialized rules.
         # run to fixed point.
         while self.recompile:
+            success = set()
             failed = set()
             for r in list(self.recompile):
                 try:
-                    plan = self.recompile_rule(r)
+                    r.plan = self.recompile_rule(r)
                 except DynaCompilerError as e:
                     failed.add(r)
                     self.set_error(r, e)
                 else:
-                    self.retract_rule(r.index)
-                    self.load_plan(plan, recurse=False)
-            if failed == self.recompile:   # no progress
-                break
+                    success.add(r)
+                    self.clear_error(r)
             self.recompile = failed
+            if not success:
+                break
+            for r in success:
+                self.load_plan(r.plan)
 
     def run_uninitialized(self):
         q = set(self.uninitialized_rules)
@@ -487,7 +484,7 @@ class Interpreter(object):
                 # now backchained.
                 for d in self.rule_dep[head_fn]:
                     if rule != d and d.head_fn not in self._gbc:
-                        self.recompile.add(d)
+                        self.needs_recompile(d)
 
             self._gbc[head_fn].append(query)
 
@@ -597,8 +594,8 @@ class Interpreter(object):
             visited = set()
 
         if fn not in self._gbc or fn in visited:
-            # don't refresh non-BC computation be careful not to get stuck in an
-            # infinite loop if there is a cycle in the dep graph
+            # don't refresh non-BC computation. Also, be careful not to get
+            # stuck in an infinite loop if there is a cycle in the dep graph
             return
 
         visited.add(fn)
@@ -740,6 +737,9 @@ class Interpreter(object):
                     else:
                         print >> out, '      %s' % (e)
 
+                    #print >> out
+                    #print >> out, magenta % indent(e.traceback.rstrip(), indent='        ')
+
                     print >> out
                     print >> out, r.render_ctx(e.exception_frame, indent='      ')
                     print >> out
index 046135cc92bb90031eebadecdcdadc64e1443d7e..9444553a206003d3ad125236119954c740dcc5e9 100644 (file)
@@ -196,7 +196,11 @@ class Crux(object):
 
             # infix
             if (not label[0].isalpha() and label[0] not in ('$','&') and len(fn_args) == 2) \
-                    or label in ('in', 'and', 'or', 'with_key', '->', 'is'):
+                    or label in ('in', 'with_key', '&with_key', '->', '&->', 'is'):
+
+                if label in {'&with_key', '->', '&->'}:
+                    label = label[1:]
+
                 [a,b] = fn_args
                 return '(%s %s %s)' % (a, label, b)
             return '%s(%s)' % (label, ', '.join(fn_args))
@@ -225,24 +229,12 @@ class Crux(object):
                 _e = e
                 a = []
                 while e.label == '& cons':
-
-                    # TODO: crashlogs/abarany:2013-07-24:11:47:31:17823.log
-                    x, xs = e.body           # e = _a3 = & cons(uV, uX)
-
-                    # g.incoming = {
-                    #  '_a5': [_a5 = edge@1(uX, uU, uV)],
-                    #  '_a4': [_a4 = pathto@0(uU)],
-                    #  '_a3': [_a3 = & cons(uV, uX)],
-                    #  '_a2': [_a2 = +@2(_a4, _a5)],
-                    #  'uU': [],
-                    #  '_t1': [_t1 = & with_key(_a2, _a3)],
-                    #  'uV': [],
-                    #  '_t0': [_t0 = & pathto(uV)], 'uX': []
-                    # }
-                    # xs = 'uX'
-
-                    [e] = g.incoming[xs]
+                    x, xs = e.body
                     a.append(self._get_function(x))
+                    if not g.incoming[xs]:
+                        a.append(self._get_function(xs))
+                        break
+                    [e] = g.incoming[xs]
 
                 if e.label == '& nil':
                     return '[%s]' % ', '.join(a)
index 3ee0e63b877adf6bef25baae98923efc25902a3a..7c30108ad0436e532f07f61a028032ea649149d5 100644 (file)
@@ -11,9 +11,8 @@ import re, os, cmd, readline
 from utils import ip, lexer, subst, drepr, _repr, get_module, yellow, \
     green, bold
 from stdlib import topython, todyna
-from errors import DynaCompilerError
+from errors import DynaCompilerError, show_traceback
 from config import dotdynadir
-from errors import show_traceback
 import load, post
 
 from interpreter import Rule
@@ -277,6 +276,7 @@ class REPL(cmd.Cmd, object):
         errors_before = self.interp.error.copy()
         yield
         if errors_before.items() != self.interp.error.items():
+
             e = set(errors_before) | set(self.interp.error)
             new_errors = 0
             cleared_errors = 0
@@ -295,7 +295,7 @@ class REPL(cmd.Cmd, object):
                     #print 'cleared error at `%s`.' % k
                     cleared_errors += 1
                 elif not was and now:
-#                    print 'new error at `%s`.' % k, es
+                    #print 'new error at `%s`.' % k, es
                     new_errors += 1
             if new_errors and cleared_errors:
                 print yellow % '>>>', '%s new errors, %s errors cleared. Type `sol` for details.\n' \
index 69d6ab9900e767c52d5ac11bbb9a774a1b63c83a..94f39165f890f01619fd6bd804c86a788c7e21ae 100644 (file)
@@ -20,6 +20,10 @@ from glob import glob
 #        return todyna([x+a for a in self.aslist])
 
 
+def lookup(k, alist):
+    a = dict(alist)
+    return a.get(k)
+
 def or_(x, y):
     if not (isbool(x) and isbool(y)):
         raise TypeError('`|` expected Boolean arguments, got `%s` and `%s`' \
index c158cff3db815392d8cac2167f8c5e6bde3dacc9..b89ca7e3f975d4de57a4764162d1b78a80bd27a0 100644 (file)
@@ -98,4 +98,4 @@ class MapsTo(NoIntern, Term):
     def __init__(self, k, v):
         super(MapsTo, self).__init__('->/2', (k, v))
     def __repr__(self):
-        return '%s -> %s' % self.args
+        return '%s -> %s' % tuple(map(_repr, self.args))
index 1a299335bbf67d9fa51c2e094066b79f97e26519..1559f5676011c01c3f01ab10311e706474820b21 100644 (file)
@@ -28,6 +28,12 @@ def parse_parser_state(parser_state):
     return backchain, ruleix, iaggr, other
 
 
+def indent(x, indent=''):
+    if isinstance(x, basestring):
+        return re.compile('^(.*)$', flags=re.MULTILINE).sub(indent + r'\1', x)
+    else:
+        return [indent + y for y in x]
+
 
 class _true(object):
     def __nonzero__(self):
index db11ffe007cb2d4939634ec246008395a3af4d7a..f1f6f1c4966bf4a3739ab5bc19c6b6d8a85fdd7e 100644 (file)
@@ -178,12 +178,12 @@ disposTab_prologish t = DisposTab s a
        , (("false",0),(SDQuote,[]))
        -- key
        , (("$key" ,1),(SDEval,[ADQuote]))
-       , (("with_key",2),(SDQuote,[ADEval, ADEval]))
+       , (("with_key",2),(SDQuote,[ADEval,ADEval]))
        -- lists
        , (("nil",  0),(SDQuote,[]))
        , (("cons", 2),(SDQuote,[ADEval,ADEval]))
-       , (("->",2),(SDQuote,[ADQuote, ADQuote]))
-       , ((":",2),(SDQuote,[ADQuote, ADQuote]))       
+       , (("->",   2),(SDQuote,[ADEval,ADEval]))
+       , ((":",    2),(SDQuote,[ADEval,ADEval]))
        ]
 
 -- | Make the default surface syntax more functional.  Here, all functors
@@ -214,9 +214,9 @@ disposTab_dyna t = DisposTab s a
        -- key
        , (("$key" ,1),(SDEval,[ADQuote]))
        , (("with_key",2),(SDQuote,[ADEval, ADEval]))
-       , (("->",2),(SDQuote,[ADQuote, ADQuote]))
-       , ((":",2),(SDQuote,[ADQuote, ADQuote]))
-
+       -- tuples
+       , (("->",   2),(SDQuote,[ADEval,ADEval]))
+       , ((":",    2),(SDQuote,[ADEval,ADEval]))
        ]
 
 ------------------------------------------------------------------------}}}
index 620cb75bc781a80a330e3da3c1b50cd200a59c58..7423159dae32c62346d5b333e402cf3352e02f9e 100644 (file)
@@ -70,3 +70,14 @@ Failed to recompile rule:
 > query foo(3)
 
 foo(3) = 12.
+
+> sol
+
+Solution
+========
+a/1
+===
+a(1) = 1.
+a(2) = 2.
+a(3) = 3.
+a(4) = 4.