Improved documentation for loaders and post-processors.
pass
-#class AggregatorConflict(Exception):
-# def __init__(self, key, expected, got):
-# msg = "Aggregator conflict %r was %r trying to set to %r." \
-# % (key, expected, got)
-# super(AggregatorConflict, self).__init__(msg)
-
-
class DynaInitializerException(Exception):
def __init__(self, exception, init):
- msg = '%r in ininitializer for rule\n %s\n %s' % \
- (exception,
- parse_attrs(init)['Span'],
- parse_attrs(init)['rule'])
+ rule = parse_attrs(init)['rule']
+ span = parse_attrs(init)['Span']
+
+ if span.startswith(dotdynadir / 'tmp'):
+ # don't show users tmp files create by the repl.
+ msg = '%r in ininitializer for rule\n %s' % \
+ (exception, rule)
+
+ else:
+ msg = '%r in ininitializer for rule\n %s\n %s' % \
+ (exception,
+ span,
+ rule)
super(DynaInitializerException, self).__init__(msg)
# chart -- because it might be too big to email); input to repl.
# This should all go into a tarball.
+ if crash_handler.interp is not None:
+ crash_handler.interp()
+
print 'FATAL ERROR (%s): %s' % (etype.__name__, evalue)
- print 'Please report this error by emailing bugs@dyna.org. ' \
- 'Please attach the following file %s' % crashreport.name
+ print 'Crash log available %s' % crashreport.name
-def enable_crash_handler():
+def crash_handler():
"""
Use our custom exception handler for handling uncaught exceptions.
"""
sys.excepthook = exception_handler
+# XXX: global state...
+crash_handler.interp = None
+
def show_traceback(einfo=None):
if not einfo:
from prioritydict import prioritydict
from config import dotdynadir
-from errors import notimplemented, enable_crash_handler, \
- DynaInitializerException, DynaCompilerError
-
-from stdlib import *
+from errors import crash_handler, DynaInitializerException
class Rule(object):
self.rules = ddict(Rule)
self.error = {}
+ self.files = []
+
def __getstate__(self):
return ((self.chart,
self.agenda,
return self.go()
+ def dynac(self, filename, out=None):
+ self.files.append(filename)
+ out = dynac(filename, out)
+ self.files.append(out)
+
def dynac_code(self, code):
"""
Compile a string of dyna code.
f.write(self.parser_state) # include parser state if any.
f.write(code)
- dynac(dyna, out) # might raise compiler error
+ self.dynac(dyna, out) # might raise compiler error
return out
interp = Interpreter()
- enable_crash_handler()
+ crash_handler()
+
+
+# def pickle_interp():
+# import subprocess
+#
+# crash = dotdynadir / 'crash'
+# crash.rmtree(ignore_errors=False)
+# crash.mkdir_p()
+#
+# for f in [dotdynadir / 'crash.log'] + interp.files:
+# path(f).copy(crash)
+#
+# subprocess.Popen(['tar', 'czf', dotdynadir / 'crash.tar.gz', crash])
+#
+# crash_handler.interp = pickle_interp
+
if args.source:
plan = args.source
else:
plan = args.source + '.plan.py'
- dynac(args.source, plan)
+ interp.dynac(args.source, plan)
if args.profile:
# When profiling, its common practice to disable the garbage collector.
-#from sexpr import sexpr
-#from tsv import tsv
-#from matrix import matrix
-#from pickled import pickled
-
-import re as _re
+import re
from utils import get_module
available = 'sexpr', 'tsv', 'matrix'
def run(interp, line):
try:
- [(name, module, args)] = _re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', line)
+ [(name, module, args)] = re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', line)
except ValueError:
print 'Error: failed to parse post command.'
print ' %s' % line
-"""
-mat - Load a text file as a (jagged) matrix.
+import re
-For example
+class matrix(object):
+ """
+ Load a text file as a (jagged) matrix.
-1 2 3
-4 5
+ For example
-6 7
+ $ echo 1 2 3 > /tmp/foo
+ $ echo 4 5 >> /tmp/foo
+ $ echo >> /tmp/foo
+ $ echo 6 7 >> /tmp/foo
+ :- load m = matrix("/tmp/foo")
+ :- sol
-m(0,0) := 1. m(0,1) := 2. m(0,2) := 3
-m(1,0) := 4. m(1,1) := 5.
+ Solution
+ ========
+ m/2
+ ===
+ m(0,0) := 1.0
+ m(0,1) := 2.0
+ m(0,2) := 3.0
+ m(1,0) := 4.0
+ m(1,1) := 5.0
+ m(3,0) := 6.0
+ m(3,1) := 7.0
-m(3,0) := 6. m(3,1) := 7.
-"""
+ As you can see, by default values are interpreted as floats, to specify a
+ different type simple passing a function which will convert strings to the
+ appropriate time (e.g. str, int, float).
-import re
+ :- load m = matrix("/tmp/foo", astype=str)
+ :- sol
-class matrix(object):
+ Solution
+ ========
+ m/2
+ ===
+ m(0,0) := "1"
+ m(0,1) := "2"
+ m(0,2) := "3"
+ m(1,0) := "4"
+ m(1,1) := "5"
+ m(3,0) := "6"
+ m(3,1) := "7"
+
+ """
def __init__(self, interp, name):
self.interp = interp
-"""
-Read lisp-style S-Expressions from a file.
-"""
-
from cStringIO import StringIO
from utils import parse_sexpr
class sexpr(object):
+ """
+ Read lisp-style S-Expressions from a file.
+
+ $ echo '(a (b c) (d e)) (a b (c))' > /tmp/foo
+ $ ./dyna
+ :- load trees = sexpr("/tmp/foo")
+ :- sol
+
+ Solution
+ ========
+ trees/1
+ =======
+ trees(0) := node("a", node("b", "c"), node("d", "e"))
+ trees(1) := node("a", "b", "c")
+
+ """
def __init__(self, interp, name):
self.interp = interp
+"""
+TODO: option for stripping comments
+TODO: option for strict number of columns.
+"""
+
import re
class tsv(object):
-
"""
Load tab-delimited files.
- TODO: option for stripping comments
- TODO: option for strict number of columns.
+ :- load row = tsv("test/repl/english.gr")
+ :- sol
+ row/4
+ =====
+ row(0,"0","S","NP VP") := true
+ row(1,"1.58","ROOT","S .") := true
+ row(2,"1.58","ROOT","S !") := true
+ row(3,"1.58","ROOT","VP !") := true
+ row(4,"3.81","VP","V") := true
+ row(5,"3.81","VP","V NP") := true
+ row(6,"1.49","VP","V VP") := true
+ ...
+
"""
def __init__(self, interp, name):
"""
try:
- changed = self.interp.do(dynac(filename))
+ changed = self.interp.do(self.interp.dynac(filename))
except DynaCompilerError as e:
print e
else:
from subprocess import Popen, PIPE
from IPython.frontend.terminal.embed import InteractiveShellEmbed
from config import dynahome, dotdynadir
-import signal
-from contextlib import contextmanager
from collections import namedtuple
return ''.join((_repr(v[x]) if x in v else x) for x in lexer(term))
-
-@contextmanager
-def interrupt_after():
-
- def handler(signum, frame):
- sys.stderr.write('^C')
- handler.interrupted = True
- return signal.SIG_IGN
-
- handler.interrupted = False
- signal.signal(signal.SIGINT, handler)
-
- yield
-
- signal.signal(signal.SIGINT, signal.default_int_handler)
-
- if handler.interrupted:
- raise KeyboardInterrupt
+#import signal
+#from contextlib import contextmanager
+#
+#@contextmanager
+#def interrupt_after():
+#
+# def handler(signum, frame):
+# sys.stderr.write('^C')
+# handler.interrupted = True
+# return signal.SIG_IGN
+#
+# handler.interrupted = False
+# signal.signal(signal.SIGINT, handler)
+#
+# yield
+#
+# signal.signal(signal.SIGINT, signal.default_int_handler)
+#
+# if handler.interrupted:
+# raise KeyboardInterrupt
class ddict(dict):