• R/O
  • SSH

Joypy: Commit

Main interpreter and library.


Commit MetaInfo

Revisionb24f0d4a1bd9d205315ff7401aad0b3e249edd1b (tree)
Time2018-08-02 02:59:07
AuthorSimon Forman <sforman@hush...>
CommiterSimon Forman

Log Message

Working on compiler.

I have a simple dataflow thingy for some Yin and Yang functions.

Change Summary

Incremental Difference

diff -r ac8c0ffac10b -r b24f0d4a1bd9 joy/utils/compiler.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/joy/utils/compiler.py Wed Aug 01 10:59:07 2018 -0700
@@ -0,0 +1,107 @@
1+from joy.parser import text_to_expression, Symbol
2+from joy.utils.stack import iter_stack, list_to_stack
3+from joy.library import SimpleFunctionWrapper
4+
5+
6+def import_yin():
7+ from joy.utils.generated_library import *
8+ return locals()
9+
10+D = {
11+ name: SimpleFunctionWrapper(func)
12+ for name, func in import_yin().iteritems()
13+ }
14+
15+
16+def _names():
17+ n = 0
18+ while True:
19+ yield Symbol('a' + str(n))
20+ n += 1
21+
22+
23+class InfiniteStack(tuple):
24+
25+ names = _names().next
26+
27+ def __init__(self, code):
28+ self.code = code
29+
30+ def __iter__(self):
31+ if not self:
32+ new_var = self.names()
33+ self.code.append(('pop', new_var))
34+ return iter((new_var, self))
35+
36+
37+class Foo(object):
38+
39+ def __init__(self, name):
40+ self.name = name
41+
42+ def __call__(self, stack, expression, code):
43+ in1, (in0, stack) = stack
44+ out = InfiniteStack.names()
45+ code.append(('call', out, self.name, (in0, in1)))
46+ return (out, stack), expression, code
47+
48+
49+def I(expression):
50+ code = []
51+ stack = InfiniteStack(code)
52+
53+ while expression:
54+ term, expression = expression
55+ if isinstance(term, Symbol):
56+ func = D[term]
57+ stack, expression, _ = func(stack, expression, code)
58+ else:
59+ stack = term, stack
60+
61+ s = list(iter_stack(stack))
62+ if s: code.append(tuple(['ret'] + s))
63+ return code
64+
65+
66+strtup = lambda a, b: '(%s, %s)' % (b, a)
67+strstk = lambda rest: reduce(strtup, rest, 'stack')
68+
69+
70+def code_gen(code):
71+ coalesce_pops(code)
72+ lines = []
73+ emit = lines.append
74+ for t in code:
75+ tag, rest = t[0], t[1:]
76+ if tag == 'pop': emit(strstk(rest) + ' = stack')
77+ elif tag == 'call': emit('%s = %s%s' % rest)
78+ elif tag == 'ret': emit('return ' + strstk(rest))
79+ else:
80+ raise ValueError(tag)
81+ return '\n'.join(' ' + line for line in lines)
82+
83+
84+def coalesce_pops(code):
85+ code.sort(key=lambda p: p[0] != 'pop') # All pops to the front.
86+ index = (i for i, t in enumerate(code) if t[0] != 'pop').next()
87+ code[:index] = [tuple(['pop'] + [t for _, t in code[:index][::-1]])]
88+
89+
90+def compile_yinyang(name, text):
91+ return '''
92+def %s(stack):
93+%s
94+''' % (name, code_gen(I(text_to_expression(text))))
95+
96+
97+D['mul'] = Foo('mul')
98+D['sub'] = Foo('sub')
99+
100+##print compile_yinyang('mul_', 'mul')
101+##print compile_yinyang('sqr', 'dup mul')
102+##print compile_yinyang('foo', 'dup 23 sub mul')
103+##print compile_yinyang('bar', 'mul mul mul mul')
104+##print compile_yinyang('baz', 'mul dup sub dup')
105+##print compile_yinyang('to_the_fifth_power', 'dup dup mul dup mul mul')
106+##print compile_yinyang('hey', 'dup dup dup')
107+print compile_yinyang('hey', 'first_two')
Show on old repository browser