From ab8ec6c95d23d87c3d778bf75d45ccf802ba25a9 Mon Sep 17 00:00:00 2001 From: Simon Forman Date: Wed, 4 Jul 2018 10:37:43 -0700 Subject: [PATCH] Minor cleanup. Renamed update() to reify() and reinstated recursive substitution. --- joy/library.py | 3 ++- joy/utils/polytypes.py | 17 ++++++++------ joy/utils/types.py | 44 +++++++++++++++++-------------------- test/test_type_inference.py | 26 ++++++++++++---------- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/joy/library.py b/joy/library.py index 975efda..bedad4c 100644 --- a/joy/library.py +++ b/joy/library.py @@ -127,7 +127,8 @@ make_generator == [codireco] ccons ''' # ifte == [nullary not] dipd branch # ifte == [nullary] dipd swap branch - +# genrec == [[genrec] cons cons cons cons] nullary swons concat ifte + ##ccons == cons cons ##unit == [] cons ##second == rest first diff --git a/joy/utils/polytypes.py b/joy/utils/polytypes.py index cd29265..e7cb851 100644 --- a/joy/utils/polytypes.py +++ b/joy/utils/polytypes.py @@ -34,7 +34,7 @@ from joy.utils.types import ( _stacky, _R, relabel, delabel, - update, + reify, ) @@ -155,12 +155,12 @@ class CombinatorJoyType(FunctionJoyType): def _log_uni(U): def inner(u, v, s=None): - _log.info( + _log.debug( '%3i %s U %s w/ %s', len(inspect_stack()), u, v, s, ) res = U(u, v, s) - _log.info( + _log.debug( '%3i %s U %s w/ %s => %s', len(inspect_stack()), u, v, s, res, ) @@ -176,8 +176,8 @@ def unify(u, v, s=None): if s is None: s = {} elif s: - u = update(s, u) - v = update(s, v) + u = reify(s, u) + v = reify(s, v) if u == v: res = s, @@ -243,7 +243,7 @@ def _lil_uni(u, v, s): def _compose(f, g, e): (f_in, f_out), (g_in, g_out) = f, g for s in unify(g_in, f_out): - yield update(s, (e, (f_in, g_out))) + yield reify(s, (e, (f_in, g_out))) def compose(f, g, e): @@ -311,7 +311,7 @@ def _infer(e, F=ID): def _interpret(f, fi, fo, e): new_fo, ee, _ = f(fo, e, {}) - ee = update(FUNCTIONS, ee) # Fix Symbols. + ee = reify(FUNCTIONS, ee) # Fix Symbols. new_F = fi, new_fo return _infer(ee, new_F) @@ -376,6 +376,8 @@ def defs(): sum_ = product = [(((Ns[1], s1), s0), (n0, s0))] + clear = [((As[1], s0), s1)] + add = mul = sub = floordiv = modulus = [ ((i2, (i1, s0)), (i3, s0)), ((f2, (i1, s0)), (f3, s0)), @@ -466,6 +468,7 @@ def set_expectations(): scope = globals().copy() scope.update(FUNCTIONS) eval(set_expectations.func_code, scope) +del scope # Type Checking... diff --git a/joy/utils/types.py b/joy/utils/types.py index 5575bc8..6251f24 100644 --- a/joy/utils/types.py +++ b/joy/utils/types.py @@ -1,6 +1,7 @@ from collections import Counter from itertools import imap from joy.utils.stack import concat +from joy.parser import Symbol class AnyJoyType(object): @@ -53,27 +54,19 @@ class StackJoyType(AnyJoyType): class JoyTypeError(Exception): pass -def update(s, term): - ''' - Apply substitution dict to term, returning new term. - ''' - t = _update(s, term) - n = 10 - while t != term: - n -= 1 - if not n: - print t - print term - print 'lalala' - 1/0 - term = t - t = _update(s, term) - return term - -def _update(s, term): - if not isinstance(term, tuple): - return s.get(term, term) - return tuple(_update(s, inner) for inner in term) +def reify(meaning, name, seen=None): + ''' + Apply substitution dict to term, returning new term. + ''' + if isinstance(name, tuple): + return tuple(reify(meaning, inner) for inner in name) + safety = 101 + while name in meaning and safety: + safety -= 1 + name = meaning[name] + if not safety: + raise ValueError('Cycle in substitution dict: %s' % (meaning,)) + return name def relabel(left, right): @@ -121,8 +114,8 @@ def unify(u, v, s=None): if s is None: s = {} elif s: - u = update(s, u) - v = update(s, v) + u = reify(s, u) + v = reify(s, v) if isinstance(u, AnyJoyType) and isinstance(v, AnyJoyType): if u >= v: @@ -164,7 +157,7 @@ def _compose(f, g): ''' # Relabel, unify, update, delabel. (f_in, f_out), (g_in, g_out) = relabel(f, g) - fg = update(unify(g_in, f_out), (f_in, g_out)) + fg = reify(unify(g_in, f_out), (f_in, g_out)) return delabel(fg) @@ -273,6 +266,8 @@ def defs(): ''' Return a dict of named stack effects. ''' + at = __(s0, i1), __(a1) + drop = take = __(s0, i1), __(s1) cons = __(a1, s0), __((a1, s0),) ccons = compose(cons, cons) dup = __(a1,), __(a1, a1) @@ -316,6 +311,7 @@ def defs(): first_two = compose(uncons, uncons, pop) fourth = compose(rest, third) + of = compose(swap, at) _Tree_add_Ee = compose(pop, swap, rolldown, rrest, ccons) _Tree_get_E = compose(popop, second) diff --git a/test/test_type_inference.py b/test/test_type_inference.py index 2f10558..9d1782d 100644 --- a/test/test_type_inference.py +++ b/test/test_type_inference.py @@ -31,7 +31,8 @@ class TestMixin(object): else: if a in seen: self.assertEqual(b, seen[a]) - seen[a] = b + else: + seen[a] = b class TestCombinators(TestMixin, unittest.TestCase): @@ -43,7 +44,7 @@ class TestCombinators(TestMixin, unittest.TestCase): ''' a1 [dup] [cons] branch ''' - expression = a1, (dup, s0), (cons, s0), branch + expression = a1, (dup, s1), (cons, s2), branch f = [ ((a0, s0), (a0, (a0, s0))), # (a0 -- a0 a0) ((s0, (a0, s1)), ((a0, s0), s1)), # (a0 [...0] -- [a0 ...0]) @@ -51,8 +52,8 @@ class TestCombinators(TestMixin, unittest.TestCase): self.assertEqualTypeStructure(infer(*expression), f) def test_concat(self): - expression = (swons, s3), (a4, s0), concat_ - f = (s1, ((swons, (a1, s1)), s1)) # (... -- ... [swons a1 ...]) + expression = (swons, s3), (a4, s1), concat_ + f = (s1, ((swons, (a1, s2)), s1)) # (-- [swons a1 ...2]) self.assertEqualTypeStructure(infer(*expression), [f]) def test_dip(self): @@ -67,9 +68,9 @@ class TestCombinators(TestMixin, unittest.TestCase): self.assertEqualTypeStructure(infer(*expression), [f]) 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) + expression = (cons, s0), dipd + f = ((a2, (a1, (s1, (a3, s2)))), (a2, (a1, ((a3, s1), s2)))) + # (a3 [...1] a1 a2 -- [a3 ...1] a1 a2) self.assertEqualTypeStructure(infer(*expression), [f]) def test_i(self): @@ -77,6 +78,11 @@ class TestCombinators(TestMixin, unittest.TestCase): expression = (cons, s0), i self.assertEqualTypeStructure(infer(*expression), infer(cons)) + def test_i_dip(self): + expression = (i, s3), dip # [i] dip + f = ((a1, (s1, s2)), (a1, s2)) # ([...1] a1 -- a1) + self.assertEqualTypeStructure(infer(*expression), [f]) + def test_infra(self): expression = [ __((n1, n2, n3), s1), # Three numbers in a stack. @@ -106,11 +112,7 @@ class TestCombinators(TestMixin, unittest.TestCase): expression = (stack, s3), dip, infra, first f = ((s1, (a1, s2)), (a1, (a1, s2))) # (a1 [...1] -- a1 a1) self.assertEqualTypeStructure(infer(*expression), [f]) - expression = nullary, - f = ((s1, (a1, s2)), (a1, (a1, s2))) # (a1 [...1] -- a1 a1) - # Something's not quite right here... - # e = infer(*expression) self.assertEqualTypeStructure(infer(*expression), [f]) def test_x(self): @@ -192,4 +194,4 @@ class TestYin(TestMixin, unittest.TestCase): if __name__ == '__main__': - unittest.main() #defaultTest='TestCombinators.test_cons_dip') + unittest.main() #defaultTest='TestCombinators.test_branch')