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:
+36
-36
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user