Switch to tabs for indentation.

Instead of a mix of 2- and 4-space tabs just use actual tabs.  ;-P
This commit is contained in:
Simon Forman
2020-04-24 12:48:15 -07:00
parent 2fb610e733
commit 078f29830d
26 changed files with 4080 additions and 4080 deletions
+36 -36
View File
@@ -54,43 +54,43 @@ function name! Hopefully they will discover this documentation.
def rename_code_object(new_name):
'''
If you want to wrap a function in another function and have the wrapped
function's name show up in the traceback when an exception occurs in
the wrapper function, you must do this brutal hackery to change the
func.__code__.co_name attribute. Just functools.wraps() is not enough.
'''
If you want to wrap a function in another function and have the wrapped
function's name show up in the traceback when an exception occurs in
the wrapper function, you must do this brutal hackery to change the
func.__code__.co_name attribute. Just functools.wraps() is not enough.
See:
See:
https://stackoverflow.com/questions/29919804/function-decorated-using-functools-wraps-raises-typeerror-with-the-name-of-the-w
https://stackoverflow.com/questions/29919804/function-decorated-using-functools-wraps-raises-typeerror-with-the-name-of-the-w
https://stackoverflow.com/questions/29488327/changing-the-name-of-a-generator/29488561#29488561
https://stackoverflow.com/questions/29488327/changing-the-name-of-a-generator/29488561#29488561
I'm just glad it's possible.
'''
def inner(func):
name = new_name + ':' + func.__name__
code_object = func.__code__
return type(func)(
type(code_object)(
code_object.co_argcount,
code_object.co_nlocals,
code_object.co_stacksize,
code_object.co_flags,
code_object.co_code,
code_object.co_consts,
code_object.co_names,
code_object.co_varnames,
code_object.co_filename,
name,
code_object.co_firstlineno,
code_object.co_lnotab,
code_object.co_freevars,
code_object.co_cellvars
),
func.__globals__,
name,
func.__defaults__,
func.__closure__
)
return inner
I'm just glad it's possible.
'''
def inner(func):
name = new_name + ':' + func.__name__
code_object = func.__code__
return type(func)(
type(code_object)(
code_object.co_argcount,
code_object.co_nlocals,
code_object.co_stacksize,
code_object.co_flags,
code_object.co_code,
code_object.co_consts,
code_object.co_names,
code_object.co_varnames,
code_object.co_filename,
name,
code_object.co_firstlineno,
code_object.co_lnotab,
code_object.co_freevars,
code_object.co_cellvars
),
func.__globals__,
name,
func.__defaults__,
func.__closure__
)
return inner
+119 -119
View File
@@ -21,49 +21,49 @@ from functools import reduce
def import_yin():
from joy.utils.generated_library import *
return locals()
from joy.utils.generated_library import *
return locals()
class InfiniteStack(tuple):
def _names():
n = 0
while True:
m = yield Symbol('a' + str(n))
n = n + 1 if m is None else m
def _names():
n = 0
while True:
m = yield Symbol('a' + str(n))
n = n + 1 if m is None else m
_NAMES = _names()
next(_NAMES)
_NAMES = _names()
next(_NAMES)
names = lambda: next(_NAMES)
reset = lambda _self, _n=_NAMES: _n.send(-1)
names = lambda: next(_NAMES)
reset = lambda _self, _n=_NAMES: _n.send(-1)
def __init__(self, code):
self.reset()
self.code = code
def __init__(self, code):
self.reset()
self.code = code
def __iter__(self):
if not self:
new_var = self.names()
self.code.append(('pop', new_var))
return iter((new_var, self))
def __iter__(self):
if not self:
new_var = self.names()
self.code.append(('pop', new_var))
return iter((new_var, self))
def I(expression):
code = []
stack = InfiniteStack(code)
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
while expression:
term, expression = expression
if isinstance(term, Symbol):
func = D[term]
stack, expression, _ = func(stack, expression, code)
else:
stack = term, stack
code.append(tuple(['ret'] + list(iter_stack(stack))))
return code
code.append(tuple(['ret'] + list(iter_stack(stack))))
return code
strtup = lambda a, b: '(%s, %s)' % (b, a)
@@ -71,123 +71,123 @@ strstk = lambda rest: reduce(strtup, rest, 'stack')
def code_gen(code):
#for p in code: print p
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[::-1]))
else:
raise ValueError(tag)
return '\n'.join(' ' + line for line in lines)
#for p in code: print p
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[::-1]))
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.
try: index = next((i for i, t in enumerate(code) if t[0] != 'pop'))
except StopIteration: return
code[:index] = [tuple(['pop'] + [t for _, t in code[:index][::-1]])]
code.sort(key=lambda p: p[0] != 'pop') # All pops to the front.
try: index = next((i for i, t in enumerate(code) if t[0] != 'pop'))
except StopIteration: return
code[:index] = [tuple(['pop'] + [t for _, t in code[:index][::-1]])]
def compile_yinyang(name, text):
return '''
return '''
def %s(stack):
%s
''' % (name, code_gen(I(text_to_expression(text))))
def q():
memo = {}
def bar(type_var):
try:
res = memo[type_var]
except KeyError:
res = memo[type_var] = InfiniteStack.names()
return res
return bar
memo = {}
def bar(type_var):
try:
res = memo[type_var]
except KeyError:
res = memo[type_var] = InfiniteStack.names()
return res
return bar
def type_vars_to_labels(thing, map_):
if not thing:
return thing
if not isinstance(thing, tuple):
return map_(thing)
return tuple(type_vars_to_labels(inner, map_) for inner in thing)
if not thing:
return thing
if not isinstance(thing, tuple):
return map_(thing)
return tuple(type_vars_to_labels(inner, map_) for inner in thing)
def remap_inputs(in_, stack, code):
map_ = q()
while in_:
term, in_ = in_
arg0, stack = stack
term = type_vars_to_labels(term, map_)
code.append(('call', term, '', arg0))
return stack, map_
map_ = q()
while in_:
term, in_ = in_
arg0, stack = stack
term = type_vars_to_labels(term, map_)
code.append(('call', term, '', arg0))
return stack, map_
class BinaryBuiltin(object):
def __init__(self, name):
self.name = name
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 __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
YIN = import_yin()
D = {
name: SimpleFunctionWrapper(YIN[name])
for name in '''
ccons
cons
dup
dupd
dupdd
over
pop
popd
popdd
popop
popopd
popopdd
rolldown
rollup
swap
swons
tuck
unit
'''.split()
}
name: SimpleFunctionWrapper(YIN[name])
for name in '''
ccons
cons
dup
dupd
dupdd
over
pop
popd
popdd
popop
popopd
popopdd
rolldown
rollup
swap
swons
tuck
unit
'''.split()
}
for name in '''
first
first_two
fourth
rest
rrest
second
third
uncons
unswons
'''.split():
first
first_two
fourth
rest
rrest
second
third
uncons
unswons
'''.split():
def foo(stack, expression, code, name=name):
in_, out = YIN_STACK_EFFECTS[name]
stack, map_ = remap_inputs(in_, stack, code)
out = type_vars_to_labels(out, map_)
return concat(out, stack), expression, code
def foo(stack, expression, code, name=name):
in_, out = YIN_STACK_EFFECTS[name]
stack, map_ = remap_inputs(in_, stack, code)
out = type_vars_to_labels(out, map_)
return concat(out, stack), expression, code
foo.__name__ = name
D[name] = foo
foo.__name__ = name
D[name] = foo
for name in '''
@@ -210,18 +210,18 @@ for name in '''
sub
truediv
'''.split():
D[name.rstrip('-')] = BinaryBuiltin(name)
D[name.rstrip('-')] = BinaryBuiltin(name)
'''
stack
stuncons
stununcons
swaack
stack
stuncons
stununcons
swaack
'''
for name in sorted(D):
print(name, end=' ')
print(name, end=' ')
## print compile_yinyang(name, name)
print('-' * 100)
+12 -12
View File
@@ -3,19 +3,19 @@ from joy.parser import Symbol
def _names():
n = 0
while True:
yield Symbol('a' + str(n))
n += 1
n = 0
while True:
yield Symbol('a' + str(n))
n += 1
class InfiniteStack(tuple):
names = lambda n=_names(): next(n)
names = lambda n=_names(): next(n)
def __iter__(self):
if not self:
return iter((self.names(), self))
def __iter__(self):
if not self:
return iter((self.names(), self))
i = InfiniteStack()
@@ -23,9 +23,9 @@ i = InfiniteStack()
a, b = i
lambda u: (lambda fu, u: fu * fu * u)(
(lambda u: (lambda fu, u: fu * fu)(
(lambda u: (lambda fu, u: fu * fu * u)(
(lambda u: 1)(u), u))(u), u))(u),
u)
(lambda u: (lambda fu, u: fu * fu)(
(lambda u: (lambda fu, u: fu * fu * u)(
(lambda u: 1)(u), u))(u), u))(u),
u)
lambda u: (lambda fu, u: fu * fu * u)((lambda u: (lambda fu, u: fu * fu)((lambda u: (lambda fu, u: fu * fu * u)((lambda u: 1)(u), u))(u), u))(u), u)
+43 -43
View File
@@ -46,54 +46,54 @@ from .stack import expression_to_string, stack_to_string
class TracePrinter(object):
'''
This is what does the formatting. You instantiate it and pass the ``viewer()``
method to the :py:func:`joy.joy.joy` function, then print it to see the
trace.
'''
'''
This is what does the formatting. You instantiate it and pass the ``viewer()``
method to the :py:func:`joy.joy.joy` function, then print it to see the
trace.
'''
def __init__(self):
self.history = []
def __init__(self):
self.history = []
def viewer(self, stack, expression):
'''
Record the current stack and expression in the TracePrinter's history.
Pass this method as the ``viewer`` argument to the :py:func:`joy.joy.joy` function.
def viewer(self, stack, expression):
'''
Record the current stack and expression in the TracePrinter's history.
Pass this method as the ``viewer`` argument to the :py:func:`joy.joy.joy` function.
:param stack quote: A stack.
:param stack expression: A stack.
'''
self.history.append((stack, expression))
:param stack quote: A stack.
:param stack expression: A stack.
'''
self.history.append((stack, expression))
def __str__(self):
return '\n'.join(self.go())
def __str__(self):
return '\n'.join(self.go())
def go(self):
'''
Return a list of strings, one for each entry in the history, prefixed
with enough spaces to align all the interpreter dots.
def go(self):
'''
Return a list of strings, one for each entry in the history, prefixed
with enough spaces to align all the interpreter dots.
This method is called internally by the ``__str__()`` method.
This method is called internally by the ``__str__()`` method.
:rtype: list(str)
'''
max_stack_length = 0
lines = []
for stack, expression in self.history:
stack = stack_to_string(stack)
expression = expression_to_string(expression)
n = len(stack)
if n > max_stack_length:
max_stack_length = n
lines.append((n, '%s . %s' % (stack, expression)))
return [ # Prefix spaces to line up '.'s.
(' ' * (max_stack_length - length) + line)
for length, line in lines
]
:rtype: list(str)
'''
max_stack_length = 0
lines = []
for stack, expression in self.history:
stack = stack_to_string(stack)
expression = expression_to_string(expression)
n = len(stack)
if n > max_stack_length:
max_stack_length = n
lines.append((n, '%s . %s' % (stack, expression)))
return [ # Prefix spaces to line up '.'s.
(' ' * (max_stack_length - length) + line)
for length, line in lines
]
def print_(self):
try:
print(self)
except:
print_exc()
print('Exception while printing viewer.')
def print_(self):
try:
print(self)
except:
print_exc()
print('Exception while printing viewer.')
+78 -78
View File
@@ -43,8 +43,8 @@ means we can directly "unpack" the expected arguments to a Joy function.
For example::
def dup((head, tail)):
return head, (head, tail)
def dup((head, tail)):
return head, (head, tail)
We replace the argument "stack" by the expected structure of the stack,
in this case "(head, tail)", and Python takes care of unpacking the
@@ -56,9 +56,9 @@ Unfortunately, the Sphinx documentation generator, which is used to generate thi
web page, doesn't handle tuples in the function parameters. And in Python 3, this
syntax was removed entirely. Instead you would have to write::
def dup(stack):
head, tail = stack
return head, (head, tail)
def dup(stack):
head, tail = stack
return head, (head, tail)
We have two very simple functions, one to build up a stack from a Python
@@ -74,95 +74,95 @@ printed left-to-right. These functions are written to support :doc:`../pretty`.
from builtins import map
def list_to_stack(el, stack=()):
'''Convert a Python list (or other sequence) to a Joy stack::
'''Convert a Python list (or other sequence) to a Joy stack::
[1, 2, 3] -> (1, (2, (3, ())))
[1, 2, 3] -> (1, (2, (3, ())))
:param list el: A Python list or other sequence (iterators and generators
won't work because ``reverse()`` is called on ``el``.)
:param stack stack: A stack, optional, defaults to the empty stack.
:rtype: stack
:param list el: A Python list or other sequence (iterators and generators
won't work because ``reverse()`` is called on ``el``.)
:param stack stack: A stack, optional, defaults to the empty stack.
:rtype: stack
'''
for item in reversed(el):
stack = item, stack
return stack
'''
for item in reversed(el):
stack = item, stack
return stack
def iter_stack(stack):
'''Iterate through the items on the stack.
'''Iterate through the items on the stack.
:param stack stack: A stack.
:rtype: iterator
'''
while stack:
item, stack = stack
yield item
:param stack stack: A stack.
:rtype: iterator
'''
while stack:
item, stack = stack
yield item
def stack_to_string(stack):
'''
Return a "pretty print" string for a stack.
'''
Return a "pretty print" string for a stack.
The items are written right-to-left::
The items are written right-to-left::
(top, (second, ...)) -> '... second top'
(top, (second, ...)) -> '... second top'
:param stack stack: A stack.
:rtype: str
'''
f = lambda stack: reversed(list(iter_stack(stack)))
return _to_string(stack, f)
:param stack stack: A stack.
:rtype: str
'''
f = lambda stack: reversed(list(iter_stack(stack)))
return _to_string(stack, f)
def expression_to_string(expression):
'''
Return a "pretty print" string for a expression.
'''
Return a "pretty print" string for a expression.
The items are written left-to-right::
The items are written left-to-right::
(top, (second, ...)) -> 'top second ...'
(top, (second, ...)) -> 'top second ...'
:param stack expression: A stack.
:rtype: str
'''
return _to_string(expression, iter_stack)
:param stack expression: A stack.
:rtype: str
'''
return _to_string(expression, iter_stack)
def _to_string(stack, f):
if not isinstance(stack, tuple): return repr(stack)
if not stack: return '' # shortcut
return ' '.join(map(_s, f(stack)))
if not isinstance(stack, tuple): return repr(stack)
if not stack: return '' # shortcut
return ' '.join(map(_s, f(stack)))
_s = lambda s: (
'[%s]' % expression_to_string(s) if isinstance(s, tuple)
else repr(s)
)
'[%s]' % expression_to_string(s) if isinstance(s, tuple)
else repr(s)
)
def concat(quote, expression):
'''Concatinate quote onto expression.
'''Concatinate quote onto expression.
In joy [1 2] [3 4] would become [1 2 3 4].
In joy [1 2] [3 4] would become [1 2 3 4].
:param stack quote: A stack.
:param stack expression: A stack.
:raises RuntimeError: if quote is larger than sys.getrecursionlimit().
:rtype: stack
'''
# This is the fastest implementation, but will trigger
# RuntimeError: maximum recursion depth exceeded
# on quotes longer than sys.getrecursionlimit().
:param stack quote: A stack.
:param stack expression: A stack.
:raises RuntimeError: if quote is larger than sys.getrecursionlimit().
:rtype: stack
'''
# This is the fastest implementation, but will trigger
# RuntimeError: maximum recursion depth exceeded
# on quotes longer than sys.getrecursionlimit().
return (quote[0], concat(quote[1], expression)) if quote else expression
return (quote[0], concat(quote[1], expression)) if quote else expression
# Original implementation.
# Original implementation.
## return list_to_stack(list(iter_stack(quote)), expression)
# In-lining is slightly faster (and won't break the
# recursion limit on long quotes.)
# In-lining is slightly faster (and won't break the
# recursion limit on long quotes.)
## temp = []
## while quote:
@@ -175,23 +175,23 @@ def concat(quote, expression):
def pick(stack, n):
'''
Return the nth item on the stack.
'''
Return the nth item on the stack.
:param stack stack: A stack.
:param int n: An index into the stack.
:raises ValueError: if ``n`` is less than zero.
:raises IndexError: if ``n`` is equal to or greater than the length of ``stack``.
:rtype: whatever
'''
if n < 0:
raise ValueError
while True:
try:
item, stack = stack
except ValueError:
raise IndexError
n -= 1
if n < 0:
break
return item
:param stack stack: A stack.
:param int n: An index into the stack.
:raises ValueError: if ``n`` is less than zero.
:raises IndexError: if ``n`` is equal to or greater than the length of ``stack``.
:rtype: whatever
'''
if n < 0:
raise ValueError
while True:
try:
item, stack = stack
except ValueError:
raise IndexError
n -= 1
if n < 0:
break
return item
+493 -493
View File
File diff suppressed because it is too large Load Diff