From: Tim Vieira Date: Wed, 14 Aug 2013 19:49:59 +0000 (-0400) Subject: several tweaks. X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=ee67212587ab5fa85fc8b9dc0b09d631ba287d08;p=dyna2 several tweaks. --- diff --git a/dyna-doctest b/dyna-doctest deleted file mode 100755 index c28b23d..0000000 --- a/dyna-doctest +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -exec python ${DYNAHOME:-.}/src/Dyna/Backend/Python/dyna_doctest.py "$@" diff --git a/run-doctests.py b/run-doctests.py index ee8d18d..57d6d3b 100755 --- a/run-doctests.py +++ b/run-doctests.py @@ -2,6 +2,7 @@ from path import path from cStringIO import StringIO from subprocess import Popen, PIPE +from argparse import ArgumentParser import re, sys src = 'src/Dyna/Backend/Python' @@ -14,70 +15,87 @@ if not path(src).exists(): from utils import red, green from dyna_doctest import run -failures = [] -print 'End-to-end' -print '==========' +def end_to_end(tests): + print 'End-to-end' + print '==========' + for x, z in tests: + print x, + sys.stdout.flush() -for z in sorted(path('examples/expected').glob("*.py.out")): + y = x + '.py.out' - x = re.sub('(examples/)expected/(.*).py.out', r'\1\2.dyna', z) - y = x + '.py.out' + # run ./dyna + p = Popen(['./dyna', x, '-o', y], stdout=PIPE, stderr=PIPE) + (out, err) = p.communicate() - print x, - sys.stdout.flush() + assert not p.returncode, out + '\n' + err - # run ./dyna - p = Popen(['./dyna', x, '-o', y], stdout=PIPE, stderr=PIPE) - (out, err) = p.communicate() + # look at diff + p = Popen(['diff', y, z], stdout=PIPE, stderr=PIPE) + (out, err) = p.communicate() - assert not p.returncode, out + '\n' + err + if not p.returncode: + print green % 'pass' + else: + print red % 'fail' + yield [x, out + '\n' + err] - # look at diff - p = Popen(['diff', y, z], stdout=PIPE, stderr=PIPE) - (out, err) = p.communicate() - if not p.returncode: - print green % 'pass' - else: - print red % 'fail' - failures.append([x, out + '\n' + err]) +def run_doctests(files): + print + print 'Doctests' + print '========' + for x in files: + print x, + sys.stdout.flush() + with file(x) as f: + g = StringIO() + if run(f.read(), g): + yield [x, g.getvalue()] + print red % 'fail' + else: + print green % 'pass' -print -print 'Doctests' -print '========' -for x in sorted(path('test').glob("*/*.dynadoc")): +def main(): - if '/ptb.dynadoc' in x: - continue + parser = ArgumentParser() + parser.add_argument('files', nargs='*', type=path) - if '/known-failures/' in x: - continue + args = parser.parse_args() - print x, - sys.stdout.flush() - with file(x) as f: - g = StringIO() - if run(f.read(), g): - failures.append([x, g.getvalue()]) - print red % 'fail' - else: - print green % 'pass' + failures = [] + # default set of doctests + if not args.files: + tests = [(re.sub('(examples/)expected/(.*).py.out', r'\1\2.dyna', z), z) \ + for z in sorted(path('examples/expected').glob("*.py.out"))] + failures.extend(end_to_end(tests)) -for f, log in failures: - print - print '================================================' - print f - print '================================================' - print log + args.files = [x for x in sorted(path('test').glob("*/*.dynadoc")) \ + if '/ptb.dynadoc' not in x \ + and '/known-failures/' not in x] + failures.extend(run_doctests(args.files)) -if failures: - print '================================================' - print 'FAILURES (%s)' % len(failures) - print '================================================' - for f, _ in failures: + # detailed failure reports + for f, log in failures: + print + print '================================================' print f - exit(1) + print '================================================' + print log + + # failure summary + if failures: + print '================================================' + print 'FAILURES (%s)' % len(failures) + print '================================================' + for f, _ in failures: + print f + exit(1) + + +if __name__ == '__main__': + main() diff --git a/src/Dyna/Backend/Python/chart.py b/src/Dyna/Backend/Python/chart.py index 1604747..7cc610a 100644 --- a/src/Dyna/Backend/Python/chart.py +++ b/src/Dyna/Backend/Python/chart.py @@ -17,6 +17,12 @@ class Chart(object): return aggregator(self.agg_name, term) def set_aggregator(self, agg): + """ + if we have a new aggregator and an existing chart, we need to shove a + bunch of aggregators into the interned nodes. This happens when a new + rule (e.g. from the repl) gives something a value, which didn't have a + value before. + """ self.agg_name = agg for item in self.intern.values(): assert item.value is None, [item, item.value, item.aggregator] # shouldn't change aggregator when non-null. diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 944fcfb..31abf1f 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -51,19 +51,11 @@ class Rule(object): c = Crux(head=None, rule=self, body=None, vs = ctx) return '\n'.join(indent + line for line in c.format()) -# def debug(self): -# import debug -# with file(dotdynadir / 'tmp.dyna', 'wb') as f: -# f.write(self.src) -# debug.main(f.name) - -# TODO: yuck, hopefully temporary measure to support pickling the Interpreter's -# state -class foo(dict): +class Charts(dict): def __init__(self, agg_name): self.agg_name = agg_name - super(foo, self).__init__() + super(Charts, self).__init__() def __missing__(self, fn): arity = int(fn.split('/')[-1]) self[fn] = c = Chart(fn, arity, self.agg_name[fn]) @@ -89,7 +81,7 @@ class Interpreter(object): self._gbc = defaultdict(list) # data structures self.agenda = prioritydict() - self.chart = foo(self.agg_name) + self.chart = Charts(self.agg_name) self.error = {} self.changed = {} # misc @@ -106,16 +98,9 @@ class Interpreter(object): def new_fn(self, fn, agg): if self.agg_name[fn] is None: self.agg_name[fn] = agg - # if we have a new aggregator and an existing chart we need to shove - # a bunch of aggregators into the interned nodes. - # - # This happens when a new rule (e.g. from the repl) gives something - # a value, which didn't have a value before -- i.e. was only used as - # structure. - if fn in self.chart: - self.chart[fn].set_aggregator(agg) + self.chart[fn].set_aggregator(agg) # check for aggregator conflict. - assert self.agg_name[fn] == agg, (fn, self.agg_name[fn], agg) + assert self.agg_name[fn] == agg def build(self, fn, *args): # handle a few special cases where the item doesn't have a chart @@ -127,10 +112,6 @@ class Interpreter(object): return MapsTo(*args) if fn == '$key/1': self.new_fn(fn, '=') - # if we haven't seen this functor before, it probably doesn't have a - # Chart, so lets go ahead and create one. - if fn not in self.agg_name: - self.new_fn(fn, None) return self.chart[fn].insert(args) def delete(self, item, val, ruleix, variables): @@ -569,7 +550,8 @@ class Interpreter(object): visited.add(fn) - # YUCK: find some was to avoid this... + # YUCK: find some was to avoid this... alternatively, we can run + # deletes first. self.was = {x: x.value for x in self.chart[fn].intern.values()} for x in self.chart[fn].intern.values(): diff --git a/src/Dyna/Backend/Python/term.py b/src/Dyna/Backend/Python/term.py index f2b2387..126a1b9 100644 --- a/src/Dyna/Backend/Python/term.py +++ b/src/Dyna/Backend/Python/term.py @@ -16,14 +16,19 @@ class Term(object): # return self is other def __cmp__(self, other): - if self is other: - return 0 try: - if self.fn == other.fn: - return cmp(self.args, other.args) - else: - return cmp(self.fn, other.fn) - except AttributeError: + if self is other: + return 0 + try: + if self.fn == other.fn: + return cmp(self.args, other.args) + else: + return cmp(self.fn, other.fn) + except AttributeError: + return 1 + except RuntimeError: + # HACK: sometimes we have a cyclic (or very deep) term and hit a + # recursion limit. return 1 def __repr__(self): @@ -34,13 +39,13 @@ class Term(object): return '%s(%s)' % (fn, ','.join(map(_repr, self.args))) +# TODO: maybe the right way to do this is with a weak value dictionary class NoIntern(Term): "Mix-in which adds hash and equality method for terms which aren't interned." + def __eq__(self, other): - try: - return (self.fn, self.args) == (other.fn, other.args) - except AttributeError: - return False + return Term.__cmp__(self, other) == 0 + def __hash__(self): return hash((self.fn, self.args))