From: Tim Vieira Date: Tue, 23 Jul 2013 17:18:43 +0000 (-0400) Subject: After retracting all rules defining a functor/arity user is allowed to X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=86f00469acf1e7a2e99d3581666f79876165f4b3;p=dyna2 After retracting all rules defining a functor/arity user is allowed to change aggregator; Issue #61: can't retract wrong aggregator. --- diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 098c44e..baf1b70 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -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 + _repr, hide_ugly_filename, true, false, parse_parser_state from prioritydict import prioritydict from config import dotdynadir @@ -60,10 +60,24 @@ def none(): class Interpreter(object): + @property + def parser_state(self): + # TODO: this is pretty hacky. XREF:parser-state + bc, rix, agg, other = self.pstate + lines = [':-ruleix %d.' % rix] + for fn in bc: + [(fn, arity)] = re.findall('(.*)/(\d+)', fn) + lines.append(":-backchain '%s'/%s." % (fn, arity)) + for fn, agg in agg.items(): + [(fn, arity)] = re.findall('(.*)/(\d+)', fn) + lines.append(":-iaggr '%s'/%s %s." % (fn, arity, agg)) + lines.extend(':-%s %s.' % (k,v) for k,v in other) + return '\n'.join(lines) + def __init__(self): # declarations self.agg_name = defaultdict(none) - self.parser_state = '' + self.pstate = (set(), 0, {}, []) self.files = [] # rules self.rules = {} @@ -276,7 +290,6 @@ class Interpreter(object): return Error() else: - # no exceptions, accept emissions. for e in emits: # an error could happen here, but we assume (by contract) that this # is not possible. @@ -308,8 +321,9 @@ class Interpreter(object): for x in read_anf(contents): anf[x.ruleix] = x - # accept the new parser state - self.parser_state = env.parser_state + # update parser state + self.pstate = parse_parser_state(env.parser_state) + for k, v in env.agg_decl.items(): self.new_fn(k, v) @@ -332,8 +346,8 @@ class Interpreter(object): try: plan = self.dynac_code('\n'.join(r.src for r in sorted(self.recompile, key=lambda r: r.index))) except DynaCompilerError as e: - # TODO: it's a bit strange to ignore the error and simply print - # the error. However, since the rules in the recompile list are + # 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. @@ -531,6 +545,12 @@ class Interpreter(object): self.recompute_coarse() + # if now there are no more rules defining a functor + if not self.rule_by_head[rule.head_fn]: + del self.chart[rule.head_fn] # delete the chart. + del self.agg_name[rule.head_fn] + del self.pstate[2][rule.head_fn] # remove fn aggr def from parser state + self._agenda() return self.changed diff --git a/src/Dyna/Backend/Python/utils.py b/src/Dyna/Backend/Python/utils.py index a7c9815..58a598e 100644 --- a/src/Dyna/Backend/Python/utils.py +++ b/src/Dyna/Backend/Python/utils.py @@ -7,6 +7,27 @@ from collections import namedtuple from cStringIO import StringIO +# TODO: This is pretty hacking we should have the codegen produce something +# easier to serialize/modify/unserialize. XREF:parser-state +def parse_parser_state(parser_state): + backchain = set() + ruleix = None + iaggr = {} + other = [] + for k, v in re.findall('^:-\s*(\S+) (.*?)\s*\.$', parser_state, re.MULTILINE): + if k == 'backchain': + [(fn, arity)] = re.findall("'(.*?)'/(\d+)", v) + backchain.add('%s/%s' % (fn, arity)) + elif k == 'iaggr': + [(fn, arity, agg)] = re.findall("'(.*?)'/(\d+)\s*(.*)", v) + iaggr['%s/%s' % (fn, arity)] = agg + elif k == 'ruleix': + ruleix = int(v) + else: + other.append((k,v)) + return backchain, ruleix, iaggr, other + + class _true(object): def __nonzero__(self): diff --git a/test/repl/retract-aggregator.dyna b/test/repl/retract-aggregator.dyna new file mode 100644 index 0000000..a54e611 --- /dev/null +++ b/test/repl/retract-aggregator.dyna @@ -0,0 +1,36 @@ +% After retracting all rules defining a functor/arity user should be allowed to +% change it's aggregator; Issue #61: can't retract wrong aggregator. + +> :- backchain f/1. +> f(X) = 1. + +> retract_rule 0 + +% now, make it's aggregator '+=' instead of '=' +> f(X) += 1. +> f(X) += 2. + +> query f(1) + +f(1) = 3. + +% will still be one rule defining f/1 +> retract_rule 1 + + +% FIXME, empty changes... +Changes +======= + + +% try to change to `:=` +> f(X) := 100. + +DynaCompilerError: +Encountered error in input program: + Conflicting aggregators; rule + f(X) := 100. + uses ':=' for f/1 but I had been lead to expect '+='. +Everything was syntactically valid, but we could not +see it through. +new rule(s) were not added to program.