move stack code up under interp & minor edits
This commit is contained in:
parent
20c4b90298
commit
d7f047cee6
|
|
@ -75,6 +75,141 @@ def joy(stack, expr, dictionary):
|
||||||
return stack, expr, dictionary
|
return stack, expr, dictionary
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
███████╗████████╗ █████╗ ██████╗██╗ ██╗
|
||||||
|
██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
|
||||||
|
███████╗ ██║ ███████║██║ █████╔╝
|
||||||
|
╚════██║ ██║ ██╔══██║██║ ██╔═██╗
|
||||||
|
███████║ ██║ ██║ ██║╚██████╗██║ ██╗
|
||||||
|
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
||||||
|
|
||||||
|
When talking about Joy we use the terms "stack", "quote", "sequence",
|
||||||
|
"list", and others to mean the same thing: a simple linear datatype that
|
||||||
|
permits certain operations such as iterating and pushing and popping
|
||||||
|
values from (at least) one end.
|
||||||
|
|
||||||
|
In describing Joy I have used the term quotation to describe all of the
|
||||||
|
above, because I needed a word to describe the arguments to combinators
|
||||||
|
which fulfill the same role in Joy as lambda abstractions (with
|
||||||
|
variables) fulfill in the more familiar functional languages. I use the
|
||||||
|
term list for those quotations whose members are what I call literals:
|
||||||
|
numbers, characters, truth values, sets, strings and other quotations.
|
||||||
|
All these I call literals because their occurrence in code results in
|
||||||
|
them being pushed onto the stack. But I also call [London Paris] a list.
|
||||||
|
So, [dup *] is a quotation but not a list.
|
||||||
|
|
||||||
|
`"A Conversation with Manfred von Thun" w/ Stevan Apter <http://archive.vector.org.uk/art10000350>`_
|
||||||
|
|
||||||
|
There is no "Stack" Python class, instead we use the `cons list`_, a
|
||||||
|
venerable two-tuple recursive sequence datastructure, where the empty
|
||||||
|
tuple ``()`` is the empty stack and ``(head, rest)`` gives the recursive
|
||||||
|
form of a stack with one or more items on it::
|
||||||
|
|
||||||
|
stack := () | (item, stack)
|
||||||
|
|
||||||
|
Putting some numbers onto a stack::
|
||||||
|
|
||||||
|
Joy Python
|
||||||
|
[] ()
|
||||||
|
[1] (1, ())
|
||||||
|
[2 1] (2, (1, ()))
|
||||||
|
[3 2 1] (3, (2, (1, ())))
|
||||||
|
...
|
||||||
|
|
||||||
|
Python has very nice "tuple packing and unpacking" in its syntax which
|
||||||
|
means we can directly "unpack" the expected arguments to a Joy function.
|
||||||
|
We assign the argument stack to the expected structure of the stack and
|
||||||
|
Python takes care of unpacking the incoming tuple and assigning values to
|
||||||
|
the names. (Note that Python syntax doesn't require parentheses around
|
||||||
|
tuples used in expressions where they would be redundant.)
|
||||||
|
|
||||||
|
def dup(stack):
|
||||||
|
head, tail = stack
|
||||||
|
return head, (head, tail)
|
||||||
|
|
||||||
|
|
||||||
|
.. _cons list: https://en.wikipedia.org/wiki/Cons#Lists
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def list_to_stack(el, stack=()):
|
||||||
|
'''
|
||||||
|
Convert a Python list (or other sequence) to a Joy stack::
|
||||||
|
|
||||||
|
[1, 2, 3] -> (1, (2, (3, ())))
|
||||||
|
|
||||||
|
:param list el: A Python list or other sequence (iterators and generators
|
||||||
|
won't work because ``reversed()`` is called on ``el``.)
|
||||||
|
:param stack stack: A stack, optional, defaults to the empty stack. This
|
||||||
|
allows for concatinating Python lists (or other sequence objects)
|
||||||
|
onto an existing Joy stack.
|
||||||
|
:rtype: stack
|
||||||
|
|
||||||
|
'''
|
||||||
|
for item in reversed(el):
|
||||||
|
stack = item, stack
|
||||||
|
return stack
|
||||||
|
|
||||||
|
|
||||||
|
def iter_stack(stack):
|
||||||
|
'''
|
||||||
|
Iterate through the items on the stack.
|
||||||
|
|
||||||
|
:param stack stack: A stack.
|
||||||
|
:rtype: iterator
|
||||||
|
'''
|
||||||
|
while stack:
|
||||||
|
item, stack = stack
|
||||||
|
yield item
|
||||||
|
|
||||||
|
|
||||||
|
def concat(quote, expression):
|
||||||
|
'''
|
||||||
|
Concatinate quote onto expression.
|
||||||
|
|
||||||
|
In joy [1 2] [3 4] would become [1 2 3 4].
|
||||||
|
|
||||||
|
:param stack quote: A stack.
|
||||||
|
:param stack expression: A stack.
|
||||||
|
:rtype: stack
|
||||||
|
'''
|
||||||
|
isnt_stack(quote)
|
||||||
|
isnt_stack(expression)
|
||||||
|
return list_to_stack(list(iter_stack(quote)), expression)
|
||||||
|
|
||||||
|
## return (quote[0], concat(quote[1], expression)) if quote else expression
|
||||||
|
# :raises RuntimeError: if quote is larger than sys.getrecursionlimit().
|
||||||
|
# This is the fastest implementation but it would trigger
|
||||||
|
# RuntimeError: maximum recursion depth exceeded
|
||||||
|
# on quotes longer than sys.getrecursionlimit().
|
||||||
|
|
||||||
|
|
||||||
|
def get_n_items(n, stack):
|
||||||
|
'''
|
||||||
|
Return items and remainder of stack.
|
||||||
|
Raise StackUnderflowError if there are fewer than n items on the stack.
|
||||||
|
'''
|
||||||
|
assert n > 0, repr(n)
|
||||||
|
temp = []
|
||||||
|
while n > 0:
|
||||||
|
n -= 1
|
||||||
|
try:
|
||||||
|
item, stack = stack
|
||||||
|
except ValueError:
|
||||||
|
raise StackUnderflowError('Not enough values on stack.') from None
|
||||||
|
temp.append(item)
|
||||||
|
temp.append(stack)
|
||||||
|
return tuple(temp)
|
||||||
|
|
||||||
|
|
||||||
|
def reversed_stack(stack):
|
||||||
|
'''
|
||||||
|
Return list_reverseiterator object for a stack.
|
||||||
|
'''
|
||||||
|
return reversed(list(iter_stack(stack)))
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
██████╗ █████╗ ██████╗ ███████╗███████╗██████╗
|
██████╗ █████╗ ██████╗ ███████╗███████╗██████╗
|
||||||
██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗
|
██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗
|
||||||
|
|
@ -196,160 +331,6 @@ def _parse(tokens):
|
||||||
return list_to_stack(frame)
|
return list_to_stack(frame)
|
||||||
|
|
||||||
|
|
||||||
r'''
|
|
||||||
███████╗████████╗ █████╗ ██████╗██╗ ██╗
|
|
||||||
██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
|
|
||||||
███████╗ ██║ ███████║██║ █████╔╝
|
|
||||||
╚════██║ ██║ ██╔══██║██║ ██╔═██╗
|
|
||||||
███████║ ██║ ██║ ██║╚██████╗██║ ██╗
|
|
||||||
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
|
||||||
|
|
||||||
When talking about Joy we use the terms "stack", "quote", "sequence",
|
|
||||||
"list", and others to mean the same thing: a simple linear datatype that
|
|
||||||
permits certain operations such as iterating and pushing and popping
|
|
||||||
values from (at least) one end.
|
|
||||||
|
|
||||||
In describing Joy I have used the term quotation to describe all of the
|
|
||||||
above, because I needed a word to describe the arguments to combinators
|
|
||||||
which fulfill the same role in Joy as lambda abstractions (with
|
|
||||||
variables) fulfill in the more familiar functional languages. I use the
|
|
||||||
term list for those quotations whose members are what I call literals:
|
|
||||||
numbers, characters, truth values, sets, strings and other quotations.
|
|
||||||
All these I call literals because their occurrence in code results in
|
|
||||||
them being pushed onto the stack. But I also call [London Paris] a list.
|
|
||||||
So, [dup \*] is a quotation but not a list.
|
|
||||||
|
|
||||||
`"A Conversation with Manfred von Thun" w/ Stevan Apter <http://archive.vector.org.uk/art10000350>`_
|
|
||||||
|
|
||||||
There is no "Stack" Python class, instead we use the `cons list`_, a
|
|
||||||
venerable two-tuple recursive sequence datastructure, where the
|
|
||||||
empty tuple ``()`` is the empty stack and ``(head, rest)`` gives the
|
|
||||||
recursive form of a stack with one or more items on it::
|
|
||||||
|
|
||||||
stack := () | (item, stack)
|
|
||||||
|
|
||||||
Putting some numbers onto a stack::
|
|
||||||
|
|
||||||
()
|
|
||||||
(1, ())
|
|
||||||
(2, (1, ()))
|
|
||||||
(3, (2, (1, ())))
|
|
||||||
...
|
|
||||||
|
|
||||||
Python has very nice "tuple packing and unpacking" in its syntax which
|
|
||||||
means we can directly "unpack" the expected arguments to a Joy function.
|
|
||||||
We assign the argument stack to the expected structure of the stack and
|
|
||||||
Python takes care of unpacking the
|
|
||||||
incoming tuple and assigning values to the names. (Note that Python
|
|
||||||
syntax doesn't require parentheses around tuples used in expressions
|
|
||||||
where they would be redundant.)
|
|
||||||
|
|
||||||
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
|
|
||||||
list and another to iterate through a stack and yield its items
|
|
||||||
one-by-one in order. There are also two functions to generate string representations
|
|
||||||
of stacks. They only differ in that one prints the terms in stack from left-to-right while the other prints from right-to-left. In both functions *internal stacks* are
|
|
||||||
printed left-to-right. These functions are written to support :doc:`../pretty`.
|
|
||||||
|
|
||||||
.. _cons list: https://en.wikipedia.org/wiki/Cons#Lists
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def list_to_stack(el, stack=()):
|
|
||||||
'''
|
|
||||||
Convert a Python list (or other sequence) to a Joy stack::
|
|
||||||
|
|
||||||
[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. This
|
|
||||||
allows for concatinating Python lists (or other sequence objects)
|
|
||||||
onto an existing Joy stack.
|
|
||||||
:rtype: stack
|
|
||||||
|
|
||||||
'''
|
|
||||||
for item in reversed(el):
|
|
||||||
stack = item, stack
|
|
||||||
return stack
|
|
||||||
|
|
||||||
|
|
||||||
def iter_stack(stack):
|
|
||||||
'''
|
|
||||||
Iterate through the items on the stack.
|
|
||||||
|
|
||||||
:param stack stack: A stack.
|
|
||||||
:rtype: iterator
|
|
||||||
'''
|
|
||||||
while stack:
|
|
||||||
item, stack = stack
|
|
||||||
yield item
|
|
||||||
|
|
||||||
|
|
||||||
def concat(quote, expression):
|
|
||||||
'''
|
|
||||||
Concatinate quote onto expression.
|
|
||||||
|
|
||||||
In joy [1 2] [3 4] would become [1 2 3 4].
|
|
||||||
|
|
||||||
:param stack quote: A stack.
|
|
||||||
:param stack expression: A stack.
|
|
||||||
:rtype: stack
|
|
||||||
'''
|
|
||||||
# This (below) is the fastest implementation, but will trigger
|
|
||||||
# RuntimeError: maximum recursion depth exceeded
|
|
||||||
# on quotes longer than sys.getrecursionlimit().
|
|
||||||
# :raises RuntimeError: if quote is larger than sys.getrecursionlimit().
|
|
||||||
|
|
||||||
## return (quote[0], concat(quote[1], expression)) if quote else expression
|
|
||||||
|
|
||||||
# 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.)
|
|
||||||
|
|
||||||
isnt_stack(quote)
|
|
||||||
isnt_stack(expression)
|
|
||||||
temp = []
|
|
||||||
while quote:
|
|
||||||
item, quote = quote
|
|
||||||
temp.append(item)
|
|
||||||
for item in reversed(temp):
|
|
||||||
expression = item, expression
|
|
||||||
return expression
|
|
||||||
|
|
||||||
|
|
||||||
def get_n_items(n, stack):
|
|
||||||
'''
|
|
||||||
Return items and remainder of stack.
|
|
||||||
Raise StackUnderflowError if there are fewer than n items on the stack.
|
|
||||||
'''
|
|
||||||
assert n > 0, repr(n)
|
|
||||||
temp = []
|
|
||||||
while n > 0:
|
|
||||||
n -= 1
|
|
||||||
try:
|
|
||||||
item, stack = stack
|
|
||||||
except ValueError:
|
|
||||||
raise StackUnderflowError('Not enough values on stack.') from None
|
|
||||||
temp.append(item)
|
|
||||||
temp.append(stack)
|
|
||||||
return tuple(temp)
|
|
||||||
|
|
||||||
|
|
||||||
def reversed_stack(stack):
|
|
||||||
'''
|
|
||||||
Return list_reverseiterator object for a stack.
|
|
||||||
'''
|
|
||||||
return reversed(list(iter_stack(stack)))
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗
|
██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗
|
||||||
██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
|
██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue