From: Tim Vieira Date: Tue, 18 Jun 2013 00:40:18 +0000 (-0400) Subject: refactor load and post-process. both are availabl and the REPL and command-line ... X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=9521cd7f33d85d59662bef80c4aad48ce5e9467c;p=dyna2 refactor load and post-process. both are availabl and the REPL and command-line (see test/repl/load.bash for example usage) --- diff --git a/dyna b/dyna index d0549fa..a082bd9 100755 --- a/dyna +++ b/dyna @@ -1,3 +1,3 @@ #!/usr/bin/env bash -exec python ${DYNAHOME:-.}/src/Dyna/Backend/Python/interpreter.py $@ +exec python ${DYNAHOME:-.}/src/Dyna/Backend/Python/interpreter.py "$@" diff --git a/examples/force.dyna b/examples/force.dyna index 4d0c1dd..2872fa7 100644 --- a/examples/force.dyna +++ b/examples/force.dyna @@ -39,8 +39,8 @@ node(U) := true for edge(_,U). pos(U,T) := tuple(x(U, T), y(U, T)). % visualization -frame(T, Item) := node(Name), Item is &text(Name, pos(Name, T)). -frame(T, Item) := edge(U,V), Item is &line(pos(U, T), pos(V, T)). +frame(T, &text(Name, pos(Name, T))) := true for _ is node(Name). +frame(T, &line(pos(U, T), pos(V, T))) := true for _ is edge(U,V). % declare some edges edge("a", "b") := 1. diff --git a/src/Dyna/Backend/Python/draw_circuit.py b/src/Dyna/Backend/Python/draw_circuit.py deleted file mode 100644 index 0ebb466..0000000 --- a/src/Dyna/Backend/Python/draw_circuit.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -Crude visualization of circuit pertaining to state of the interpreter. -""" - -import webbrowser -from debug import Hypergraph -from cStringIO import StringIO - -def circuit(edges): - # create hypergraph object - g = Hypergraph() - for e in edges: - head, label, body = e - g.edge(str(head), str(label), map(str, body)) - return g - - -def infer_edges(interp): - edges = set() - - # Use rule initializers to find all active hyperedges in the current Chart. - def _emit(item, _, ruleix, variables): - b = variables['nodes'] - b.sort() - b = tuple(b) - edges.add((item, ruleix, b)) - - for r in interp.rules.values(): - r.init(emit=_emit) - - return edges - - -def main(interp): - es = infer_edges(interp) - c = circuit(es) - - with file('/tmp/state.html', 'wb') as f: - print >> f, """ - - - - - - """ - - x = StringIO() - interp.dump_charts(x) - - print >> f, '
%s
' \ - % '

Charts

%s' \ - % '
%s
' \ - % x.getvalue() - - print >> f, """ -
-

Hypergraph

