Things have kind of run away with me. I've been working in Prolog for the last month or so. I'm not yet sure how to bring it together with the Python code.
28 KiB
28 KiB
In [1]:
from notebook_preamble import D, J, V, defineIn [2]:
V('23 sqr'). 23 sqr 23 . sqr 23 . dup mul 23 23 . mul 529 .
In [3]:
dup, mul = D['dup'], D['mul']In [4]:
def sqr(stack, expression, dictionary):
return mul(*dup(stack, expression, dictionary))In [5]:
old_sqr = D['sqr']
D['sqr'] = sqrIn [6]:
V('23 sqr'). 23 sqr 23 . sqr 529 .
In [7]:
def compile_joy(name, expression):
term, expression = expression
code = term +'(stack, expression, dictionary)'
format_ = '%s(*%s)'
while expression:
term, expression = expression
code = format_ % (term, code)
return '''\
def %s(stack, expression, dictionary):
return %s
''' % (name, code)
def compile_joy_definition(defi):
return compile_joy(defi.name, defi.body)
In [8]:
print compile_joy_definition(old_sqr)def sqr(stack, expression, dictionary):
return mul(*dup(stack, expression, dictionary))
In [9]:
unit, dip = D['unit'], D['dip']In [10]:
# print compile_joy_definition(D['quoted'])
# raises
# TypeError: can only concatenate tuple (not "str") to tupleIn [11]:
def foo(stack, expression, dictionary):
stack, expression, dictionary = baz(*bar(stack, expression, dictionary))
return barp(*lerp(*baq((99, (23, stack)), expression, dictionary)))In [12]:
from joy.utils.types import compile_, doc_from_stack_effect, infer_string
from joy.library import SimpleFunctionWrapperIn [13]:
stack_effects = infer_string('tuck over dup')In [14]:
for fi, fo in stack_effects:
print doc_from_stack_effect(fi, fo)(a2 a1 -- a1 a2 a1 a2 a2)
In [15]:
source = compile_('foo', stack_effects[0])In [16]:
print sourcedef foo(stack): """ :: (a2 a1 -- a1 a2 a1 a2 a2) """ (a1, (a2, s1)) = stack return (a2, (a2, (a1, (a2, (a1, s1)))))
In [17]:
exec compile(source, '__main__', 'single')
D['foo'] = SimpleFunctionWrapper(foo)In [18]:
V('23 18 foo') . 23 18 foo
23 . 18 foo
23 18 . foo
18 23 18 23 23 .
In [19]:
from joy.parser import text_to_expressionIn [20]:
Ein = '[a b c d] e a [f]' # The terms should be reversed here but I don't realize that until later.
Eout = '[a e c d]'
E = '[%s] [%s]' % (Ein, Eout)
print E[[a b c d] e a [f]] [[a e c d]]
In [21]:
(fi, (fo, _)) = text_to_expression(E)In [22]:
fi, foOut [22]:
(((a, (b, (c, (d, ())))), (e, (a, ((f, ()), ())))), ((a, (e, (c, (d, ())))), ()))
In [23]:
Ein = '[a1 a2 a3 a4] a5 a6 a7'
Eout = '[a1 a5 a3 a4]'
E = '[%s] [%s]' % (Ein, Eout)
print E[[a1 a2 a3 a4] a5 a6 a7] [[a1 a5 a3 a4]]
In [24]:
(fi, (fo, _)) = text_to_expression(E)In [25]:
fi, foOut [25]:
(((a1, (a2, (a3, (a4, ())))), (a5, (a6, (a7, ())))), ((a1, (a5, (a3, (a4, ())))), ()))
In [26]:
def type_vars():
from joy.library import a1, a2, a3, a4, a5, a6, a7, s0, s1
return locals()
tv = type_vars()
tvOut [26]:
{'a1': a1,
'a2': a2,
'a3': a3,
'a4': a4,
'a5': a5,
'a6': a6,
'a7': a7,
's0': s0,
's1': s1}In [27]:
from joy.utils.types import reifyIn [28]:
stack_effect = reify(tv, (fi, fo))
print doc_from_stack_effect(*stack_effect)(... a7 a6 a5 [a1 a2 a3 a4 ] -- ... [a1 a5 a3 a4 ])
In [29]:
print stack_effect(((a1, (a2, (a3, (a4, ())))), (a5, (a6, (a7, ())))), ((a1, (a5, (a3, (a4, ())))), ()))
In [30]:
stack_effect = eval('(((a1, (a2, (a3, (a4, s1)))), (a5, (a6, (a7, s0)))), ((a1, (a5, (a3, (a4, s1)))), s0))', tv)In [31]:
print doc_from_stack_effect(*stack_effect)(a7 a6 a5 [a1 a2 a3 a4 ...1] -- [a1 a5 a3 a4 ...1])
In [32]:
stack_effect = eval('(((a1, (a2, s1)), (a5, (a6, (a7, s0)))), ((a1, (a5, s1)), s0))', tv)In [33]:
print doc_from_stack_effect(*stack_effect)(a7 a6 a5 [a1 a2 ...1] -- [a1 a5 ...1])
In [34]:
source = compile_('Ee', stack_effect)
print sourcedef Ee(stack): """ :: (a7 a6 a5 [a1 a2 ...1] -- [a1 a5 ...1]) """ ((a1, (a2, s1)), (a5, (a6, (a7, s0)))) = stack return ((a1, (a5, s1)), s0)
In [35]:
stack_effect = eval('((a7, (a6, (a5, ((a1, (a2, s1)), s0)))), ((a1, (a5, s1)), s0))', tv)In [36]:
print doc_from_stack_effect(*stack_effect)([a1 a2 ...1] a5 a6 a7 -- [a1 a5 ...1])
In [37]:
source = compile_('Ee', stack_effect)
print sourcedef Ee(stack): """ :: ([a1 a2 ...1] a5 a6 a7 -- [a1 a5 ...1]) """ (a7, (a6, (a5, ((a1, (a2, s1)), s0)))) = stack return ((a1, (a5, s1)), s0)
In [38]:
eval(compile(source, '__main__', 'single'))
D['Ee'] = SimpleFunctionWrapper(Ee)In [39]:
V('[a b c d] 1 2 [f] Ee') . [a b c d] 1 2 [f] Ee
[a b c d] . 1 2 [f] Ee
[a b c d] 1 . 2 [f] Ee
[a b c d] 1 2 . [f] Ee
[a b c d] 1 2 [f] . Ee
[a 1 c d] .
In [ ]:
In [40]:
def dup(stack):
(a1, s23) = stack
return (a1, (a1, s23))
In [41]:
stack_effects = infer_string('dup mul')
for fi, fo in stack_effects:
print doc_from_stack_effect(fi, fo)(n1 -- n2)
In [42]:
def sqr(stack):
(n1, s23) = stack
n2 = mul(n1, n1)
return (n2, s23)
In [ ]:
In [ ]:
In [43]:
stack_effects = infer_string('mul mul sub')
for fi, fo in stack_effects:
print doc_from_stack_effect(fi, fo)(n4 n3 n2 n1 -- n5)
In [44]:
def foo(stack):
(n1, (n2, (n3, (n4, s23)))) = stack
n5 = mul(n1, n2)
n6 = mul(n5, n3)
n7 = sub(n6, n4)
return (n7, s23)
# or
def foo(stack):
(n1, (n2, (n3, (n4, s23)))) = stack
n5 = sub(mul(mul(n1, n2), n3), n4)
return (n5, s23)
In [ ]:
In [45]:
stack_effects = infer_string('tuck')
for fi, fo in stack_effects:
print doc_from_stack_effect(fi, fo)(a2 a1 -- a1 a2 a1)
In [ ]:
In [46]:
from joy.parser import SymbolIn [47]:
def _names():
n = 0
while True:
yield Symbol('a' + str(n))
n += 1
names = _names().nextIn [80]:
class Foo(object):
def __init__(self, name):
self.name = name
def __call__(self, stack, expression, code):
in1, (in0, stack) = stack
out = names()
code.append(('call', out, self.name, (in0, in1)))
return (out, stack), expression, codeIn [64]:
def I(stack, expression, code):
while expression:
term, expression = expression
if callable(term):
stack, expression, _ = term(stack, expression, code)
else:
stack = term, stack
code.append(('pop', term))
s = []
while stack:
term, stack = stack
s.insert(0, term)
if s:
code.append(('push',) + tuple(s))
return codeIn [50]:
strtup = lambda a, b: '(%s, %s)' % (b, a)
strstk = lambda rest: reduce(strtup, rest, 'stack')
def code_gen(code):
coalesce_pops(code)
lines = []
for t in code:
tag, rest = t[0], t[1:]
if tag == 'pop':
lines.append(strstk(rest) + ' = stack')
elif tag == 'push':
lines.append('stack = ' + strstk(rest))
elif tag == 'call':
#out, name, in_ = rest
lines.append('%s = %s%s' % rest)
else:
raise ValueError(tag)
return '\n'.join(' ' + line for line in lines)
def coalesce_pops(code):
index = [i for i, t in enumerate(code) if t[0] == 'pop']
for start, end in yield_groups(index):
code[start:end] = \
[tuple(['pop'] + [t for _, t in code[start:end][::-1]])]
def yield_groups(index):
'''
Yield slice indices for each group of contiguous ints in the
index list.
'''
k = 0
for i, (a, b) in enumerate(zip(index, index[1:])):
if b - a > 1:
if k != i:
yield index[k], index[i] + 1
k = i + 1
if k < len(index):
yield index[k], index[-1] + 1
def compile_yinyang(name, expression):
return '''\
def %s(stack):
%s
return stack
''' % (name, code_gen(I((), expression, [])))
In [69]:
mul = Foo('mul')
sub = Foo('sub')In [74]:
def import_yin():
from joy.utils.generated_library import *
return locals()
yin_dict = {name: SimpleFunctionWrapper(func) for name, func in import_yin().iteritems()}
yin_dict
dup = yin_dict['dup']
#def dup(stack, expression, code):
# n, stack = stack
# return (n, (n, stack)), expression<ipython-input-74-a6ea700b09d9>:1: SyntaxWarning: import * only allowed at module level def import_yin():
In [75]:
print compile_yinyang('mul_', (names(), (names(), (mul, ()))))def mul_(stack):
(a31, (a32, stack)) = stack
a33 = mul(a32, a31)
stack = (a33, stack)
return stack
In [76]:
e = (names(), (dup, (mul, ())))
print compile_yinyang('sqr', e)def sqr(stack):
(a34, stack) = stack
a35 = mul(a34, a34)
stack = (a35, stack)
return stack
In [77]:
e = (names(), (dup, (names(), (sub, (mul, ())))))
print compile_yinyang('foo', e)def foo(stack):
(a36, (a37, stack)) = stack
a38 = sub(a37, a36)
a39 = mul(a38, a36)
stack = (a39, stack)
return stack
In [78]:
e = (names(), (names(), (mul, (dup, (sub, (dup, ()))))))
print compile_yinyang('bar', e)def bar(stack):
(a40, (a41, stack)) = stack
a42 = mul(a41, a40)
a43 = sub(a42, a42)
stack = (a43, (a43, stack))
return stack
In [79]:
e = (names(), (dup, (dup, (mul, (dup, (mul, (mul, ())))))))
print compile_yinyang('to_the_fifth_power', e)def to_the_fifth_power(stack):
(a44, stack) = stack
a45 = mul(a44, a44)
a46 = mul(a45, a45)
a47 = mul(a46, a44)
stack = (a47, stack)
return stack
In [ ]:
In [ ]:
In [ ]:
In [ ]: