Minor cleanup.

Joy type errors get their own exception class.
This commit is contained in:
Simon Forman 2018-06-24 18:39:46 -07:00
parent 1aace53fa0
commit d874b2a134
2 changed files with 103 additions and 143 deletions

View File

@ -8,15 +8,18 @@ and we can introduce a kind of Kleene Star or sequence type that can stand for
an unbounded sequence of other types. an unbounded sequence of other types.
''' '''
from itertools import chain, product
import sys import sys
sys.path.append('/home/sforman/Desktop/Joypy-hg') sys.path.append('/home/sforman/Desktop/Joypy-hg')
from itertools import product import joy.library
from joy.utils.types import ( from joy.utils.types import (
AnyJoyType, A, AnyJoyType, A,
C, C,
DEFS, DEFS,
doc_from_stack_effect, doc_from_stack_effect,
FloatJoyType, FloatJoyType,
JoyTypeError,
NumberJoyType, N, NumberJoyType, N,
StackJoyType, S, StackJoyType, S,
stacky, stacky,
@ -30,13 +33,6 @@ from joy.utils.types import (
class IntJoyType(NumberJoyType): prefix = 'i' class IntJoyType(NumberJoyType): prefix = 'i'
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = A
n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
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)
class KleeneStar(object): class KleeneStar(object):
''' '''
A sequence of zero or more `AnyJoyType` variables would be: A sequence of zero or more `AnyJoyType` variables would be:
@ -94,20 +90,20 @@ class NumberStarJoyType(KleeneStar): kind = NumberJoyType
class StackStarJoyType(KleeneStar): kind = StackJoyType class StackStarJoyType(KleeneStar): kind = StackJoyType
As = map(AnyStarJoyType, _R) class FunctionJoyType(AnyJoyType):
Ns = map(NumberStarJoyType, _R)
Ss = map(StackStarJoyType, _R) 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 _lil_uni(u, v, s): class SymbolJoyType(FunctionJoyType): prefix = 'F'
if u >= v: class CombinatorJoyType(FunctionJoyType): prefix = 'C'
s[u] = v
return s,
if v >= u:
s[v] = u
return s,
raise TypeError('Cannot unify %r and %r.' % (u, v))
def unify(u, v, s=None): def unify(u, v, s=None):
@ -125,7 +121,7 @@ def unify(u, v, s=None):
if isinstance(u, tuple) and isinstance(v, tuple): if isinstance(u, tuple) and isinstance(v, tuple):
if len(u) != len(v) != 2: if len(u) != len(v) != 2:
raise TypeError(repr((u, v))) raise JoyTypeError(repr((u, v)))
a, b = v a, b = v
if isinstance(a, KleeneStar): if isinstance(a, KleeneStar):
@ -161,24 +157,34 @@ def unify(u, v, s=None):
if isinstance(v, tuple): if isinstance(v, tuple):
if not stacky(u): if not stacky(u):
raise TypeError('Cannot unify %r and %r.' % (u, v)) raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
s[u] = v s[u] = v
return s, return s,
if isinstance(u, tuple): if isinstance(u, tuple):
if not stacky(v): if not stacky(v):
raise TypeError('Cannot unify %r and %r.' % (v, u)) raise JoyTypeError('Cannot unify %r and %r.' % (v, u))
s[v] = u s[v] = u
return s, return s,
return () return ()
def _lil_uni(u, v, s):
if u >= v:
s[u] = v
return s,
if v >= u:
s[v] = u
return s,
raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
def compose(f, g): def compose(f, g):
(f_in, f_out), (g_in, g_out) = f, g (f_in, f_out), (g_in, g_out) = f, g
s = unify(g_in, f_out) s = unify(g_in, f_out)
if not s: if not s:
raise TypeError('Cannot unify %r and %r.' % (fo, gi)) raise JoyTypeError('Cannot unify %r and %r.' % (fo, gi))
for result in s: for result in s:
yield update(result, (f_in, g_out)) yield update(result, (f_in, g_out))
@ -194,17 +200,57 @@ def meta_compose(F, G):
try: try:
for result in C(f, g): for result in C(f, g):
yield result yield result
except TypeError: except JoyTypeError:
pass pass
def MC(F, G): def MC(F, G):
res = sorted(set(meta_compose(F, G))) res = sorted(set(meta_compose(F, G)))
if not res: if not res:
raise TypeError('Cannot unify %r and %r.' % (F, G)) raise JoyTypeError('Cannot unify %r and %r.' % (F, G))
return res return res
flatten = lambda g: list(chain.from_iterable(g))
ID = S[0], S[0] # Identity function.
def kav(e, F=ID):
if not e:
return [F]
n, e = e
if isinstance(n, SymbolJoyType):
res = flatten(kav(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, {})
new_F = fi, new_fo
res.extend(kav(ee, new_F))
else:
lit = s9, (n, s9)
res = flatten(kav(e, Fn) for Fn in MC([F], [lit]))
return res
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = A
n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
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)
As = map(AnyStarJoyType, _R)
Ns = map(NumberStarJoyType, _R)
Ss = map(StackStarJoyType, _R)
mul = [ mul = [
((i2, (i1, s0)), (i3, s0)), ((i2, (i1, s0)), (i3, s0)),
@ -214,118 +260,29 @@ mul = [
] ]
dup = [DEFS['dup']] SYMBOLS = {
cons = [DEFS['cons']] name: SymbolJoyType(name, [DEFS[name]], i)
for i, name in enumerate('''
ccons cons divmod_ dup dupd first
sum_ = [(((Ns[1], s1), s0), (n0, s0))] mul over pm pop popd popdd popop
f = [(s0, ((n1, (n2, (n3, s1))), s0))] pred rest rolldown rollup rrest
second sqrt succ swap swons third
tuck uncons
print doc_from_stack_effect(*f[0]), doc_from_stack_effect(*sum_[0]) '''.strip().split())
print '.......................' }
##for result in unify(sum_[0][0], f[0][1]):
## print result, '->', update(result, sum_[0][1]) SYMBOLS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
for g in MC(f, sum_):
print doc_from_stack_effect(*g)
print
print '.......................'
print
for g in MC(dup, mul):
print doc_from_stack_effect(*g)
##stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if isinstance(q, tuple) 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__
class SymbolJoyType(FunctionJoyType): prefix = 'F'
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
from joy.library import dip, dipd
##def dip_t(stack, expression):
## (quote, (a1, stack)) = stack
## expression = stack_concat(quote, (a1, expression))
## return stack, expression
CONS = SymbolJoyType('cons', cons, 23)
DIP = CombinatorJoyType('dip', [dip], 44)
DIPD = CombinatorJoyType('dipd', [dipd], 45)
from itertools import chain
flatten = lambda g: list(chain.from_iterable(g))
def kav(F, e):
if not e:
return [F]
n, e = e
if isinstance(n, SymbolJoyType):
Fs = MC([F], n.stack_effects)
res = flatten(kav(Fn, e) for Fn in Fs)
elif isinstance(n, CombinatorJoyType):
res = []
for combinator in n.stack_effects:
fi, fo = F
new_fo, ee, _ = combinator(fo, e, {})
new_F = fi, new_fo
res.extend(kav(new_F, ee))
else:
lit = s9, (n, s9)
res = flatten(kav(Fn, e) for Fn in MC([F], [lit]))
return res
##l = [(s0, ((CONS, s2), (A[1], s0)))]
##
##e = (DIP, ())
##
##h = kav(l[0], e)
##
##for z in h:
## print doc_from_stack_effect(*z)
ID = s0, s0
expression = (a1, ((CONS, s0), (DIP, ())))
for sec in kav(ID, expression):
print doc_from_stack_effect(*sec)
expression = (a1, (a3, ((CONS, s0), (DIPD, ()))))
for sec in kav(ID, expression):
print doc_from_stack_effect(*sec)
COMBINATORS = {
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,
))
}

View File

@ -47,6 +47,9 @@ N = n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = map(NumberJoyType, _R)
S = s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = map(StackJoyType, _R) S = s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = map(StackJoyType, _R)
class JoyTypeError(Exception): pass
def update(s, term): def update(s, term):
if not isinstance(term, tuple): if not isinstance(term, tuple):
return s.get(term, term) return s.get(term, term)
@ -106,7 +109,7 @@ def unify(u, v, s=None):
if v >= u: if v >= u:
s[v] = u s[v] = u
return s return s
raise TypeError('Cannot unify %r and %r.' % (u, v)) raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
if isinstance(u, tuple) and isinstance(v, tuple): if isinstance(u, tuple) and isinstance(v, tuple):
if len(u) != len(v) != 2: if len(u) != len(v) != 2:
@ -119,13 +122,13 @@ def unify(u, v, s=None):
if isinstance(v, tuple): if isinstance(v, tuple):
if not stacky(u): if not stacky(u):
raise TypeError('Cannot unify %r and %r.' % (u, v)) raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
s[u] = v s[u] = v
return s return s
if isinstance(u, tuple): if isinstance(u, tuple):
if not stacky(v): if not stacky(v):
raise TypeError('Cannot unify %r and %r.' % (v, u)) raise JoyTypeError('Cannot unify %r and %r.' % (v, u))
s[v] = u s[v] = u
return s return s
@ -146,7 +149,7 @@ def compose(f, g):
else: else:
s = unify(g_in, f_out) s = unify(g_in, f_out)
if s == False: # s can also be the empty dict, which is ok. if s == False: # s can also be the empty dict, which is ok.
raise TypeError('Cannot unify %r and %r.' % (fo, gi)) raise JoyTypeError('Cannot unify %r and %r.' % (fo, gi))
fg_in, fg_out = update(s, (f_in, g_out)) fg_in, fg_out = update(s, (f_in, g_out))
return fg_in, fg_out return fg_in, fg_out