- %s -
- """ % c.render('circuit') - - print >> f, '' - - webbrowser.open(f.name) diff --git a/src/Dyna/Backend/Python/graph.py b/src/Dyna/Backend/Python/graph.py deleted file mode 100644 index 44f3628..0000000 --- a/src/Dyna/Backend/Python/graph.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Postprocessor for animated visualization of basic elements such as lines and -text. - -We look for the following patterns in the dynabase - - visual element - v - frame(T, &text(String, tuple(X, Y))). - ^ - time index - -Frames should have value true. The example above places a text element reading -`String` at position `(X,Y)` in a frame at time `T`. This element can be -specified by dyna rule. -""" - -import pylab as pl -from matplotlib.animation import FuncAnimation -from collections import defaultdict - -def main(interp): - - frame = defaultdict(list) - for _, [t, item], val in interp.chart['frame/2'][:,:,:]: - if val: - frame[t].append(item) - - nframes = max(frame) - - def draw_frame(t): - ax.cla() - ax.set_title(t) - ax.set_xlim(-2,2) # TODO: this isn't right... - ax.set_ylim(-2,2) - if t not in frame: - print 'frame', t, 'missing.' - for item in frame[t]: - if item.fn == 'line/2': - [(a,b), (c,d)] = item.args - ax.plot([a,c], [b,d], color='b', alpha=0.5) - elif item.fn == 'text/2': - (s,(x,y)) = item.args - ax.text(x,y,s) - else: - print 'dont know how to render', item - - fig = pl.figure() - ax = pl.axes() - - print 'creating animation..' - anim = FuncAnimation(fig, draw_frame, frames=nframes) - print 'saving...' - anim.save('examples/force.dyna.mp4', fps=30, extra_args=['-vcodec', 'libx264']) - print 'wrote examples/force.dyna.mp4' diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 966bb51..47e8b04 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -23,20 +23,16 @@ TODO - doc tests for Dyna code. - - think about indices as memoized queries - - - let Dyna do some of the work for you. think about using Dyna to maintain - rules and update handlers. + - Use Dyna do some more work! think about using Dyna to maintain rules, update + handlers, and indices (as Jason points out indices are just memoized + queries). - magic templates transform for backward chaining, for example: :- sigmoid(X) := needs(X), 1 / (1 + exp(-X)). :- needs(0.5). - - operator for getattr (this will generate slightly different code because we - don't want to look up by string -- i.e. call the getattr builtin). - - - hook for python imports? + - hook for python imports? or maybe an arbirary preamble/epilogue. :- python: from numpy import exp, sqrt, log @@ -58,16 +54,17 @@ BUGS FASTER ====== - - specialize calls to emit, don't build the big dictionaries if the aggregator - doesn't use them. Consider generate both version (or an argument to the - update handler which will skip the appropriate code paths). + - specialize calls to emit: don't build the local variable dictionaries if the + aggregator doesn't use them. Consider generate both versions (or an argument + to the update handler which will skip the appropriate code paths). - faster charts (dynamic argument types? jason's trie data structure) - teach planner to prefer not to use the value column, because it's not indexed. - - Consider indexing value column if plans will need it. + - Collect all query modes use by the planner. Consider indexing value column if + plans need it. - dynac should provide routines for building terms. We can hack something together with anf output, but this will be prety kludgy and inefficient. @@ -174,6 +171,9 @@ from collections import defaultdict from hashlib import sha1 from time import time +import load, post + + from chart import Chart, Term, _repr from defn import aggregator from utils import ip, red, green, blue, magenta, yellow, parse_attrs, \ @@ -596,29 +596,24 @@ def peel(fn, item): def main(): parser = argparse.ArgumentParser(description="The dyna interpreter!") - parser.add_argument('source', - help='Path to Dyna source file (or plan if --plan=true).', nargs='?') + parser.add_argument('source', nargs='?', + help='Path to Dyna source file (or plan if --plan=true).') parser.add_argument('--plan', action='store_true', help='`source` specifies output of the compiler instead of dyna source code.') parser.add_argument('-i', dest='interactive', action='store_true', - help='Fire-up an IPython shell.') - parser.add_argument('-o', dest='output', + help='Fire-up REPL after runing solver..') + parser.add_argument('-o', '--output', dest='output', type=argparse.FileType('wb'), help='Output chart.') - parser.add_argument('--post-process', - help='run post-processing script.') + parser.add_argument('--post-process', nargs='*', + help='run post-processor.') + parser.add_argument('--load', nargs='*', + help='run loaders.') parser.add_argument('--profile', action='store_true', help='run profiler.') args = parser.parse_args() - if args.post_process is not None: - try: - pp = __import__(args.post_process) - except ImportError: - print ('ERROR: No postprocessor named %r' % args.post_process) - return - interp = Interpreter() enable_crash_handler() @@ -652,15 +647,19 @@ def main(): return interp.do(plan) + interp.dump_charts(args.output) # should be a post-processor - interp.dump_charts(args.output) + if args.load: + for cmd in args.load: + load.run(interp, cmd) + + if args.post_process: + for cmd in args.post_process: + post.run(interp, cmd) if args.interactive or not args.source: interp.repl() - if args.post_process is not None: - pp.main(interp) - if __name__ == '__main__': main() diff --git a/src/Dyna/Backend/Python/load.py b/src/Dyna/Backend/Python/load.py deleted file mode 100644 index 18b94f0..0000000 --- a/src/Dyna/Backend/Python/load.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -Load interpreter state using python's pickle protocol. -""" - -import cPickle - -from interpreter import Interpreter, foo, none - - -def main(): - with file('save.pkl', 'r') as f: - interp = cPickle.load(f) - interp.repl() - - -if __name__ == '__main__': - main() diff --git a/src/Dyna/Backend/Python/load/__init__.py b/src/Dyna/Backend/Python/load/__init__.py new file mode 100644 index 0000000..eca4929 --- /dev/null +++ b/src/Dyna/Backend/Python/load/__init__.py @@ -0,0 +1,12 @@ +from sexpr import sexpr +from tsv import tsv +from matrix import matrix +from pickled import pickled + +import re + +def run(interp, line): + [(name, module, args)] = re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', line) + m = getattr(__import__('load'), module)(interp, name) + exec 'm.main(%s)' % args + interp.go() diff --git a/src/Dyna/Backend/Python/load/matrix.py b/src/Dyna/Backend/Python/load/matrix.py new file mode 100644 index 0000000..de827a6 --- /dev/null +++ b/src/Dyna/Backend/Python/load/matrix.py @@ -0,0 +1,54 @@ +""" +mat - Load a text file as a (jagged) matrix. + +For example + +1 2 3 +4 5 + +6 7 + + +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. + +""" + +import re + +class matrix(object): + + def __init__(self, interp, name): + self.interp = interp + self.name = name + + # TODO: option for strict width + # TODO: option for stripping comments + def main(self, filename, astype=float, delim='\s+'): + + interp = self.interp + + fn = '%s/2' % self.name + if interp.agg_name[fn] is None: + interp.new_fn(fn, ':=') + + def term(a, v): + interp.emit(interp.build(fn, *a), + v, + ruleix=None, + variables=None, + delete=False) + + with file(filename) as f: + for i, line in enumerate(f): + line = line.rstrip() + if not line: + continue + if delim is not None: + line = re.split(delim, line) + else: + line = [line] + for j, v in enumerate(line): + term((i, j), astype(v)) diff --git a/src/Dyna/Backend/Python/load/pickled.py b/src/Dyna/Backend/Python/load/pickled.py new file mode 100644 index 0000000..fa592c4 --- /dev/null +++ b/src/Dyna/Backend/Python/load/pickled.py @@ -0,0 +1,27 @@ +""" +Load interpreter state using python's pickle protocol. This is the output of +`save`. + +TODO: Can we merge a pickled interpreter into an existing one? + +""" + +import cPickle + + +class pickled(object): + + def __init__(self, interp=None, name=None): + self.interp = interp + self.name = name + + def main(self, filename): + with file(filename, 'r') as f: + interp = cPickle.load(f) + return interp + + +if __name__ == '__main__': + from interpreter import Interpreter, foo, none + import sys + pickled().main(sys.argv[1]).repl() diff --git a/src/Dyna/Backend/Python/load/sexpr.py b/src/Dyna/Backend/Python/load/sexpr.py new file mode 100644 index 0000000..453bf77 --- /dev/null +++ b/src/Dyna/Backend/Python/load/sexpr.py @@ -0,0 +1,84 @@ +""" +Read lisp-style S-Expressions from a file. +""" + +from cStringIO import StringIO +from utils import parse_sexpr + + +class sexpr(object): + + def __init__(self, interp, name): + self.interp = interp + self.name = name + + def main(self, filename): + + interp = self.interp + name = self.name + + def obj(*a): + fn = '%s/%s' % (name, len(a)) + if interp.agg_name[fn] is None: + interp.new_fn(fn, ':=') + return interp.build(fn, *a) + + def node(*a): + fn = '%s/%s' % ('node', len(a)) + if interp.agg_name[fn] is None: + interp.new_fn(fn, ':=') + return interp.build(fn, *a) + + def t(xs): + if isinstance(xs, basestring): + return xs + else: + assert len(xs) > 1 + if len(xs) == 2: + [sym, a] = map(t, xs) + return node(sym, a) + elif len(xs) == 3: + [sym, a, b] = map(t, xs) + return node(sym, a, b) + else: + [sym, a] = t(xs[0]), t(xs[1]) + rest = t(['@' + xs[0]] + xs[2:]) + return node(sym, a, rest) + + contents = file(filename).read() + + for i, [x] in enumerate(parse_sexpr(contents)): + interp.emit(obj(i), + t(x), + ruleix=None, + variables=None, + delete=False) + + +# TODO: maybe really big terms should have a pretty printer +def pretty(t, initialindent=0): + "Pretty print tree as a tabbified s-expression." + f = StringIO() + out = f.write + def pp(t, indent=initialindent, indentme=True): + if indentme: + out(' '*indent) + if isinstance(t, basestring): # base case + return out('"%s"' % t) + if len(t) == 1: + if t[0]: + pp('"%s"' % t[0], indent, indentme) + return + label, children = t[0], t[1:] + label = '"%s"' % label + assert isinstance(label, basestring) + out('&t(%s, ' % label) + n = len(children) + for i, child in enumerate(children): + pp(child, indent + len(label) + 5, i != 0) # first child already indented + if i != n-1: # no newline after last child + out(',\n') + out(')') + pp(t) + out('\n') + return f.getvalue() diff --git a/src/Dyna/Backend/Python/load/tsv.py b/src/Dyna/Backend/Python/load/tsv.py new file mode 100644 index 0000000..be67a79 --- /dev/null +++ b/src/Dyna/Backend/Python/load/tsv.py @@ -0,0 +1,42 @@ +import re + +class tsv(object): + + """ + Load tab-delimited files. + + TODO: option for stripping comments + TODO: option for strict number of columns. + """ + + def __init__(self, interp, name): + self.interp = interp + self.name = name + + def main(self, filename, delim='\t'): + + interp = self.interp + name = self.name + + def term(a): + fn = '%s/%s' % (name, len(a)) + + if interp.agg_name[fn] is None: + interp.new_fn(fn, ':=') + + interp.emit(interp.build(fn, *a), + True, + ruleix=None, + variables=None, + delete=False) + + with file(filename) as f: + for i, line in enumerate(f): + line = line.rstrip() + if not line: + continue + if delim is not None: + line = re.split(delim, line) + else: + line = [line] + term([i] + line) diff --git a/src/Dyna/Backend/Python/loadmat.py b/src/Dyna/Backend/Python/loadmat.py deleted file mode 100644 index 9bd7551..0000000 --- a/src/Dyna/Backend/Python/loadmat.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -loadmat - Load a text file as a (jagged) matrix. - -For example - -1 2 3 -4 5 - -6 7 - - -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. - -""" - -import re - -interp = None -name = None - -# TODO: option for strict width -# TODO: option for stripping comments -def main(filename, astype=float, delim='\s+'): - - fn = '%s/2' % name - if interp.agg_name[fn] is None: - interp.new_fn(fn, ':=') - - def term(a, v): - interp.emit(interp.build(fn, *a), - v, - ruleix=None, - variables=None, - delete=False) - - with file(filename) as f: - for i, line in enumerate(f): - line = line.rstrip() - if not line: - continue - if delim is not None: - line = re.split(delim, line) - else: - line = [line] - - for j, v in enumerate(line): - term((i, j), astype(v)) diff --git a/src/Dyna/Backend/Python/post/__init__.py b/src/Dyna/Backend/Python/post/__init__.py new file mode 100644 index 0000000..30aa68e --- /dev/null +++ b/src/Dyna/Backend/Python/post/__init__.py @@ -0,0 +1,11 @@ +import re +from save import save +from graph import graph +from draw_circuit import draw_circuit +from dump_chart import dump_chart + + +def run(interp, line): + [(name, args)] = re.findall('([a-z][a-zA-Z_0-9]*)\((.*)\)$', line) + m = globals()[name](interp) + eval('m.main(%s)' % args) diff --git a/src/Dyna/Backend/Python/post/draw_circuit.py b/src/Dyna/Backend/Python/post/draw_circuit.py new file mode 100644 index 0000000..3d4ed5d --- /dev/null +++ b/src/Dyna/Backend/Python/post/draw_circuit.py @@ -0,0 +1,77 @@ +""" +Crude visualization of circuit pertaining to state of the interpreter. +""" + +import webbrowser +from debug import Hypergraph +from cStringIO import StringIO + + +def circuit(edges): + # create hypergraph object + g = Hypergraph() + for e in edges: + head, label, body = e + g.edge(str(head), str(label), map(str, body)) + return g + + +def infer_edges(interp): + edges = set() + + # Use rule initializers to find all active hyperedges in the current Chart. + def _emit(item, _, ruleix, variables): + b = variables['nodes'] + b.sort() + b = tuple(b) + edges.add((item, ruleix, b)) + + for r in interp.rules.values(): + r.init(emit=_emit) + + return edges + + +class draw_circuit(object): + + def __init__(self, interp): + self.interp = interp + + def main(self, outfile): + interp = self.interp + + es = infer_edges(interp) + c = circuit(es) + + with file(outfile, 'wb') as f: + print >> f, """ + + + + + + """ + + x = StringIO() + interp.dump_charts(x) + + print >> f, '
%s
' \ + % '

