diff --git a/joy/utils/polytypes.py b/joy/utils/polytypes.py index 918f65b..272b512 100644 --- a/joy/utils/polytypes.py +++ b/joy/utils/polytypes.py @@ -13,6 +13,7 @@ from itertools import chain, product import sys sys.path.append('/home/sforman/Desktop/Joypy-hg') import joy.library +from joy.utils.stack import concat as CONCAT from joy.utils.types import ( AnyJoyType, A, C, @@ -101,6 +102,9 @@ class FunctionJoyType(AnyJoyType): return self __radd__ = __add__ + def __repr__(self): + return self.name + class SymbolJoyType(FunctionJoyType): prefix = 'F' class CombinatorJoyType(FunctionJoyType): prefix = 'C' @@ -182,11 +186,8 @@ def _lil_uni(u, v, s): def compose(f, g): (f_in, f_out), (g_in, g_out) = f, g - s = unify(g_in, f_out) - if not s: - raise JoyTypeError('Cannot unify %r and %r.' % (fo, gi)) - for result in s: - yield update(result, (f_in, g_out)) + for s in unify(g_in, f_out): + yield update(s, (f_in, g_out)) def C(f, g): @@ -198,8 +199,7 @@ def C(f, g): def meta_compose(F, G): for f, g in product(F, G): try: - for result in C(f, g): - yield result + for result in C(f, g): yield result except JoyTypeError: pass @@ -231,6 +231,7 @@ def infer(e, F=ID): 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: @@ -260,21 +261,18 @@ mul = [ ] -SYMBOLS = { +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 + tuck uncons stack swaack '''.strip().split()) } - -SYMBOLS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100) - - -COMBINATORS = { +FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100) +FUNCTIONS.update({ combo.__name__: CombinatorJoyType(combo.__name__, [combo], i) for i, combo in enumerate(( joy.library.i, @@ -284,5 +282,21 @@ COMBINATORS = { 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) + + + + + diff --git a/joy/utils/types.py b/joy/utils/types.py index 91285d9..477155b 100644 --- a/joy/utils/types.py +++ b/joy/utils/types.py @@ -264,6 +264,7 @@ def defs(): tuck = __(a2, a1), __(a1, a2, a1) over = __(a2, a1), __(a2, a1, a2) stack = s0, (s0, s0) + swaack = (s1, s0), (s0, s1) stuncons = C(stack, uncons) stununcons = C(stack, uncons, uncons) first_two = C(uncons, uncons, pop) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 66ba2f7..87b61fa 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -8,77 +8,85 @@ from joy.utils.stack import list_to_stack as __ infr = lambda e: infer(__(e)) -globals().update(SYMBOLS) -globals().update(COMBINATORS) +globals().update(FUNCTIONS) class TestKleeneStar(unittest.TestCase): +# def setUp(self): +# def tearDown(self): + + def test_infra(self): + expression = [ + __((n1, n2, n3), s1), # Three numbers in a stack. + (mul, s2), + infra + ] + f = (s0, ((n0, (n1, s1)), s2)) + # (-- [n0 n1 ...1]) Two numbers in a stack. + self.assertEqual(infr(expression), [f]) + def test_sum(self): expression = [ - (n1, (n2, (n3, s1))), # Three numbers in a stack. + __((n1, n2, n3), s1), # Three numbers in a stack. sum, # builtin shadowed by SymbolJoyType ] # A function that puts a single number on the stack. f = s0, (n0, s0) self.assertEqual(infr(expression), [f]) - def test_BS(self): + def test_Yin(self): expression = pop, swap, rolldown, rest, rest, cons, cons # ([a3 a4 ...0] a2 a1 a0 -- [a1 a2 ...0]) f = (a0, (a1, (a2, ((a3, (a4, s0)), s1)))), ((a1, (a2, s0)), s1) self.assertEqual(infr(expression), [f]) - def test_enter(self): + def test_cons_dip(self): expression = a1, (cons, s0), dip # a1 [cons] dip # (a0 [...0] -- [a0 ...0] a1) f = ((s0, (a0, s1)), (a1, ((a0, s0), s1))) self.assertEqual(infr(expression), [f]) - def test_2(self): + def test_cons_dipd(self): + expression = a1, a3, (cons, s0), dipd + f = ((s0, (a0, s1)), (a1, (a2, ((a0, s0), s1)))) + # (a0 [...0] -- [a0 ...0] a2 a1) + self.assertEqual(infr(expression), [f]) + + def test_i(self): # [cons] i == cons expression = (cons, s0), i self.assertEqual(infr(expression), infr([cons])) + def test_branch(self): + ''' + a1 [dup] [cons] branch + ''' + expression = a1, (dup, s0), (cons, s0), branch + f = [ + ((s0, (a0, s1)), ((a0, s0), s1)), # (a0 [...0] -- [a0 ...0]) + ((a0, s0), (a0, (a0, s0))), # (a0 -- a0 a0) + ] + self.assertEqual(infr(expression), f) + + def test_swaack(self): + expression = a0, (a1, s0), swaack + f = (s0, ((a0, s0), (a1, s1))) # (-- a1 [a0 ...0]) + self.assertEqual(infr(expression), [f]) + + def test_x(self): + expression = (a1, (swap, ((dup, s2), (dip, s0)))), x + f = (s0, ((a0, (swap, ((dup, s1), (dip, s2)))), (a1, (a1, s0)))) + # (-- a1 a1 [a0 swap [dup ...1] dip ...2]) + self.assertEqual(infr(expression), [f]) + +## for sec in infr(expression): +## print sec, doc_from_stack_effect(*sec) + -## ##for g in MC(dup, mul): ## print doc_from_stack_effect(*g) -## print doc_from_stack_effect(*f) -## print -## for sec in infer(e): -## print sec, doc_from_stack_effect(*sec) -## self.assertRaises(KeyError, lambda: {}[23]) -## def test_leave(self): -## def setUp(self): -## def tearDown(self): - - - -##DIP = CombinatorJoyType('dip', [dip], 44) -##DIPD = CombinatorJoyType('dipd', [dipd], 45) - -##l = [(s0, ((CONS, s2), (A[1], s0)))] -## -##e = (DIP, ()) -## -##h = infer(e, l[0]) -## -##for z in h: -## print doc_from_stack_effect(*z) - -## -## -## -## -## -##expression = (a1, (a3, ((CONS, s0), (DIPD, ())))) -## -##for sec in infer(expression): -## print doc_from_stack_effect(*sec) -## - if __name__ == '__main__': unittest.main()