From db28989b6457878a641fa3b7812248d6f37e33ab Mon Sep 17 00:00:00 2001 From: Simon Forman Date: Tue, 26 Jun 2018 21:45:58 -0700 Subject: [PATCH] Trying to add a guard to combinators. So they can notice if they're given a stack that doesn't match what they're expecting. This seems to work, but I realized that type variables in the pending expression need to be update()'d too. hmm... --- joy/utils/polytypes.py | 106 ++++++++++++++++++++++-------------- test/test_type_inference.py | 14 +++-- 2 files changed, 75 insertions(+), 45 deletions(-) diff --git a/joy/utils/polytypes.py b/joy/utils/polytypes.py index a878f2b..ff0ddb1 100644 --- a/joy/utils/polytypes.py +++ b/joy/utils/polytypes.py @@ -10,8 +10,6 @@ an unbounded sequence of other types. ''' 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 @@ -109,7 +107,24 @@ class FunctionJoyType(AnyJoyType): class SymbolJoyType(FunctionJoyType): prefix = 'F' -class CombinatorJoyType(FunctionJoyType): prefix = 'C' + + +class CombinatorJoyType(FunctionJoyType): + + prefix = 'C' + + def __init__(self, name, sec, number, expect=None): + super(CombinatorJoyType, self).__init__(name, sec, number) + self.expect = expect + + def enter_guard(self, f): + if self.expect is None: + return f + g = self.expect, self.expect + new_f = list(C(f, g)) + assert len(new_f) == 1, repr(new_f) + return new_f[0] + def unify(u, v, s=None): @@ -224,10 +239,14 @@ def infer(e, F=ID): res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects)) elif isinstance(n, CombinatorJoyType): + fi, fo = n.enter_guard(F) res = [] for combinator in n.stack_effects: - fi, fo = F + print fo + print e new_fo, ee, _ = combinator(fo, e, {}) + print new_fo + print ee ee = update(FUNCTIONS, ee) # Fix Symbols. new_F = fi, new_fo res.extend(infer(ee, new_F)) @@ -294,6 +313,10 @@ FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 1 globals().update(FUNCTIONS) + +dip.expect = s8, (a8, s7) + + def _ge(self, other): return (issubclass(other.__class__, self.__class__) or hasattr(self, 'accept') @@ -304,40 +327,41 @@ 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 +##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 +## diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 5645545..194c0c6 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -54,9 +54,15 @@ class TestCombinators(TestMixin, unittest.TestCase): self.assertEqualTypeStructure(infr(expression), f) 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))) + expression = (cons, s0), dip # [cons] dip + # (a2 [...1] a1 -- [a2 ...1] a3) + f = (a1, (s1, (a2, s2))), (a1, ((a2, s1), s2)) + # shouldn't a3 be a1? + self.assertEqualTypeStructure(infr(expression), [f]) + + def test_dip(self): + expression = dip, + f = ((s1, (a1, s2)), (a2, s2)) # (a1 [...1] -- a2) self.assertEqualTypeStructure(infr(expression), [f]) def test_cons_dipd(self): @@ -163,4 +169,4 @@ class TestYin(TestMixin, unittest.TestCase): if __name__ == '__main__': - unittest.main() + unittest.main(defaultTest='TestCombinators.test_cons_dip')