From: Tim Vieira Date: Tue, 23 Jul 2013 04:00:22 +0000 (-0400) Subject: added `|=` and fixed `:-`. X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=9a7d0d5b7cf7eb6bb0f27b22c58ed4c7c1565529;p=dyna2 added `|=` and fixed `:-`. updated `test/repl/boolean-aggregators.dynadoc` --- diff --git a/src/Dyna/Backend/Python/Backend.hs b/src/Dyna/Backend/Python/Backend.hs index 752f0db..44c1fd9 100644 --- a/src/Dyna/Backend/Python/Backend.hs +++ b/src/Dyna/Backend/Python/Backend.hs @@ -53,7 +53,7 @@ aggrs :: S.Set String aggrs = S.fromList [ "max=" , "min=" , "+=" , "*=" - , "&=" + , "&=" , "|=" , ":-" , "=" , "majority=" , "mean=" diff --git a/src/Dyna/Backend/Python/aggregator.py b/src/Dyna/Backend/Python/aggregator.py index ecbbbdf..20b0b54 100644 --- a/src/Dyna/Backend/Python/aggregator.py +++ b/src/Dyna/Backend/Python/aggregator.py @@ -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, diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 374df71..098c44e 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -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. diff --git a/src/Dyna/Backend/Python/repl.py b/src/Dyna/Backend/Python/repl.py index e2bf78c..60cfde6 100644 --- a/src/Dyna/Backend/Python/repl.py +++ b/src/Dyna/Backend/Python/repl.py @@ -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' \ diff --git a/src/Dyna/Backend/Python/stdlib.py b/src/Dyna/Backend/Python/stdlib.py index 100a9f9..69d6ab9 100644 --- a/src/Dyna/Backend/Python/stdlib.py +++ b/src/Dyna/Backend/Python/stdlib.py @@ -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`' \ diff --git a/test/repl/boolean-aggregators.dynadoc b/test/repl/boolean-aggregators.dynadoc index 19eb59b..4ad4c43 100644 --- a/test/repl/boolean-aggregators.dynadoc +++ b/test/repl/boolean-aggregators.dynadoc @@ -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.