]> hydra-www.ietfng.org Git - dyna2/commitdiff
cleanup/move repl into its own module.
authorTim Vieira <tim.f.vieira@gmail.com>
Sat, 1 Jun 2013 06:53:15 +0000 (02:53 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Sat, 1 Jun 2013 06:53:15 +0000 (02:53 -0400)
src/Dyna/Backend/Python/defn.py
src/Dyna/Backend/Python/interpreter.py
src/Dyna/Backend/Python/repl.py [new file with mode: 0644]

index 1f830a646f8c8d46b85f5367db36548175764fca..1e0603b75fdde7d1e148bdfe5100045960bbcc3e 100644 (file)
@@ -1,8 +1,3 @@
-"""
-Misc doctests
--------------
-"""
-
 import math, operator
 from collections import defaultdict, Counter
 from utils import red
index 2155b21a555c8d6aa284727a0aa69ea70de3a8fe..a30ad4a86b70a60cda7143ee9f0a3bb0796bbb37 100644 (file)
@@ -1,17 +1,17 @@
 #!/usr/bin/env python
-from __future__ import division
 
 """
 
+MISC
+====
 
-===
 
 This has an absurd parse:
   x += f('result = 5').
 
+
 set= is wrong .. needs to keep counts like bag=
 
-===
 
 
 Warnings/lint checking
@@ -84,15 +84,31 @@ INTERPRETER
   Should errors have linear provenance? The error could have come from more than
   one parent.
 
-"""
 
-#from debug import ultraTB2; ultraTB2.enable()
-#from debug import saverr; saverr.enable(editor=True)
+  The reason we have to support error is because the system might need to go
+  through an error state before it can reach it's fixed out. In order to be
+  invariant to execution order (preserve our semantice) we to need to have the
+  ability fo reach pass thru an error state.
+
+  for example:
+   :- a += 1/c.
+   :- b += 0.         % (1)
+   :- b += 1.         % (2)
 
+  If we process (1) before (2) we get an error value for `a` due to the divide
+  by zero but then once (2) is processed the error should go away because `b` is
+  no longer `0`. Whereas, (2) before (1) is ok!
+
+  timv: This isn't sufficiently motivating because we can just leave `a` as
+  `null` until we pass the divide by zero error.
+
+"""
+
+from __future__ import division
 import os, sys
-from cStringIO import StringIO
 from collections import defaultdict
 from argparse import ArgumentParser
+
 from utils import ip, red, green, blue, magenta, yellow, dynahome
 from defn import agg_bind
 
@@ -101,12 +117,6 @@ class AggregatorConflict(Exception):
     pass
 
 
-#def eval(x):
-#    exec x in globals(), locals()
-#    if 'result' in locals():
-#        return locals()['result']
-
-
 trace = None
 
 # TODO: as soon as we have safe names for these things we can get rid of this.
@@ -123,16 +133,6 @@ class aggregator_indirect(dict):
         self[item] = a
         return a
 
-
-aggregator = aggregator_indirect()
-
-
-chart = chart_indirect()
-
-_delete = False
-agenda = set()
-agg = {}
-
 # when a new rule comes along it puts a string in the following dictionary
 class aggregator_declaration(object):
     def __init__(self):
@@ -144,7 +144,13 @@ class aggregator_declaration(object):
     def __getitem__(self, key):
         return self.map[key]
 
+
+
+_delete = False
+agenda = set()
 agg_decl = aggregator_declaration()
+aggregator = aggregator_indirect()
+chart = chart_indirect()
 
 
 def dump_charts(out=sys.stdout):
@@ -305,7 +311,10 @@ def update_dispatcher(item, val):
     if val is None:
         return
     for handler in register.handlers[item.fn]:
-        handler(item, val)
+        try:
+            handler(item, val)
+        except ZeroDivisionError as e:
+            print >> trace, 'ZeroDivisionError: %s on update %s = %s' % (e, item, val)
 
 
 def peel(fn, item):
@@ -406,10 +415,7 @@ def go():
 
 
 def dynac(f, out):
-    cmd = '%s/dist/build/dyna/dyna -B python -o "%s" "%s"' % (dynahome, out, f)
-    if os.system(cmd):
-#        print 'command failed:\n\t' + cmd
-        return True
+    return os.system('%s/dist/build/dyna/dyna -B python -o "%s" "%s"' % (dynahome, out, f))
 
 
 def dynac_code(code, debug=False, run=True):
@@ -429,9 +435,6 @@ def dynac_code(code, debug=False, run=True):
         import debug
         debug.main(dyna)
 
-    with file(out) as f:
-        new_code = f.read()
-
     if run:
         do(out)
 
@@ -463,128 +466,12 @@ def do(filename):
     load(filename)
 
     for init in initializer.handlers:   # assumes we have cleared
-        init()
-
-    go()
-
-
-import cmd, readline
-
-class REPL(cmd.Cmd, object):
-
-    def __init__(self, hist):
-        cmd.Cmd.__init__(self)
-        self.prompt = ":- "
-        self.hist = hist
-        if not os.path.exists(hist):
-            with file(hist, 'wb') as f:
-                f.write('')
-        readline.read_history_file(hist)
-
-    def do_exit(self, _):
-        readline.write_history_file(self.hist)
-        return -1
-
-    def do_EOF(self, args):
-        "Exit on end of file character ^D."
-        print 'exit'
-        return self.do_exit(args)
-
-    def precmd(self, line):
-        """
-        This method is called after the line has been input but before it has
-        been interpreted. If you want to modify the input line before execution
-        (for example, variable substitution) do it here.
-        """
-        return line
-
-    def do_changed(self, _):
-        if not changed:
-            print 'nothing changed.'
-            print
-            return
-        print
-        print 'Changed'
-        print '============='
-        for x, v in changed.items():
-            print pretty(x), ':=', v
-        print
-
-    def do_chart(self, args):
-        if not args:
-            dump_charts()
-        else:
-            unrecognized = set(args.split()) - set(chart.keys())
-            for f in unrecognized:
-                print 'unrecognized predicate', f
-            if unrecognized:
-                print 'available:\n\t' + '\t'.join(chart.keys())
-                return
-            for f in args.split():
-                print chart[f]
-                print
-
-    def emptyline(self):
-        """Do nothing on empty input line"""
-        pass
-
-    def do_ip(self, _):
-        ip()
-
-    def do_go(self, _):
-        go()
-
-    def do_trace(self, args):
-        global trace
-        if args == 'on':
-            trace = sys.stdout
-        elif args == 'off':
-            trace = file(os.devnull, 'w')
-        else:
-            print 'Did not understand argument %r please use (on or off).' % args
-
-    def do_debug(self, line):
-        dynac_code(line, debug=True, run=False)
-
-    def do_query(self, line):
-
-        if line.endswith('.'):
-            print "Queries don't end with a dot."
-            return
-
-        query = 'zzz set= _VALUE is %s, eval("print 12345"), _VALUE.' % line
-
-        print blue % query
-
-        self.default(query)
-
-    def default(self, line):
-        """
-        Called on an input line when the command prefix is not recognized.  In
-        that case we execute the line as Python code.
-        """
-        line = line.strip()
-        if not line.endswith('.'):
-            print "ERROR: Line doesn't end with period."
-            return
-        try:
-            if dynac_code(line):  # failure.
-                return
-        except AggregatorConflict as e:
-            print 'AggregatorConflict:', e
-        else:
-            self.do_changed('')
-
-    def cmdloop(self, _=None):
         try:
-            super(REPL, self).cmdloop()
-        except KeyboardInterrupt:
-            print '^C'
-            self.cmdloop()
-
+            init()
+        except ZeroDivisionError as e:
+            print >> trace, 'ZeroDivisionError:', e, 'in initializer.'
 
-def repl(hist):
-    REPL(hist).cmdloop()
+    go()
 
 
 def main():
@@ -628,6 +515,7 @@ def main():
         dump_charts()
 
     if argv.interactive:
+        from repl import repl
         repl(hist = argv.source + '.hist')
 
 
diff --git a/src/Dyna/Backend/Python/repl.py b/src/Dyna/Backend/Python/repl.py
new file mode 100644 (file)
index 0000000..2142d77
--- /dev/null
@@ -0,0 +1,123 @@
+import os, sys
+import cmd
+import readline
+
+import interpreter
+
+
+class REPL(cmd.Cmd, object):
+
+    def __init__(self, hist):
+        cmd.Cmd.__init__(self)
+        self.prompt = ":- "
+        self.hist = hist
+        if not os.path.exists(hist):
+            with file(hist, 'wb') as f:
+                f.write('')
+        readline.read_history_file(hist)
+        self.do_trace('off')
+
+    def do_exit(self, _):
+        readline.write_history_file(self.hist)
+        return -1
+
+    def do_EOF(self, args):
+        "Exit on end of file character ^D."
+        print 'exit'
+        return self.do_exit(args)
+
+    def precmd(self, line):
+        """
+        This method is called after the line has been input but before it has
+        been interpreted. If you want to modify the input line before execution
+        (for example, variable substitution) do it here.
+        """
+        return line
+
+    def do_changed(self, _):
+        if not interpreter.changed:
+            print 'nothing changed.'
+            print
+            return
+        print
+        print 'Changed'
+        print '============='
+        for x, v in interpreter.changed.items():
+            print x, ':=', v
+        print
+
+    def do_chart(self, args):
+        if not args:
+            interpreter.dump_charts()
+        else:
+            unrecognized = set(args.split()) - set(interpreter.chart.keys())
+            for f in unrecognized:
+                print 'unrecognized predicate', f
+            if unrecognized:
+                print 'available:\n\t' + '\t'.join(interpreter.chart.keys())
+                return
+            for f in args.split():
+                print interpreter.chart[f]
+                print
+
+    def emptyline(self):
+        """Do nothing on empty input line"""
+        pass
+
+    def do_ip(self, _):
+        interpreter.ip()
+
+    def do_go(self, _):
+        interpreter.go()
+
+    def do_trace(self, args):
+        if args == 'on':
+            interpreter.trace = sys.stdout
+        elif args == 'off':
+            interpreter.trace = file(os.devnull, 'w')
+        else:
+            print 'Did not understand argument %r please use (on or off).' % args
+
+    def do_debug(self, line):
+        interpreter.dynac_code(line, debug=True, run=False)
+
+    def do_query(self, line):
+
+        if line.endswith('.'):
+            print "Queries don't end with a dot."
+            return
+
+        query = 'zzz set= _VALUE is %s, eval("print 12345"), _VALUE.' % line
+
+        print blue % query
+
+        self.default(query)
+
+    def default(self, line):
+        """
+        Called on an input line when the command prefix is not recognized.  In
+        that case we execute the line as Python code.
+        """
+        line = line.strip()
+        if not line.endswith('.'):
+            print "ERROR: Line doesn't end with period."
+            return
+        try:
+            if interpreter.dynac_code(line):  # failure.
+                return
+        except interpreter.AggregatorConflict as e:
+            print 'AggregatorConflict:', e
+        else:
+            self.do_changed('')
+
+    def cmdloop(self, _=None):
+        try:
+            super(REPL, self).cmdloop()
+        except KeyboardInterrupt:
+            print '^C'
+            self.cmdloop()
+
+
+def repl(hist):
+    REPL(hist).cmdloop()
+