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...
This commit is contained in:
Simon Forman 2018-06-26 21:45:58 -07:00
parent bbc0fae2e9
commit db28989b64
2 changed files with 75 additions and 45 deletions

View File

@ -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
##

View File

@ -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')