return ''
if self.arity == 0:
[term] = rows
- return '%s => %s.' % (term, _repr(term.value))
+ return '%s = %s.' % (term, _repr(term.value))
p = [(_repr(term), _repr(term.value)) for term in sorted(rows)]
lines = [self.name, '='*len(self.name)] # heading
terms, values = zip(*p)
widths = map(len, terms)
- fmt = '%%-%ds => %%s.' % min(max(widths), 40)
+ fmt = '%%-%ds = %%s.' % min(max(widths), 40)
for term, value in zip(terms, values):
lines.append(fmt % (term, value))
lines.append('')
def dump_rules(self):
if not self.rules:
+ print 'No rules found.'
return
print
print 'Rules'
========
m/2
===
- m(0,0) => 1.0.
- m(0,1) => 2.0.
- m(0,2) => 3.0.
- m(1,0) => 4.0.
- m(1,1) => 5.0.
- m(3,0) => 6.0.
- m(3,1) => 7.0.
+ m(0,0) = 1.0.
+ m(0,1) = 2.0.
+ m(0,2) = 3.0.
+ m(1,0) = 4.0.
+ m(1,1) = 5.0.
+ m(3,0) = 6.0.
+ m(3,1) = 7.0.
As you can see, by default values are interpreted as floats, to specify a
========
m/2
===
- m(0,0) => "1".
- m(0,1) => "2".
- m(0,2) => "3".
- m(1,0) => "4".
- m(1,1) => "5".
- m(3,0) => "6".
- m(3,1) => "7".
+ m(0,0) = "1".
+ m(0,1) = "2".
+ m(0,2) = "3".
+ m(1,0) = "4".
+ m(1,1) = "5".
+ m(3,0) = "6".
+ m(3,1) = "7".
"""
========
trees/1
=======
- trees(0) => node("a", node("b", "c"), node("d", "e"))
- trees(1) => node("a", "b", "c")
+ trees(0) = node("a", node("b", "c"), node("d", "e"))
+ trees(1) = node("a", "b", "c")
"""
> sol
row/4
=====
- row(0,"0","S","NP VP") => true.
- row(1,"1.58","ROOT","S .") => true.
- row(2,"1.58","ROOT","S !") => true.
- row(3,"1.58","ROOT","VP !") => true.
- row(4,"3.81","VP","V") => true.
- row(5,"3.81","VP","V NP") => true.
- row(6,"1.49","VP","V VP") => true.
+ row(0,"0","S","NP VP") = true.
+ row(1,"1.58","ROOT","S .") = true.
+ row(2,"1.58","ROOT","S !") = true.
+ row(3,"1.58","ROOT","VP !") = true.
+ row(4,"3.81","VP","V") = true.
+ row(5,"3.81","VP","V NP") = true.
+ row(6,"1.49","VP","V VP") = true.
...
"""
import re
from utils import yellow, green, cyan, red, _repr, drepr
import debug, defn
-from cStringIO import StringIO
-from utils import lexer, subst
from draw_circuit import infer_edges
from collections import defaultdict
def dig(head, visited, tail, groups, interp):
if head in tail:
- return [yellow % head + ': ' + red % '*cycle*']
+ return ['%s = %s' % (yellow % head, head.value)] \
+ + ['|'] \
+ + branch([[red % 'continue as before (cyclic structure, will continue forever)']])
if head in visited:
- return [yellow % head + ': ' + red % 'shared structure see above']
+ return ['%s = %s' % (yellow % head, head.value)] \
+ + ['|'] \
+ + branch([[red % 'continue as before (shared structure)']])
if head not in groups:
return []
if block:
contribs.append(crux.format() + ['|'] + block)
else:
- contribs.append(crux.format())
+ contribs.append(crux.format() + [''])
- return ['%s => %s' % (yellow % head, cyan % _repr(head.value))] \
+ return ['%s = %s' % (yellow % head, cyan % _repr(head.value))] \
+ ['|'] \
+ branch(contribs) + ['']
"""
Retract rule from program by rule index.
- > a += 1.
- > b += 1.
- > c += a*b.
+ > a += 1.
+ > b += 1.
+ > c += a*b.
- > rules
+ In order to retract a rule we need to know it's index, for that we use
+ the command `rules`.
- Rules
- =====
- 0: a += 1.
- 1: b += 1.
- 2: c += a * b.
+ > rules
- > retract_rule 0
+ Rules
+ =====
+ 0: a += 1.
+ 1: b += 1.
+ 2: c += a * b.
+
+ Now let's remove a rule:
+
+ > retract_rule 0
This removes rule 0 from the program. Now, let's inspect the changes to
the solution.
- > sol
+ > sol
- Solution
- ========
- b => 1.
+ Solution
+ ========
+ b = 1.
"""
- self.interp.retract_rule(int(idx))
+
+ try:
+ idx = int(idx)
+ except ValueError:
+ print 'Please specify an integer. Type `help retract_rule` to read more.'
+ else:
+ if self.interp.retract_rule(idx) is None:
+ print 'List available by typing `rules`'
+ print
def do_exit(self, _):
"""
self.interp.new_rules = set()
try:
- query = "$out(%s) dict= %s." % (self.lineno, q)
+ query = "$query dict= %s." % q
self.default(query, show_changed=False)
try:
- [(_, _, results)] = self.interp.chart['$out/1'][self.lineno,:]
+ [(_, _, results)] = self.interp.chart['$query/0'][:,]
return results
except ValueError:
return []
finally:
+
# cleanup:
# retract newly added rules.
for r in self.interp.new_rules:
self.interp.retract_rule(r)
- # drop $out chart
- del self.interp.chart['$out/1']
+
+ try:
+ # drop $out chart
+ del self.interp.chart['$query/0']
+ except KeyError:
+ # query must have failed.
+ pass
+
+ self.interp.new_rules = set()
def do_vquery(self, q):
"""
- `vquery` shows variable bindings
> vquery f(X)
- 1 where {X=1}
- 4 where {X=1}
+ 1 where {X=1}
+ 4 where {X=1}
- `query` shows variable bindings applied to query
> query f(X)
- 1 =* f(1)
- 4 =* f(2)
+ f(1) = 1.
+ f(2) = 4.
- `trace` is an introspection tool for visualizing the derivation of an
item and its value. Type `help trace` for more information.
if len(results) == 0:
print 'No results.'
return
+ print
for term, result in sorted((subst(q, dict(result.variables)), result) for result in results):
- print ' ', _repr(result.value), '=*', term
+ print term, '=', _repr(result.value)
print
def default(self, line, show_changed=True):
except (DynaInitializerException, DynaCompilerError) as e:
print type(e).__name__ + ':'
print e
- print '> new rule(s) were not added to program.'
+ print 'new rule(s) were not added to program.'
print
else:
if show_changed:
return
print '============='
for x, v in sorted(changed.items()):
- print '%s => %s.' % (x, _repr(v))
+ print '%s = %s.' % (x, _repr(v))
# def _changed_subscriptions(self, changed):
#
========
data/3
======
- data(2,"cow","boy") => true.
+ data(2,"cow","boy") = true.
data/4
======
- data(0,"a","b","3.0") => true.
- data(1,"c","d","4.0") => true.
+ data(0,"a","b","3.0") = true.
+ data(1,"c","d","4.0") = true.
"""
try:
In our solution we see that `a` is true.
> sol
- a => true.
- b => true.
- c => true.
+ a = true.
+ b = true.
+ c = true.
Now we want to find out why
> trace a
- a => true
+ a = true
|
└─ :- true
a :- b=true.
|
- └─ b => true
+ └─ b = true
|
└─ :- true
b :- c=true.
|
- └─ c => true
+ └─ c = true
|
└─ |= true
> trace bar(10,10)
- bar(10,10) => 220
+ bar(10,10) = 220
|
├─ += 110
│
│ bar(A=10, B=10) += (foo(A=10)=11 * B=10)=110.
│ |
- │ └─ foo(10) => 11
+ │ └─ foo(10) = 11
│ |
│ └─ = 11
│
> trace a
- a => 2.0
+ a = 2.0
|
├─ += 1
│
# retract newly added rules.
for r in self.interp.new_rules:
self.interp.retract_rule(r)
- # drop $out chart
- del self.interp.chart['$trace/0']
+
+ try:
+ # drop $out chart
+ del self.interp.chart['$trace/0']
+ except KeyError:
+ # query must have failed.
+ pass
+
+ self.interp.new_rules = set()
do_load.__doc__ = do_load.__doc__.format(load=', '.join(load.available))
assert not stdout.strip(), [stdout, stderr]
# hide our temporary file's ugly sha1 file names from users.
ugly_file_name = dotdynadir + '[a-z0-9/.]+\.dyna\S*'
- stderr = re.sub(ugly_file_name, '', stderr)
+ stderr = re.sub(ugly_file_name, '<repl>', stderr)
raise DynaCompilerError(stderr)