]> hydra-www.ietfng.org Git - dyna2/commitdiff
After retracting all rules defining a functor/arity user is allowed to
authorTim Vieira <tim.f.vieira@gmail.com>
Tue, 23 Jul 2013 17:18:43 +0000 (13:18 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Tue, 23 Jul 2013 17:18:43 +0000 (13:18 -0400)
change aggregator; Issue #61: can't retract wrong aggregator.

src/Dyna/Backend/Python/interpreter.py
src/Dyna/Backend/Python/utils.py
test/repl/retract-aggregator.dyna [new file with mode: 0644]

index 098c44ef38d3658db916946cbf8334ee60e8f5dd..baf1b70950924033be36558307bb4047fef410d0 100644 (file)
@@ -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
 
index a7c9815978d956555a1be292459cffcc49350b6a..58a598e30f315f9e87337cf080f251007887504d 100644 (file)
@@ -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 (file)
index 0000000..a54e611
--- /dev/null
@@ -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.