Working on compiler.

I have a simple dataflow thingy for some Yin and Yang functions.
This commit is contained in:
Simon Forman 2018-08-01 10:59:07 -07:00
parent f2425ae1ae
commit 5974c516d1
1 changed files with 107 additions and 0 deletions

107
joy/utils/compiler.py Normal file
View File

@ -0,0 +1,107 @@
from joy.parser import text_to_expression, Symbol
from joy.utils.stack import iter_stack, list_to_stack
from joy.library import SimpleFunctionWrapper
def import_yin():
from joy.utils.generated_library import *
return locals()
D = {
name: SimpleFunctionWrapper(func)
for name, func in import_yin().iteritems()
}
def _names():
n = 0
while True:
yield Symbol('a' + str(n))
n += 1
class InfiniteStack(tuple):
names = _names().next
def __init__(self, code):
self.code = code
def __iter__(self):
if not self:
new_var = self.names()
self.code.append(('pop', new_var))
return iter((new_var, self))
class Foo(object):
def __init__(self, name):
self.name = name
def __call__(self, stack, expression, code):
in1, (in0, stack) = stack
out = InfiniteStack.names()
code.append(('call', out, self.name, (in0, in1)))
return (out, stack), expression, code
def I(expression):
code = []
stack = InfiniteStack(code)
while expression:
term, expression = expression
if isinstance(term, Symbol):
func = D[term]
stack, expression, _ = func(stack, expression, code)
else:
stack = term, stack
s = list(iter_stack(stack))
if s: code.append(tuple(['ret'] + s))
return code
strtup = lambda a, b: '(%s, %s)' % (b, a)
strstk = lambda rest: reduce(strtup, rest, 'stack')
def code_gen(code):
coalesce_pops(code)
lines = []
emit = lines.append
for t in code:
tag, rest = t[0], t[1:]
if tag == 'pop': emit(strstk(rest) + ' = stack')
elif tag == 'call': emit('%s = %s%s' % rest)
elif tag == 'ret': emit('return ' + strstk(rest))
else:
raise ValueError(tag)
return '\n'.join(' ' + line for line in lines)
def coalesce_pops(code):
code.sort(key=lambda p: p[0] != 'pop') # All pops to the front.
index = (i for i, t in enumerate(code) if t[0] != 'pop').next()
code[:index] = [tuple(['pop'] + [t for _, t in code[:index][::-1]])]
def compile_yinyang(name, text):
return '''
def %s(stack):
%s
''' % (name, code_gen(I(text_to_expression(text))))
D['mul'] = Foo('mul')
D['sub'] = Foo('sub')
##print compile_yinyang('mul_', 'mul')
##print compile_yinyang('sqr', 'dup mul')
##print compile_yinyang('foo', 'dup 23 sub mul')
##print compile_yinyang('bar', 'mul mul mul mul')
##print compile_yinyang('baz', 'mul dup sub dup')
##print compile_yinyang('to_the_fifth_power', 'dup dup mul dup mul mul')
##print compile_yinyang('hey', 'dup dup dup')
print compile_yinyang('hey', 'first_two')