]> hydra-www.ietfng.org Git - dyna2/commitdiff
added `|=` and fixed `:-`.
authorTim Vieira <tim.f.vieira@gmail.com>
Tue, 23 Jul 2013 04:00:22 +0000 (00:00 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Tue, 23 Jul 2013 04:00:22 +0000 (00:00 -0400)
updated `test/repl/boolean-aggregators.dynadoc`

src/Dyna/Backend/Python/Backend.hs
src/Dyna/Backend/Python/aggregator.py
src/Dyna/Backend/Python/interpreter.py
src/Dyna/Backend/Python/repl.py
src/Dyna/Backend/Python/stdlib.py
test/repl/boolean-aggregators.dynadoc

index 752f0db44fe3f53503312a4805d1342c370cb429..44c1fd952b9a7dcafa49142a67e46a32b687f03b 100644 (file)
@@ -53,7 +53,7 @@ aggrs :: S.Set String
 aggrs = S.fromList
   [ "max=" , "min="
   , "+=" , "*="
-  , "&="
+  , "&=" , "|="
   , ":-"
   , "="
   , "majority=" , "mean="
index ecbbbdf4eb398bd2ad9eb9cf91f838e048af3e89..20b0b54da35524e7c114732f1b965510dd1ffcde 100644 (file)
@@ -5,6 +5,8 @@ from __future__ import division
 
 # TODO: aggregators might want a reference to the item they are associated with.
 
+# TODO: we should never have a negative multiplicity
+
 import operator
 from collections import Counter
 from utils import drepr, _repr, user_vars, isbool, true, false
@@ -144,7 +146,6 @@ class or_equals(BAggregator):
             for val in s:
                 if not isbool(val):
                     raise TypeError('%s is not Boolean.' % _repr(val))
-
             # TODO: can short circuit as soon as we get a true... but above we
             # check the types.. so we don't get the benefit.
             for val in s:
@@ -153,6 +154,19 @@ class or_equals(BAggregator):
             return false
 
 
+class colon_dash(BAggregator):
+    def fold(self):
+        s = [x for x, m in self.iteritems() if m > 0]
+        if len(s):
+            for val in s:
+                if val is not true:
+                    raise TypeError('%s is not true.' % _repr(val))
+            # TODO: can short circuit as soon as we get a true... but above we
+            # check the types.. so we don't get the benefit.
+            for val in s:
+                if val is true:
+                    return true
+
 
 class and_equals(BAggregator):
     def fold(self):
@@ -161,7 +175,6 @@ class and_equals(BAggregator):
             for val in s:
                 if not isbool(val):
                     raise TypeError('%s is not Boolean.' % _repr(val))
-
             # TODO: can short circuit as soon as we get a false. but above we
             # check the types.. so we don't get the benfit
             for val in s:
@@ -194,7 +207,8 @@ defs = {
     '+=': plus_equals,
     '*=': times_equals,
     '&=': and_equals,
-    ':-': or_equals,
+    ':-': colon_dash,
+    '|=': or_equals,
     'majority=': majority_equals,
     'set=': set_equals,
     'bag=': bag_equals,
index 374df71323e70bb491964aebdc1092126c783d73..098c44ef38d3658db916946cbf8334ee60e8f5dd 100644 (file)
@@ -196,7 +196,7 @@ class Interpreter(object):
             # compute item's new value
             now = item.aggregator.fold()
 
-        except (AggregatorError, ZeroDivisionError, TypeError, OverflowError) as e:
+        except (AggregatorError, ZeroDivisionError, ValueError, TypeError, OverflowError) as e:
             # handle error in aggregator
             now = Error()
             self.replace(item, now)
@@ -228,7 +228,7 @@ class Interpreter(object):
 
             try:
                 handler(item, val, emit=t_emit)
-            except (ZeroDivisionError, TypeError, RuntimeError, OverflowError) as e:
+            except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e:
                 e.exception_frame = rule_error_context()
                 e.traceback = traceback.format_exc()
                 error.append((e, handler))
@@ -266,7 +266,7 @@ class Interpreter(object):
         for handler in self._gbc[item.fn]:
             try:
                 handler(*args, emit=t_emit)
-            except (ZeroDivisionError, TypeError, RuntimeError, OverflowError) as e:
+            except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e:
                 e.exception_frame = rule_error_context()
                 e.traceback = traceback.format_exc()
                 errors.append((e, handler))
@@ -330,13 +330,20 @@ class Interpreter(object):
         # run to fixed point.
         if self.recompile:
             try:
-                plan = self.dynac_code('\n'.join(r.src for r in self.recompile))
+                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 is a little bit strange to ignore the error and
-                # simply print something. However, since the rules in the
-                # recompile list are syntactically valid (well, they at least
-                # were valid) -- this means that errors must be planning
-                # errors... probably all to do with missing BC declarations.
+                # TODO: it's a bit strange to ignore the error and simply print
+                # the error. 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.
+                #
+                # TODO: should probably at the very least report compiler errors
+                # in a similar fashion to initialization errors.
+                #
+                # TODO: we probably have to worry about infinite loops -- at the
+                # moment this results in an interpreter crash due to max
+                # recursion limit
                 print e
             else:
                 # TODO: reuse old rule index when we recompile.
@@ -363,7 +370,7 @@ class Interpreter(object):
                 self.clear_error(rule)  # clear errors on rule, if any
                 rule.init(emit=_emit)
 
-            except (ZeroDivisionError, TypeError, RuntimeError, OverflowError) as e:
+            except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError) as e:
                 e.exception_frame = rule_error_context()
                 e.traceback = traceback.format_exc()
                 self.set_error(rule, e)
@@ -499,7 +506,7 @@ class Interpreter(object):
                 # run initializer in delete mode
                 try:
                     rule.init(emit=self.delete)
-                except (ZeroDivisionError, TypeError, RuntimeError, OverflowError):
+                except (ZeroDivisionError, ValueError, TypeError, RuntimeError, OverflowError):
                     # TODO: what happens if there's an error?
                     pass
             else:
@@ -513,6 +520,15 @@ class Interpreter(object):
             # recompute memos and dependent memos
             self.recompute_gbc_memo(rule.head_fn)
 
+
+        # clear push-time errors pertaining to this rule
+        for item, x in self.error.items():
+            if isinstance(item, Rule):
+                continue
+            (_, es) = x
+            for e, h in es:
+                self.error[item] = [(e, h) for e, h in self.error[item] if h is not None and h.rule.index == rule.index]
+
         self.recompute_coarse()
 
         self._agenda()
@@ -623,11 +639,7 @@ class Interpreter(object):
                 if h is None:
                     I[item.fn][type(e)].append((item, val, e))
                 else:
-                    if h.rule.index not in self.rules:
-                        # TODO: clear all errors pertaining to a rule at
-                        # push-time. This is a temporary filter, which is fine
-                        # for now.
-                        continue
+                    assert h.rule.index in self.rules
                     E[h.rule][type(e)].append((item, val, e))
 
         # We only dump the error chart if it's non empty.
index e2bf78c783524ae6223319efa121690218ea4e6f..60cfde61b9c798a17cb596c9f22a11d771d045dd 100644 (file)
@@ -282,13 +282,19 @@ class REPL(cmd.Cmd, object):
             for k in e:
                 was = k in errors_before
                 now = k in self.interp.error
+
+                if k in self.interp.error:
+                    es = self.interp.error[k]
+                else:
+                    es = ''
+
                 if isinstance(k, Rule):
                     k = 'rule index %s' % k.index
                 if was and not now:
                     #print 'cleared error at `%s`.' % k
                     cleared_errors += 1
                 elif not was and now:
-                    #print 'new error at `%s`.' % k
+#                    print 'new error at `%s`.' % k, es
                     new_errors += 1
             if new_errors and cleared_errors:
                 print yellow % '>>>', '%s new errors, %s errors cleared. Type `sol` for details.\n' \
index 100a9f97e8e7ebdede399eb9468358e0349a3073..69d6ab9900e767c52d5ac11bbb9a774a1b63c83a 100644 (file)
@@ -6,6 +6,20 @@ from math import log, exp, sqrt
 from random import random as _random
 from glob import glob
 
+
+#def add(self, x):
+#    if islist(x):
+#        n = len(self.aslist)
+#        m = len(x.aslist)
+#        if n != m:
+#            raise ValueError("Can't add list of unequal lengths (%s and %s)" % (len(self.aslist), len(x.aslist)))
+#        else:
+#            return todyna([a+b for a,b in zip(self.aslist, x.aslist)])
+#    else:
+#        # try to add scalar
+#        return todyna([x+a for a in self.aslist])
+
+
 def or_(x, y):
     if not (isbool(x) and isbool(y)):
         raise TypeError('`|` expected Boolean arguments, got `%s` and `%s`' \
index 19eb59b524fbb2f9452c318564faf5caa5854946..4ad4c4393af849729d09161a35e131ec81da2523 100644 (file)
@@ -18,7 +18,7 @@ Errors
 ======
 Error(s) aggregating e/0:
   TypeError:
-    `e`: 10 is not Boolean.
+    `e`: 10 is not true.
 
 > retract_rule 0
 
@@ -28,14 +28,55 @@ e = null.
 
 >>> 1 errors cleared.
 
+> e :- false.
 
-> a :- false.
+Changes
+=======
+e = $error.
+
+>>> 1 new errors. Type `sol` for details.
+
+
+> e :- true.
+
+% didn't clear error because there is still a false aggregand.
+
+> rules
+
+Rules
+=====
+  1: e :- false.
+  2: e :- true.
+
+> retract_rule 1
+
+Changes
+=======
+e = true.
+>>> 1 errors cleared.
+
+> sol
+
+Solution
+========
+e.             % note the special case printing.
+
+
+> retract_rule 2
+
+Changes
+=======
+e = null.
+
+
+> a |= false.
 
 Changes
 =======
 a = false.
 
-> a :- true.
+
+> a |= true.
 
 Changes
 =======
@@ -58,7 +99,7 @@ c = "horse".
 
 Solution
 ========
-a.
+a = true.
 b = $error.
 c = "horse".
 
@@ -87,7 +128,7 @@ c = true.
 
 Solution
 ========
-a.
+a = true.
 b = true.
 c = true.