Type checking, initial work.
This commit is contained in:
parent
705c95ee28
commit
eb739024eb
571
docs/Types.html
571
docs/Types.html
File diff suppressed because it is too large
Load Diff
1013
docs/Types.ipynb
1013
docs/Types.ipynb
File diff suppressed because it is too large
Load Diff
246
docs/Types.md
246
docs/Types.md
|
|
@ -127,7 +127,7 @@ The simplest way to "compile" this function would be something like:
|
|||
|
||||
```python
|
||||
def poswrd(s, e, d):
|
||||
return roll_down(*swap(*pop(s, e, d)))
|
||||
return rolldown(*swap(*pop(s, e, d)))
|
||||
```
|
||||
|
||||
However, internally this function would still be allocating tuples (stack cells) and doing other unnecesssary work.
|
||||
|
|
@ -829,9 +829,9 @@ We can use `compile_()` to generate many primitives in the library from their st
|
|||
```python
|
||||
def defs():
|
||||
|
||||
roll_down = (1, 2, 3), (2, 3, 1)
|
||||
rolldown = (1, 2, 3), (2, 3, 1)
|
||||
|
||||
roll_up = (1, 2, 3), (3, 1, 2)
|
||||
rollup = (1, 2, 3), (3, 1, 2)
|
||||
|
||||
pop = (1,), ()
|
||||
|
||||
|
|
@ -877,13 +877,13 @@ for name, stack_effect_comment in sorted(defs().items()):
|
|||
return (a1, stack)
|
||||
|
||||
|
||||
def roll_down(stack):
|
||||
def rolldown(stack):
|
||||
"""(1 2 3 -- 2 3 1)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a0, (a2, (a1, stack)))
|
||||
|
||||
|
||||
def roll_up(stack):
|
||||
def rollup(stack):
|
||||
"""(1 2 3 -- 3 1 2)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a1, (a0, (a2, stack)))
|
||||
|
|
@ -1218,9 +1218,9 @@ Rewrite the stack effect comments:
|
|||
```python
|
||||
def defs():
|
||||
|
||||
roll_down = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
rolldown = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
|
||||
roll_up = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
rollup = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
|
||||
pop = (A[1],), ()
|
||||
|
||||
|
|
@ -1295,8 +1295,8 @@ for name, stack_effect_comment in sorted(DEFS.items()):
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
|
|
@ -1331,7 +1331,7 @@ Revisit the `F` function, works fine.
|
|||
|
||||
|
||||
```python
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
F
|
||||
```
|
||||
|
||||
|
|
@ -1361,7 +1361,7 @@ def neato(*funcs):
|
|||
|
||||
```python
|
||||
# e.g. [swap] dip
|
||||
neato(roll_up, swap, roll_down)
|
||||
neato(rollup, swap, rolldown)
|
||||
```
|
||||
|
||||
(a0 a1 a2 -- a1 a0 a2)
|
||||
|
|
@ -1370,7 +1370,7 @@ neato(roll_up, swap, roll_down)
|
|||
|
||||
```python
|
||||
# e.g. [popop] dipd
|
||||
neato(popdd, roll_down, pop)
|
||||
neato(popdd, rolldown, pop)
|
||||
```
|
||||
|
||||
(a0 a1 a2 a3 -- a2 a3)
|
||||
|
|
@ -1379,7 +1379,7 @@ neato(popdd, roll_down, pop)
|
|||
|
||||
```python
|
||||
# Reverse the order of the top three items.
|
||||
neato(roll_up, swap)
|
||||
neato(rollup, swap)
|
||||
```
|
||||
|
||||
(a0 a1 a2 -- a2 a1 a0)
|
||||
|
|
@ -1461,8 +1461,8 @@ for name, stack_effect_comment in sorted(defs().items()):
|
|||
popdd = (a3 a2 a1 -- a2 a1)
|
||||
popop = (a2 a1 --)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
|
|
@ -1554,16 +1554,12 @@ NEW_DEFS = {
|
|||
name: (sequence_to_stack(i), sequence_to_stack(o))
|
||||
for name, (i, o) in DEFS.iteritems()
|
||||
}
|
||||
|
||||
NEW_DEFS['stack'] = S[0], (S[0], S[0])
|
||||
NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1])
|
||||
globals().update(NEW_DEFS)
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
stack = S[0], (S[0], S[0])
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
C(stack, uncons)
|
||||
```
|
||||
|
|
@ -1662,12 +1658,14 @@ for name, stack_effect_comment in sorted(NEW_DEFS.items()):
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
stack = (... -- ... [...])
|
||||
succ = (n1 -- n2)
|
||||
swaack = ([.1.] -- [.0.])
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
swons = ([.0.] a0 -- [a0 .0.])
|
||||
third = ([a0 a1 a2 .0.] -- a2)
|
||||
|
|
@ -2268,14 +2266,167 @@ Obviously it would be:
|
|||
|
||||
Without any information about the contents of the quote we can't say much about the result.
|
||||
|
||||
I think there's a way forward. If we convert our list of terms we are composing into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly. We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack. For combinators like `branch` that can have more than one stack effect we have to "split universes" again and return both. (Note: bug! If one branch doesn't type check the currect code ignores it, so you can think things are okay but have a type error waiting in the faled branch, I think... D'oh! FIXME!!!)
|
||||
I think there's a way forward. If we convert our list of terms we are composing into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly. We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack. For combinators like `branch` that can have more than one stack effect we have to "split universes" again and return both.
|
||||
|
||||
|
||||
```python
|
||||
stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
|
||||
class FunctionJoyType(AnyJoyType):
|
||||
|
||||
def __init__(self, name, sec, number):
|
||||
self.name = name
|
||||
self.stack_effects = sec
|
||||
self.number = number
|
||||
|
||||
def __add__(self, other):
|
||||
return self
|
||||
__radd__ = __add__
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SymbolJoyType(FunctionJoyType): prefix = 'F'
|
||||
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
def flatten(g):
|
||||
return list(chain.from_iterable(g))
|
||||
|
||||
|
||||
ID = S[0], S[0] # Identity function.
|
||||
|
||||
|
||||
def infer(e, F=ID):
|
||||
if not e:
|
||||
return [F]
|
||||
|
||||
n, e = e
|
||||
|
||||
if isinstance(n, SymbolJoyType):
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
|
||||
|
||||
elif isinstance(n, CombinatorJoyType):
|
||||
res = []
|
||||
for combinator in n.stack_effects:
|
||||
fi, fo = F
|
||||
new_fo, ee, _ = combinator(fo, e, {})
|
||||
ee = update(FUNCTIONS, ee) # Fix Symbols.
|
||||
new_F = fi, new_fo
|
||||
res.extend(infer(ee, new_F))
|
||||
else:
|
||||
lit = s9, (n, s9)
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
|
||||
i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
|
||||
n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
|
||||
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
import joy.library
|
||||
|
||||
FNs = '''ccons cons divmod_ dup dupd first
|
||||
over pm pop popd popdd popop pred
|
||||
rest rolldown rollup rrest second
|
||||
sqrt stack succ swaack swap swons
|
||||
third tuck uncons'''
|
||||
|
||||
FUNCTIONS = {
|
||||
name: SymbolJoyType(name, [NEW_DEFS[name]], i)
|
||||
for i, name in enumerate(FNs.strip().split())
|
||||
}
|
||||
FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
|
||||
FUNCTIONS['mul'] = SymbolJoyType('mul', [
|
||||
((i2, (i1, s0)), (i3, s0)),
|
||||
((f2, (i1, s0)), (f3, s0)),
|
||||
((i2, (f1, s0)), (f3, s0)),
|
||||
((f2, (f1, s0)), (f3, s0)),
|
||||
], 101)
|
||||
FUNCTIONS.update({
|
||||
combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
|
||||
for i, combo in enumerate((
|
||||
joy.library.i,
|
||||
joy.library.dip,
|
||||
joy.library.dipd,
|
||||
joy.library.dipdd,
|
||||
joy.library.dupdip,
|
||||
joy.library.b,
|
||||
joy.library.x,
|
||||
joy.library.infra,
|
||||
))
|
||||
})
|
||||
|
||||
def branch_true(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(then, expression), dictionary
|
||||
|
||||
def branch_false(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(else_, expression), dictionary
|
||||
|
||||
FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
globals().update(FUNCTIONS)
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
from itertools import chain
|
||||
from joy.utils.stack import list_to_stack as l2s
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
expression
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
|
||||
|
||||
|
||||
|
||||
|
||||
```python
|
||||
expression = l2s([n1, n2, mul])
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
infer(expression)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
[]
|
||||
|
||||
|
||||
|
||||
|
||||
```python
|
||||
class SymbolJoyType(AnyJoyType):
|
||||
prefix = 'F'
|
||||
|
|
@ -2345,7 +2496,7 @@ For this to work the type label classes have to be modified to let `T >= t` succ
|
|||
|
||||
|
||||
```python
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
|
||||
print doc_from_stack_effect(*F)
|
||||
```
|
||||
|
|
@ -2353,22 +2504,22 @@ print doc_from_stack_effect(*F)
|
|||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
ValueError Traceback (most recent call last)
|
||||
TypeError Traceback (most recent call last)
|
||||
|
||||
<ipython-input-112-4b4cb6ff86e5> in <module>()
|
||||
1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
<ipython-input-119-7fde90b4e88f> in <module>()
|
||||
1 F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
2
|
||||
----> 3 print doc_from_stack_effect(*F)
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2376,14 +2527,14 @@ print doc_from_stack_effect(*F)
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2391,14 +2542,14 @@ print doc_from_stack_effect(*F)
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2406,14 +2557,14 @@ print doc_from_stack_effect(*F)
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2421,14 +2572,14 @@ print doc_from_stack_effect(*F)
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2436,7 +2587,22 @@ print doc_from_stack_effect(*F)
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
ValueError: need more than 1 value to unpack
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
4 if not s:
|
||||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
TypeError: 'SymbolJoyType' object is not iterable
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
243
docs/Types.rst
243
docs/Types.rst
|
|
@ -211,7 +211,7 @@ The simplest way to "compile" this function would be something like:
|
|||
.. code:: ipython2
|
||||
|
||||
def poswrd(s, e, d):
|
||||
return roll_down(*swap(*pop(s, e, d)))
|
||||
return rolldown(*swap(*pop(s, e, d)))
|
||||
|
||||
However, internally this function would still be allocating tuples
|
||||
(stack cells) and doing other unnecesssary work.
|
||||
|
|
@ -1045,9 +1045,9 @@ from their stack effect comments:
|
|||
|
||||
def defs():
|
||||
|
||||
roll_down = (1, 2, 3), (2, 3, 1)
|
||||
rolldown = (1, 2, 3), (2, 3, 1)
|
||||
|
||||
roll_up = (1, 2, 3), (3, 1, 2)
|
||||
rollup = (1, 2, 3), (3, 1, 2)
|
||||
|
||||
pop = (1,), ()
|
||||
|
||||
|
|
@ -1094,13 +1094,13 @@ from their stack effect comments:
|
|||
return (a1, stack)
|
||||
|
||||
|
||||
def roll_down(stack):
|
||||
def rolldown(stack):
|
||||
"""(1 2 3 -- 2 3 1)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a0, (a2, (a1, stack)))
|
||||
|
||||
|
||||
def roll_up(stack):
|
||||
def rollup(stack):
|
||||
"""(1 2 3 -- 3 1 2)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a1, (a0, (a2, stack)))
|
||||
|
|
@ -1482,9 +1482,9 @@ Rewrite the stack effect comments:
|
|||
|
||||
def defs():
|
||||
|
||||
roll_down = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
rolldown = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
|
||||
roll_up = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
rollup = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
|
||||
pop = (A[1],), ()
|
||||
|
||||
|
|
@ -1559,8 +1559,8 @@ Rewrite the stack effect comments:
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
|
|
@ -1596,7 +1596,7 @@ Revisit the ``F`` function, works fine.
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
F
|
||||
|
||||
|
||||
|
|
@ -1629,7 +1629,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# e.g. [swap] dip
|
||||
neato(roll_up, swap, roll_down)
|
||||
neato(rollup, swap, rolldown)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1640,7 +1640,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# e.g. [popop] dipd
|
||||
neato(popdd, roll_down, pop)
|
||||
neato(popdd, rolldown, pop)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1651,7 +1651,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# Reverse the order of the top three items.
|
||||
neato(roll_up, swap)
|
||||
neato(rollup, swap)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1753,8 +1753,8 @@ comments. We can write a function to check that:
|
|||
popdd = (a3 a2 a1 -- a2 a1)
|
||||
popop = (a2 a1 --)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
|
|
@ -1873,13 +1873,10 @@ conversion function instead. This is programmer's laziness.
|
|||
name: (sequence_to_stack(i), sequence_to_stack(o))
|
||||
for name, (i, o) in DEFS.iteritems()
|
||||
}
|
||||
|
||||
NEW_DEFS['stack'] = S[0], (S[0], S[0])
|
||||
NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1])
|
||||
globals().update(NEW_DEFS)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
stack = S[0], (S[0], S[0])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
C(stack, uncons)
|
||||
|
|
@ -1984,12 +1981,14 @@ Clunky junk, but it will suffice for now.
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
stack = (... -- ... [...])
|
||||
succ = (n1 -- n2)
|
||||
swaack = ([.1.] -- [.0.])
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
swons = ([.0.] a0 -- [a0 .0.])
|
||||
third = ([a0 a1 a2 .0.] -- a2)
|
||||
|
|
@ -2686,14 +2685,159 @@ as a Joy interpreter stack, and just execute combinators directly. We
|
|||
can hybridize the compostition function with an interpreter to evaluate
|
||||
combinators, compose non-combinator functions, and put type variables on
|
||||
the stack. For combinators like ``branch`` that can have more than one
|
||||
stack effect we have to "split universes" again and return both. (Note:
|
||||
bug! If one branch doesn't type check the currect code ignores it, so
|
||||
you can think things are okay but have a type error waiting in the faled
|
||||
branch, I think... D'oh! FIXME!!!)
|
||||
stack effect we have to "split universes" again and return both.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
|
||||
class FunctionJoyType(AnyJoyType):
|
||||
|
||||
def __init__(self, name, sec, number):
|
||||
self.name = name
|
||||
self.stack_effects = sec
|
||||
self.number = number
|
||||
|
||||
def __add__(self, other):
|
||||
return self
|
||||
__radd__ = __add__
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SymbolJoyType(FunctionJoyType): prefix = 'F'
|
||||
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
|
||||
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def flatten(g):
|
||||
return list(chain.from_iterable(g))
|
||||
|
||||
|
||||
ID = S[0], S[0] # Identity function.
|
||||
|
||||
|
||||
def infer(e, F=ID):
|
||||
if not e:
|
||||
return [F]
|
||||
|
||||
n, e = e
|
||||
|
||||
if isinstance(n, SymbolJoyType):
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
|
||||
|
||||
elif isinstance(n, CombinatorJoyType):
|
||||
res = []
|
||||
for combinator in n.stack_effects:
|
||||
fi, fo = F
|
||||
new_fo, ee, _ = combinator(fo, e, {})
|
||||
ee = update(FUNCTIONS, ee) # Fix Symbols.
|
||||
new_F = fi, new_fo
|
||||
res.extend(infer(ee, new_F))
|
||||
else:
|
||||
lit = s9, (n, s9)
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
|
||||
i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
|
||||
n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
|
||||
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
import joy.library
|
||||
|
||||
FNs = '''ccons cons divmod_ dup dupd first
|
||||
over pm pop popd popdd popop pred
|
||||
rest rolldown rollup rrest second
|
||||
sqrt stack succ swaack swap swons
|
||||
third tuck uncons'''
|
||||
|
||||
FUNCTIONS = {
|
||||
name: SymbolJoyType(name, [NEW_DEFS[name]], i)
|
||||
for i, name in enumerate(FNs.strip().split())
|
||||
}
|
||||
FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
|
||||
FUNCTIONS['mul'] = SymbolJoyType('mul', [
|
||||
((i2, (i1, s0)), (i3, s0)),
|
||||
((f2, (i1, s0)), (f3, s0)),
|
||||
((i2, (f1, s0)), (f3, s0)),
|
||||
((f2, (f1, s0)), (f3, s0)),
|
||||
], 101)
|
||||
FUNCTIONS.update({
|
||||
combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
|
||||
for i, combo in enumerate((
|
||||
joy.library.i,
|
||||
joy.library.dip,
|
||||
joy.library.dipd,
|
||||
joy.library.dipdd,
|
||||
joy.library.dupdip,
|
||||
joy.library.b,
|
||||
joy.library.x,
|
||||
joy.library.infra,
|
||||
))
|
||||
})
|
||||
|
||||
def branch_true(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(then, expression), dictionary
|
||||
|
||||
def branch_false(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(else_, expression), dictionary
|
||||
|
||||
FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
globals().update(FUNCTIONS)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from itertools import chain
|
||||
from joy.utils.stack import list_to_stack as l2s
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression = l2s([n1, n2, mul])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
infer(expression)
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[]
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
|
|
@ -2770,7 +2914,7 @@ For this to work the type label classes have to be modified to let
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
|
||||
print doc_from_stack_effect(*F)
|
||||
|
||||
|
|
@ -2780,22 +2924,22 @@ For this to work the type label classes have to be modified to let
|
|||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
ValueError Traceback (most recent call last)
|
||||
TypeError Traceback (most recent call last)
|
||||
|
||||
<ipython-input-112-4b4cb6ff86e5> in <module>()
|
||||
1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
<ipython-input-119-7fde90b4e88f> in <module>()
|
||||
1 F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
2
|
||||
----> 3 print doc_from_stack_effect(*F)
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2803,14 +2947,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2818,14 +2962,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2833,14 +2977,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2848,14 +2992,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2863,7 +3007,22 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
ValueError: need more than 1 value to unpack
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
4 if not s:
|
||||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
TypeError: 'SymbolJoyType' object is not iterable
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -211,7 +211,7 @@ The simplest way to "compile" this function would be something like:
|
|||
.. code:: ipython2
|
||||
|
||||
def poswrd(s, e, d):
|
||||
return roll_down(*swap(*pop(s, e, d)))
|
||||
return rolldown(*swap(*pop(s, e, d)))
|
||||
|
||||
However, internally this function would still be allocating tuples
|
||||
(stack cells) and doing other unnecesssary work.
|
||||
|
|
@ -1045,9 +1045,9 @@ from their stack effect comments:
|
|||
|
||||
def defs():
|
||||
|
||||
roll_down = (1, 2, 3), (2, 3, 1)
|
||||
rolldown = (1, 2, 3), (2, 3, 1)
|
||||
|
||||
roll_up = (1, 2, 3), (3, 1, 2)
|
||||
rollup = (1, 2, 3), (3, 1, 2)
|
||||
|
||||
pop = (1,), ()
|
||||
|
||||
|
|
@ -1094,13 +1094,13 @@ from their stack effect comments:
|
|||
return (a1, stack)
|
||||
|
||||
|
||||
def roll_down(stack):
|
||||
def rolldown(stack):
|
||||
"""(1 2 3 -- 2 3 1)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a0, (a2, (a1, stack)))
|
||||
|
||||
|
||||
def roll_up(stack):
|
||||
def rollup(stack):
|
||||
"""(1 2 3 -- 3 1 2)"""
|
||||
(a2, (a1, (a0, stack))) = stack
|
||||
return (a1, (a0, (a2, stack)))
|
||||
|
|
@ -1482,9 +1482,9 @@ Rewrite the stack effect comments:
|
|||
|
||||
def defs():
|
||||
|
||||
roll_down = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
rolldown = (A[1], A[2], A[3]), (A[2], A[3], A[1])
|
||||
|
||||
roll_up = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
rollup = (A[1], A[2], A[3]), (A[3], A[1], A[2])
|
||||
|
||||
pop = (A[1],), ()
|
||||
|
||||
|
|
@ -1559,8 +1559,8 @@ Rewrite the stack effect comments:
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
|
|
@ -1596,7 +1596,7 @@ Revisit the ``F`` function, works fine.
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
F
|
||||
|
||||
|
||||
|
|
@ -1629,7 +1629,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# e.g. [swap] dip
|
||||
neato(roll_up, swap, roll_down)
|
||||
neato(rollup, swap, rolldown)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1640,7 +1640,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# e.g. [popop] dipd
|
||||
neato(popdd, roll_down, pop)
|
||||
neato(popdd, rolldown, pop)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1651,7 +1651,7 @@ also get the effect of combinators in some limited cases.
|
|||
.. code:: ipython2
|
||||
|
||||
# Reverse the order of the top three items.
|
||||
neato(roll_up, swap)
|
||||
neato(rollup, swap)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
|
@ -1753,8 +1753,8 @@ comments. We can write a function to check that:
|
|||
popdd = (a3 a2 a1 -- a2 a1)
|
||||
popop = (a2 a1 --)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
|
|
@ -1873,13 +1873,10 @@ conversion function instead. This is programmer's laziness.
|
|||
name: (sequence_to_stack(i), sequence_to_stack(o))
|
||||
for name, (i, o) in DEFS.iteritems()
|
||||
}
|
||||
|
||||
NEW_DEFS['stack'] = S[0], (S[0], S[0])
|
||||
NEW_DEFS['swaack'] = (S[1], S[0]), (S[0], S[1])
|
||||
globals().update(NEW_DEFS)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
stack = S[0], (S[0], S[0])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
C(stack, uncons)
|
||||
|
|
@ -1984,12 +1981,14 @@ Clunky junk, but it will suffice for now.
|
|||
popop = (a2 a1 --)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 .1.] -- [.1.])
|
||||
roll_down = (a1 a2 a3 -- a2 a3 a1)
|
||||
roll_up = (a1 a2 a3 -- a3 a1 a2)
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1)
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2)
|
||||
rrest = ([a0 a1 .0.] -- [.0.])
|
||||
second = ([a0 a1 .0.] -- a1)
|
||||
sqrt = (n0 -- n1)
|
||||
stack = (... -- ... [...])
|
||||
succ = (n1 -- n2)
|
||||
swaack = ([.1.] -- [.0.])
|
||||
swap = (a1 a2 -- a2 a1)
|
||||
swons = ([.0.] a0 -- [a0 .0.])
|
||||
third = ([a0 a1 a2 .0.] -- a2)
|
||||
|
|
@ -2686,14 +2685,159 @@ as a Joy interpreter stack, and just execute combinators directly. We
|
|||
can hybridize the compostition function with an interpreter to evaluate
|
||||
combinators, compose non-combinator functions, and put type variables on
|
||||
the stack. For combinators like ``branch`` that can have more than one
|
||||
stack effect we have to "split universes" again and return both. (Note:
|
||||
bug! If one branch doesn't type check the currect code ignores it, so
|
||||
you can think things are okay but have a type error waiting in the faled
|
||||
branch, I think... D'oh! FIXME!!!)
|
||||
stack effect we have to "split universes" again and return both.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
|
||||
class FunctionJoyType(AnyJoyType):
|
||||
|
||||
def __init__(self, name, sec, number):
|
||||
self.name = name
|
||||
self.stack_effects = sec
|
||||
self.number = number
|
||||
|
||||
def __add__(self, other):
|
||||
return self
|
||||
__radd__ = __add__
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SymbolJoyType(FunctionJoyType): prefix = 'F'
|
||||
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
|
||||
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def flatten(g):
|
||||
return list(chain.from_iterable(g))
|
||||
|
||||
|
||||
ID = S[0], S[0] # Identity function.
|
||||
|
||||
|
||||
def infer(e, F=ID):
|
||||
if not e:
|
||||
return [F]
|
||||
|
||||
n, e = e
|
||||
|
||||
if isinstance(n, SymbolJoyType):
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
|
||||
|
||||
elif isinstance(n, CombinatorJoyType):
|
||||
res = []
|
||||
for combinator in n.stack_effects:
|
||||
fi, fo = F
|
||||
new_fo, ee, _ = combinator(fo, e, {})
|
||||
ee = update(FUNCTIONS, ee) # Fix Symbols.
|
||||
new_F = fi, new_fo
|
||||
res.extend(infer(ee, new_F))
|
||||
else:
|
||||
lit = s9, (n, s9)
|
||||
res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
|
||||
i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
|
||||
n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
|
||||
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
import joy.library
|
||||
|
||||
FNs = '''ccons cons divmod_ dup dupd first
|
||||
over pm pop popd popdd popop pred
|
||||
rest rolldown rollup rrest second
|
||||
sqrt stack succ swaack swap swons
|
||||
third tuck uncons'''
|
||||
|
||||
FUNCTIONS = {
|
||||
name: SymbolJoyType(name, [NEW_DEFS[name]], i)
|
||||
for i, name in enumerate(FNs.strip().split())
|
||||
}
|
||||
FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
|
||||
FUNCTIONS['mul'] = SymbolJoyType('mul', [
|
||||
((i2, (i1, s0)), (i3, s0)),
|
||||
((f2, (i1, s0)), (f3, s0)),
|
||||
((i2, (f1, s0)), (f3, s0)),
|
||||
((f2, (f1, s0)), (f3, s0)),
|
||||
], 101)
|
||||
FUNCTIONS.update({
|
||||
combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
|
||||
for i, combo in enumerate((
|
||||
joy.library.i,
|
||||
joy.library.dip,
|
||||
joy.library.dipd,
|
||||
joy.library.dipdd,
|
||||
joy.library.dupdip,
|
||||
joy.library.b,
|
||||
joy.library.x,
|
||||
joy.library.infra,
|
||||
))
|
||||
})
|
||||
|
||||
def branch_true(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(then, expression), dictionary
|
||||
|
||||
def branch_false(stack, expression, dictionary):
|
||||
(then, (else_, (flag, stack))) = stack
|
||||
return stack, CONCAT(else_, expression), dictionary
|
||||
|
||||
FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
globals().update(FUNCTIONS)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from itertools import chain
|
||||
from joy.utils.stack import list_to_stack as l2s
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
expression = l2s([n1, n2, mul])
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
infer(expression)
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[]
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
|
|
@ -2770,7 +2914,7 @@ For this to work the type label classes have to be modified to let
|
|||
|
||||
.. code:: ipython2
|
||||
|
||||
F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
|
||||
print doc_from_stack_effect(*F)
|
||||
|
||||
|
|
@ -2780,22 +2924,22 @@ For this to work the type label classes have to be modified to let
|
|||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
ValueError Traceback (most recent call last)
|
||||
TypeError Traceback (most recent call last)
|
||||
|
||||
<ipython-input-112-4b4cb6ff86e5> in <module>()
|
||||
1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
|
||||
<ipython-input-119-7fde90b4e88f> in <module>()
|
||||
1 F = reduce(C, (pop, swap, rolldown, rest, rest, cons, cons))
|
||||
2
|
||||
----> 3 print doc_from_stack_effect(*F)
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2803,14 +2947,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2818,14 +2962,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2833,14 +2977,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2848,14 +2992,14 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
<ipython-input-99-ddee30dbb1a6> in C(f, g)
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
|
|
@ -2863,7 +3007,22 @@ For this to work the type label classes have to be modified to let
|
|||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
ValueError: need more than 1 value to unpack
|
||||
<ipython-input-98-ddee30dbb1a6> in C(f, g)
|
||||
10 def C(f, g):
|
||||
11 f, g = relabel(f, g)
|
||||
---> 12 for fg in compose(f, g):
|
||||
13 yield delabel(fg)
|
||||
|
||||
|
||||
<ipython-input-97-5eb7ac5ad2c2> in compose(f, g)
|
||||
1 def compose(f, g):
|
||||
----> 2 (f_in, f_out), (g_in, g_out) = f, g
|
||||
3 s = unify(g_in, f_out)
|
||||
4 if not s:
|
||||
5 raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
|
||||
|
||||
|
||||
TypeError: 'SymbolJoyType' object is not iterable
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Multiple Stack Effects
|
||||
|
||||
By adjusting the machinery in types.py to handles lists of stackeffect comments
|
||||
By adjusting the machinery in types.py to handles lists of stack effect comments
|
||||
we can capture more information about the type signatures of some functions,
|
||||
and we can introduce a kind of Kleene Star or sequence type that can stand for
|
||||
an unbounded sequence of other types.
|
||||
|
|
@ -13,6 +13,7 @@ from itertools import chain, product
|
|||
import sys
|
||||
sys.path.append('/home/sforman/Desktop/Joypy-hg')
|
||||
import joy.library
|
||||
from joy.parser import Symbol
|
||||
from joy.utils.stack import concat as CONCAT
|
||||
from joy.utils.types import (
|
||||
AnyJoyType, A,
|
||||
|
|
@ -125,12 +126,11 @@ def unify(u, v, s=None):
|
|||
return _lil_uni(u, v, s)
|
||||
|
||||
if isinstance(u, tuple) and isinstance(v, tuple):
|
||||
if len(u) != len(v) != 2:
|
||||
raise JoyTypeError(repr((u, v)))
|
||||
if len(u) != 2 or len(v) != 2:
|
||||
raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
|
||||
|
||||
a, b = v
|
||||
(a, b), (c, d) = v, u
|
||||
if isinstance(a, KleeneStar):
|
||||
c, d = u
|
||||
if isinstance(c, KleeneStar):
|
||||
s = _lil_uni(a, c, s) # Attempt to unify the two K-stars.
|
||||
return unify(d, b, s[0])
|
||||
|
|
@ -147,20 +147,13 @@ def unify(u, v, s=None):
|
|||
sn.update(s)
|
||||
return t
|
||||
|
||||
a, b = u
|
||||
if isinstance(a, KleeneStar):
|
||||
s0 = unify(v, b)
|
||||
s1 = unify(v, (a.another(), u))
|
||||
t = s0 + s1
|
||||
if isinstance(c, KleeneStar):
|
||||
t = unify(v, d) + unify(v, (c.another(), u))
|
||||
for sn in t:
|
||||
sn.update(s)
|
||||
sn.update(s)
|
||||
return t
|
||||
|
||||
ses = unify(u[0], v[0], s)
|
||||
results = ()
|
||||
for sn in ses:
|
||||
results += unify(u[1], v[1], sn)
|
||||
return results
|
||||
return tuple(flatten(unify(d, b, sn) for sn in unify(c, a, s)))
|
||||
|
||||
if isinstance(v, tuple):
|
||||
if not stacky(u):
|
||||
|
|
@ -174,7 +167,7 @@ def unify(u, v, s=None):
|
|||
s[v] = u
|
||||
return s,
|
||||
|
||||
return ()
|
||||
return _lil_uni(u, v, s)
|
||||
|
||||
|
||||
def _lil_uni(u, v, s):
|
||||
|
|
@ -214,7 +207,8 @@ def MC(F, G):
|
|||
return res
|
||||
|
||||
|
||||
flatten = lambda g: list(chain.from_iterable(g))
|
||||
def flatten(g):
|
||||
return list(chain.from_iterable(g))
|
||||
|
||||
|
||||
ID = S[0], S[0] # Identity function.
|
||||
|
|
@ -256,25 +250,23 @@ Ns = map(NumberStarJoyType, _R)
|
|||
Ss = map(StackStarJoyType, _R)
|
||||
|
||||
|
||||
mul = [
|
||||
((i2, (i1, s0)), (i3, s0)),
|
||||
((f2, (i1, s0)), (f3, s0)),
|
||||
((i2, (f1, s0)), (f3, s0)),
|
||||
((f2, (f1, s0)), (f3, s0)),
|
||||
]
|
||||
|
||||
|
||||
FUNCTIONS = {
|
||||
name: SymbolJoyType(name, [DEFS[name]], i)
|
||||
for i, name in enumerate('''
|
||||
ccons cons divmod_ dup dupd first
|
||||
mul over pm pop popd popdd popop
|
||||
pred rest rolldown rollup rrest
|
||||
second sqrt succ swap swons third
|
||||
tuck uncons stack swaack
|
||||
over pm pop popd popdd popop pred
|
||||
rest rolldown rollup rrest second
|
||||
sqrt stack succ swaack swap swons
|
||||
third tuck uncons
|
||||
'''.strip().split())
|
||||
}
|
||||
FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
|
||||
FUNCTIONS['mul'] = SymbolJoyType('mul', [
|
||||
((i2, (i1, s0)), (i3, s0)),
|
||||
((f2, (i1, s0)), (f3, s0)),
|
||||
((i2, (f1, s0)), (f3, s0)),
|
||||
((f2, (f1, s0)), (f3, s0)),
|
||||
], 101)
|
||||
FUNCTIONS.update({
|
||||
combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
|
||||
for i, combo in enumerate((
|
||||
|
|
@ -300,6 +292,52 @@ def branch_false(stack, expression, dictionary):
|
|||
FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
|
||||
|
||||
|
||||
globals().update(FUNCTIONS)
|
||||
|
||||
def _ge(self, other):
|
||||
return (issubclass(other.__class__, self.__class__)
|
||||
or hasattr(self, 'accept')
|
||||
and isinstance(other, self.accept))
|
||||
|
||||
AnyJoyType.__ge__ = _ge
|
||||
AnyJoyType.accept = tuple, int, float, long, str, unicode, bool, Symbol
|
||||
StackJoyType.accept = tuple
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
from joy.parser import text_to_expression
|
||||
from joy.utils.stack import list_to_stack as l2s
|
||||
|
||||
|
||||
F = infer(l2s((pop, pop, pop)))
|
||||
for f in F:
|
||||
print doc_from_stack_effect(*f)
|
||||
s = text_to_expression('0 1 2')
|
||||
L = unify(s, F[0][0])
|
||||
print L
|
||||
|
||||
print
|
||||
|
||||
F = infer(l2s((pop, swap, rolldown, rest, rest, cons, cons)))
|
||||
for f in F:
|
||||
print doc_from_stack_effect(*f)
|
||||
s = text_to_expression('0 1 2 [3 4]')
|
||||
L = unify(s, F[0][0])
|
||||
print L
|
||||
print
|
||||
|
||||
g = update(L[0], F[0])
|
||||
print doc_from_stack_effect(*g)
|
||||
print g
|
||||
|
||||
|
||||
print '- - - - - -'
|
||||
s = text_to_expression('[3 4]')
|
||||
L = unify(s, F[0][1])
|
||||
print L
|
||||
print
|
||||
|
||||
g = update(L[0], F[0])
|
||||
print doc_from_stack_effect(*g)
|
||||
print g
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ def _f(term, switch):
|
|||
while term and isinstance(term, tuple):
|
||||
item, term = term
|
||||
a.append(item)
|
||||
assert isinstance(term, StackJoyType), repr(term)
|
||||
assert isinstance(term, (tuple, StackJoyType)), repr(term)
|
||||
a = [_to_str(i, term, switch) for i in a]
|
||||
return a
|
||||
|
||||
|
|
@ -206,10 +206,11 @@ def _to_str(term, stack, switch):
|
|||
while term and isinstance(term, tuple):
|
||||
item, term = term
|
||||
a.append(_to_str(item, stack, switch))
|
||||
assert isinstance(term, StackJoyType), repr(term)
|
||||
assert isinstance(term, (tuple, StackJoyType)), repr(term)
|
||||
if term == stack:
|
||||
switch[0] = True
|
||||
end = '...'
|
||||
end = '' if term == () else '...'
|
||||
#end = '...'
|
||||
else:
|
||||
end = '...%i' % term.number
|
||||
a.append(end)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class TestMixin(object):
|
|||
self.assert_(a >= b)
|
||||
self.assert_(b >= a)
|
||||
# Check type variables match expected pattern.
|
||||
self._compare_structures(a, b)
|
||||
self._compare_structures(b, a)
|
||||
|
||||
def _compare_structures(self, a, b, seen=None):
|
||||
# Sometimes we change ONLY the "number" attr of our type vars.
|
||||
|
|
@ -33,12 +33,12 @@ class TestMixin(object):
|
|||
self._compare_structures(aa, bb, seen)
|
||||
else:
|
||||
if a in seen:
|
||||
self.assertIs(b, seen[a])
|
||||
self.assertEqual(b, seen[a])
|
||||
seen[a] = b
|
||||
|
||||
|
||||
class TestCombinators(TestMixin, unittest.TestCase):
|
||||
|
||||
|
||||
# def setUp(self):
|
||||
# def tearDown(self):
|
||||
|
||||
|
|
@ -76,9 +76,19 @@ class TestCombinators(TestMixin, unittest.TestCase):
|
|||
(mul, s2),
|
||||
infra
|
||||
]
|
||||
f = (s0, ((n0, (n1, s1)), s2))
|
||||
# (-- [n0 n1 ...1]) Two numbers in a stack.
|
||||
self.assertEqualTypeStructure(infr(expression), [f])
|
||||
f = [
|
||||
(s1, ((f1, (n1, s2)), s3)), # (-- [f1 n1 ...2])
|
||||
(s1, ((i1, (n1, s2)), s3)), # (-- [i1 n1 ...2])
|
||||
]
|
||||
self.assertEqualTypeStructure(infr(expression), f)
|
||||
|
||||
def test_nullary(self):
|
||||
expression = n1, n2, (mul, s2), (stack, s3), dip, infra, first
|
||||
f = [
|
||||
(s1, (f1, (n1, (n2, s2)))), # (-- n2 n1 f1)
|
||||
(s1, (i1, (n1, (n2, s2)))), # (-- n2 n1 i1)
|
||||
]
|
||||
self.assertEqualTypeStructure(infr(expression), f)
|
||||
|
||||
def test_x(self):
|
||||
expression = (a1, (swap, ((dup, s2), (dip, s0)))), x
|
||||
|
|
@ -129,6 +139,17 @@ class TestYin(TestMixin, unittest.TestCase):
|
|||
f = (s0, ((a0, s0), (a1, s1))) # (-- a1 [a0 ...0])
|
||||
self.assertEqualTypeStructure(infr(expression), [f])
|
||||
|
||||
def test_z_down(self):
|
||||
expression = s2, swap, uncons, swap
|
||||
f = (((a1, s1), s2), (a1, (s1, (s3, s2))))
|
||||
# ([a1 ...1] -- [...3] [...1] a1)
|
||||
self.assertEqualTypeStructure(infr(expression), [f])
|
||||
|
||||
def test_z_right(self):
|
||||
expression = a1, a2, (swons, s3), cons, dip, uncons, swap
|
||||
f = ((s1, s2), (a1, (s3, ((a2, s1), s2))))
|
||||
# ([...1] -- [a2 ...1] [...3] a1)
|
||||
self.assertEqualTypeStructure(infr(expression), [f])
|
||||
|
||||
## def test_(self):
|
||||
## expression = pop, swap, rolldown, rest, rest, cons, cons
|
||||
|
|
|
|||
Loading…
Reference in New Issue