Charts

%s' \ + % '
%s
' \ + % x.getvalue() + + print >> f, """ +
+

Hypergraph

+ %s +
+ """ % c.render('circuit') + + print >> f, '' + + webbrowser.open(f.name) diff --git a/src/Dyna/Backend/Python/post/dump_chart.py b/src/Dyna/Backend/Python/post/dump_chart.py new file mode 100644 index 0000000..438d3d9 --- /dev/null +++ b/src/Dyna/Backend/Python/post/dump_chart.py @@ -0,0 +1,20 @@ + + +""" +Save interpreter state using python's pickle protocol. +""" + +import sys + + +class dump_chart(object): + + def __init__(self, interp): + self.interp = interp + + def main(self, filename=None): + if filename is None: + self.interp.dump_charts(sys.stdout) + else: + with file(filename, 'wb') as f: + self.interp.dump_charts(f) diff --git a/src/Dyna/Backend/Python/post/graph.py b/src/Dyna/Backend/Python/post/graph.py new file mode 100644 index 0000000..f06b460 --- /dev/null +++ b/src/Dyna/Backend/Python/post/graph.py @@ -0,0 +1,60 @@ +""" +Postprocessor for animated visualization of basic elements such as lines and +text. + +We look for the following patterns in the dynabase + + visual element + v + frame(T, &text(String, tuple(X, Y))). + ^ + time index + +Frames should have value true. The example above places a text element reading +`String` at position `(X,Y)` in a frame at time `T`. This element can be +specified by dyna rule. +""" + +import pylab as pl +from matplotlib.animation import FuncAnimation +from collections import defaultdict + +class graph(object): + + def __init__(self, interp): + self.interp = interp + + def main(self, outfile): + + frame = defaultdict(list) + for _, [t, item], val in self.interp.chart['frame/2'][:,:,:]: + if val: + frame[t].append(item) + + nframes = max(frame) + + def draw_frame(t): + ax.cla() + ax.set_title(t) + ax.set_xlim(-2,2) # TODO: this isn't right... + ax.set_ylim(-2,2) + if t not in frame: + print 'frame', t, 'missing.' + for item in frame[t]: + if item.fn == 'line/2': + [(a,b), (c,d)] = item.args + ax.plot([a,c], [b,d], color='b', alpha=0.5) + elif item.fn == 'text/2': + (s,(x,y)) = item.args + ax.text(x,y,s) + else: + print 'dont know how to render', item + + fig = pl.figure() + ax = pl.axes() + + print 'creating animation..' + anim = FuncAnimation(fig, draw_frame, frames=nframes) + print 'saving...' + anim.save(outfile, fps=30, extra_args=['-vcodec', 'libx264']) + print 'wrote examples/force.dyna.mp4' diff --git a/src/Dyna/Backend/Python/post/save.py b/src/Dyna/Backend/Python/post/save.py new file mode 100644 index 0000000..9e3ba8c --- /dev/null +++ b/src/Dyna/Backend/Python/post/save.py @@ -0,0 +1,15 @@ +""" +Save interpreter state using python's pickle protocol. +""" + +import cPickle + + +class save(object): + + def __init__(self, interp): + self.interp = interp + + def main(self, filename): + with file(filename, 'wb') as f: + cPickle.dump(self.interp, f) diff --git a/src/Dyna/Backend/Python/repl.py b/src/Dyna/Backend/Python/repl.py index fa963f3..225710e 100644 --- a/src/Dyna/Backend/Python/repl.py +++ b/src/Dyna/Backend/Python/repl.py @@ -6,6 +6,11 @@ from errors import DynaCompilerError, DynaInitializerException from chart import _repr from config import dotdynadir +from errors import show_traceback +import load, post + +from interpreter import Interpreter, foo, none + class REPL(cmd.Cmd, object): @@ -116,10 +121,6 @@ class REPL(cmd.Cmd, object): print self.interp.dump_errors() - def do_draw_circuit(self, _): - import draw_circuit - draw_circuit.main(self.interp) - def cmdloop(self, _=None): try: super(REPL, self).cmdloop() @@ -130,22 +131,17 @@ class REPL(cmd.Cmd, object): finally: readline.write_history_file(self.hist) - def do_load(self, cmd): + def do_load(self, line): try: - self._load(cmd) + load.run(self.interp, line) + self.interp.dump_charts() except: - from errors import show_traceback show_traceback() + readline.write_history_file(self.hist) - def _load(self, cmd): - import re - [(name, module, args)] = re.findall('^([a-z][a-zA-Z_0-9]*) = ([a-z][a-zA-Z_0-9]*)\((.*)\)', cmd) - - m = __import__(module) - m.interp = self.interp - m.name = name - - exec 'm.main(%s)' % args - - self.interp.go() - self.interp.dump_charts() + def do_post(self, line): + try: + post.run(self.interp, line) + except: + show_traceback() + readline.write_history_file(self.hist) diff --git a/src/Dyna/Backend/Python/save.py b/src/Dyna/Backend/Python/save.py deleted file mode 100644 index ed99a3c..0000000 --- a/src/Dyna/Backend/Python/save.py +++ /dev/null @@ -1,11 +0,0 @@ -""" -Save interpreter state using python's pickle protocol. -""" - -import cPickle - - -def main(interp): - with file('save.pkl', 'wb') as f: - cPickle.dump(interp, f) - print 'wrote', f.name diff --git a/src/Dyna/Backend/Python/sexpr.py b/src/Dyna/Backend/Python/sexpr.py deleted file mode 100644 index 7a2eff9..0000000 --- a/src/Dyna/Backend/Python/sexpr.py +++ /dev/null @@ -1,73 +0,0 @@ -import sys -from cStringIO import StringIO -from utils import parse_sexpr - - -if __name__ == '__main__': - - def t(xs): - if isinstance(xs, basestring): -# return '"%s"' % xs - return xs - else: - assert len(xs) > 1 - if len(xs) == 2: - [sym, a] = map(t, xs) -# return '&t(%s)' % ', '.join(t(x) for x in xs) - return [sym, a] - elif len(xs) == 3: - [sym, a, b] = map(t, xs) -# return '&t(%s, %s, %s)' % (sym, a, b) - return [sym, a, b] - else: - [sym, a] = t(xs[0]), t(xs[1]) - rest = t(['@' + xs[0]] + xs[2:]) -# return '&t(%s, %s, %s)' % (sym, a, rest) - return [sym, a, rest] - - - def check_binary(x): - if isinstance(x, basestring): - return True - elif len(x) in (2, 3): - return all(map(check_binary, x)) - else: - return False - - - def pretty(t, initialindent=0): - "Pretty print tree as a tabbified s-expression." - f = StringIO() - out = f.write - def pp(t, indent=initialindent, indentme=True): - if indentme: - out(' '*indent) - if isinstance(t, basestring): # base case - return out('"%s"' % t) - if len(t) == 1: - if t[0]: - pp('"%s"' % t[0], indent, indentme) - return - label, children = t[0], t[1:] - - label = '"%s"' % label - - assert isinstance(label, basestring) - out('&t(%s, ' % label) - n = len(children) - for i, child in enumerate(children): - pp(child, indent + len(label) + 5, i != 0) # first child already indented - if i != n-1: # no newline after last child - out(',\n') - out(')') - pp(t) - out('\n') - return f.getvalue() - - for i, [x] in enumerate(parse_sexpr(sys.stdin.read())): - btree = t(x) - - assert check_binary(btree) - print - print 'sentence(%s) :=\n%s.' % (i, pretty(btree, 4).rstrip()) - print diff --git a/src/Dyna/Backend/Python/term.py b/src/Dyna/Backend/Python/term.py index f1816d5..6efaf4d 100644 --- a/src/Dyna/Backend/Python/term.py +++ b/src/Dyna/Backend/Python/term.py @@ -38,11 +38,11 @@ class Term(object): __add__ = __sub__ = __mul__ = notimplemented - def subst(self, v): - if self in v: - return v[self] - # TODO: this should go thru the Chart - return Term(self.fn, tuple(x if isconst(x) else x.subst(v) for x in self.args)) +# def subst(self, v): +# if self in v: +# return v[self] +# # TODO: this should go thru the Chart +# return Term(self.fn, tuple(x if isconst(x) else x.subst(v) for x in self.args)) def _repr(x): @@ -63,6 +63,7 @@ def isconst(x): return not isinstance(x, (Variable, Term)) + class Variable(object): def __init__(self, name): @@ -111,10 +112,10 @@ class Variable(object): else: return other == self.value - def subst(self, v): - if self in v: - return v[self] - return self +# def subst(self, v): +# if self in v: +# return v[self] +# return self def extend(v, x, t): @@ -123,7 +124,7 @@ def extend(v, x, t): """ v1 = v.copy() v1[x] = t - x.value = t +# x.value = t return v1 @@ -199,38 +200,44 @@ def symbol(name): return Symbol(name) -if __name__ == '__main__': - - [f,g,h] = map(symbol, ['f','g','h']) - vs = [X,Y,Z] = map(symbol, ['X','Y','Z']) - - def test(a, b): - for v in vs: - v.value = None - - print - print 'unify %s and %s' % (a,b) - s = unify(a, b) - print '->', s - if s is None: - return - - print a, b - assert a == b - assert repr(a) == repr(b), [a,b] - - for v in vs: - v.value = None - - test(f(X), f(g(h(X,Y),X))) - test(f(X), f(g(h(Z),"foo"))) - test(f(X, Y), f("cat", 123)) - test(f(X), f(X)) - test(f(X), f(Y)) - test("abc", "abc") +#if __name__ == '__main__': +# +# [f,g,h] = map(symbol, ['f','g','h']) +# vs = [X,Y,Z] = map(symbol, ['X','Y','Z']) +# +# def test(a, b): +# for v in vs: +# v.value = None +# +# print +# print 'unify %s and %s' % (a,b) +# s = unify(a, b) +# print '->', s +# if s is None: +# return +# +# # apply new bindings +# for v, now in s.iteritems(): +# print '%s [was: %r, now: %r]' % (v, v.value, now) +# v.value = now +# +# print a, b +# assert a == b +# assert repr(a) == repr(b), [a,b] +# +# for v in vs: +# v.value = None +# +# test(f(X), f(g(h(X,Y),X))) +# test(f(X), f(g(h(Z),"foo"))) +# test(f(X, Y), f("cat", 123)) +# test(f(X), f(X)) +# test(f(X), f(Y)) +# test("abc", "abc") +# +# Z.value = 3 +# Y.value = Z +# X.value = Y +# print [X,Y,Z] +# assert X.value == Y.value == Z.value == 3 - Z.value = 3 - Y.value = Z - X.value = Y - print [X,Y,Z] - assert X.value == Y.value == Z.value == 3 diff --git a/src/Dyna/Backend/Python/tsv.py b/src/Dyna/Backend/Python/tsv.py deleted file mode 100644 index 85bc48d..0000000 --- a/src/Dyna/Backend/Python/tsv.py +++ /dev/null @@ -1,30 +0,0 @@ -import re - -interp = None -name = None - -# TODO: option for stripping comments -def main(filename, ncols=None, delim='\t'): - - def term(a): - fn = '%s/%s' % (name, len(a)) - - if interp.agg_name[fn] is None: - interp.new_fn(fn, ':=') - - interp.emit(interp.build(fn, *a), - True, - ruleix=None, - variables=None, - delete=False) - - with file(filename) as f: - for i, line in enumerate(f): - line = line.rstrip() - if not line: - continue - if delim is not None: - line = re.split(delim, line) - else: - line = [line] - term([i] + line) diff --git a/test/repl/load.bash b/test/repl/load.bash index 7cb0e8b..02d0cfb 100755 --- a/test/repl/load.bash +++ b/test/repl/load.bash @@ -2,9 +2,8 @@ # The example shows off some of the REPL's data loading commands. -echo ' -load rules_tsv = tsv("test/repl/papa.gr"). -load token = loadmat("test/repl/sentences.txt", astype=str). -' |./dyna test/repl/load.dyna -i - -#load tree_sexpr = sexpr("trees.txt", binarize=True) +./dyna test/repl/load.dyna \ + --load 'rules_tsv = tsv("test/repl/papa.gr")' \ + 'token = matrix("test/repl/sentences.txt", astype=str)' \ + 'tree = sexpr("test/repl/trees.txt")' \ + --post 'dump_chart()'