updated doctests, caught some cases of missing clear error.
print '========'
for x in sorted(path('test').glob("*/*.dynadoc")):
+
+ if '/ptb.dynadoc' in x:
+ continue
+
+ if '/known-failures/' in x:
+ continue
+
print x,
sys.stdout.flush()
with file(x) as f:
return self.chart[fn].insert(args)
def delete(self, item, val, ruleix, variables):
+ self.clear_error(item)
self.emit(item, val, ruleix, variables, delete=True)
def emit(self, item, val, ruleix, variables, delete):
print 'Rule %s not found.' % idx
return
+ self.clear_error(rule)
+
# remove $rule
if hasattr(rule, 'item'):
self.delete(rule.item, true, ruleix=None, variables=None)
def dump_errors(self, out=None):
if out is None:
out = sys.stdout
- # We only dump the error chart if it's non empty.
- if not self.error and not self.uninitialized_rules:
- return
- print >> out
- print >> out, red % 'Errors'
- print >> out, red % '======'
# separate errors into aggregation errors and update handler errors
I = defaultdict(lambda: defaultdict(list))
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
E[h.rule][type(e)].append((item, val, e))
+ # We only dump the error chart if it's non empty.
+ if not I and not E and not self.uninitialized_rules:
+ return
+
+ print >> out
+ print >> out, red % 'Errors'
+ print >> out, red % '======'
+
# aggregation errors
for r in sorted(I, key=lambda r: r.index):
print >> out, 'Error(s) aggregating %s:' % r
# errors pertaining to rules
for r in sorted(E, key=lambda r: r.index):
- print >> out, 'Error(s) in rule:', r.span
+ print >> out, 'Error(s) in rule %s:' % r.index, r.span
print >> out
for line in r.src.split('\n'):
print >> out, ' ', line
"""
import re, os, cmd, readline
-from utils import ip, lexer, subst, drepr, _repr, get_module
+from utils import ip, lexer, subst, drepr, _repr, get_module, yellow
from stdlib import topython, todyna
from errors import DynaCompilerError
from config import dotdynadir
import load, post
+from interpreter import Rule
+from contextlib import contextmanager
+
+
class REPL(cmd.Cmd, object):
def __init__(self, interp, hist=dotdynadir / 'dyna.hist'):
except ValueError:
print 'Please specify an integer. Type `help retract_rule` to read more.'
else:
- changes = self.interp.retract_rule(idx)
- if changes is None:
- print 'List available by typing `rules`'
- print
- else:
- self._changed(changes)
+ with self.error_tracker():
+ changes = self.interp.retract_rule(idx)
+ if changes is None:
+ print 'List available by typing `rules`'
+ print
+ else:
+ self._changed(changes)
def do_exit(self, _):
"""
print 'new rule(s) were not added to program.'
print
else:
- new_rules = self.interp.load_plan(src)
- changed = self.interp.run_agenda()
- if show_changed:
- self._changed(changed)
+ with self.error_tracker():
+ new_rules = self.interp.load_plan(src)
+ changed = self.interp.run_agenda()
+ if show_changed:
+ self._changed(changed)
return (new_rules, changed)
+ @contextmanager
+ def error_tracker(self):
+ errors_before = self.interp.error.copy()
+ yield
+ if errors_before.items() != self.interp.error.items():
+ e = set(errors_before) | set(self.interp.error)
+ new_errors = 0
+ cleared_errors = 0
+ for k in e:
+ was = k in errors_before
+ now = k in self.interp.error
+ 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
+ new_errors += 1
+ if new_errors and cleared_errors:
+ print yellow % '>>>', '%s new errors, %s errors cleared. Type `sol` for details.\n' \
+ % (new_errors, cleared_errors)
+ elif new_errors:
+ print yellow % '>>>', '%s new errors. Type `sol` for details.\n' \
+ % (new_errors,)
+ elif cleared_errors:
+ print yellow % '>>>', '%s errors cleared.\n' \
+ % (cleared_errors,)
+
def _changed(self, changed):
if not changed:
return
f(2,1) = 1.
f(2,2) = 2.
+>>> 5 new errors. Type `sol` for details.
+
> sol
Solution
Error(s) aggregating d/0:
TypeError:
`d`: unsupported operand type(s) for *: 'NoneType' and 'int'
-Error(s) in rule: <repl>
+Error(s) in rule 1: <repl>
a += 1/b.
ZeroDivisionError:
when `b` = 0
division by zero
a += (1 / b=0)=?.
-Error(s) in rule: <repl>
+Error(s) in rule 2: <repl>
c += "" + b.
TypeError:
when `b` = 0
cannot concatenate 'str' and 'int' objects
c += ("" + b=0)=?.
-Error(s) in rule: <repl>
+Error(s) in rule 4: <repl>
b := e/0.
ZeroDivisionError:
when `e` = 0
division by zero
b := (e=0 / 0)=?.
-Error(s) in rule: <repl>
+Error(s) in rule 5: <repl>
a += e/0.
ZeroDivisionError:
when `e` = 0
> a += 1/d.
+>>> 1 new errors. Type `sol` for details.
+
> sol
Solution
b = 2.
d = 1.
+>>> 1 errors cleared.
+
% Looks good.
> sol
> a += 1 / d.
+>>> 1 new errors. Type `sol` for details.
+
> rules
Rules
=======
a = 1.0.
d = 1.
+
+>>> 1 errors cleared.
=======
e = $error.
+>>> 1 new errors. Type `sol` for details.
+
> sol
Solution
=======
e = null.
-
+>>> 1 errors cleared.
> a :- false.
b = $error.
c = "horse".
+>>> 1 new errors. Type `sol` for details.
+
> sol
b = true.
c = true.
+>>> 1 errors cleared.
> f(1,2). f(2,2).
a(2) = 2.
b = $error.
+>>> 1 new errors. Type `sol` for details.
+
+
> sol
Solution
=======
b = 0.
+>>> 1 errors cleared.
+
+
> a(1) := 2. a(2) := 2. b := 0. b := a(X).
Changes
=======
a = $error.
+>>> 1 new errors. Type `sol` for details.
+
> sol
Solution
=======
a = 2.
+>>> 1 errors cleared.
+
+
> sol
Solution
> x = cons(1, 2).
+>>> 1 new errors. Type `sol` for details.
+
> sol
Solution empty.
> retract_rule 0
+>>> 1 errors cleared.
+
> s set= Y for Y in [3,2,1,[2,1],&f(1)].
Changes
=======
a = $error.
+>>> 1 new errors. Type `sol` for details.
+
+
> b = a + 1.
+>>> 1 new errors. Type `sol` for details.
+
> rules
Rules
Errors
======
-Error(s) in rule: <repl>
+Error(s) in rule 0: <repl>
f(X) = f(X-1).
RuntimeError:
when `f(-323)` = null
=======
a = null.
+>>> 2 errors cleared.
+
> sol
Solution empty.
\ No newline at end of file