diff --git a/joy/joy.py b/joy/joy.py
index 901b159..07ed9a6 100644
--- a/joy/joy.py
+++ b/joy/joy.py
@@ -42,11 +42,11 @@ def joy(stack, expression, dictionary, viewer=None):
or functions. Literals are put onto the stack and functions are
executed.
-
- :param quote stack: The stack.
- :param quote expression: The expression to evaluate.
- :param dict dictionary: A `dict` mapping names to Joy functions.
+ :param stack stack: The stack.
+ :param stack expression: The expression to evaluate.
+ :param dict dictionary: A ``dict`` mapping names to Joy functions.
:param function viewer: Optional viewer function.
+ :rtype: (stack, (), dictionary)
'''
while expression:
@@ -67,6 +67,13 @@ def joy(stack, expression, dictionary, viewer=None):
def run(text, stack, dictionary, viewer=None):
'''
Return the stack resulting from running the Joy code text on the stack.
+
+ :param str text: Joy code.
+ :param stack stack: The stack.
+ :param dict dictionary: A ``dict`` mapping names to Joy functions.
+ :param function viewer: Optional viewer function.
+ :rtype: (stack, (), dictionary)
+
'''
expression = text_to_expression(text)
return joy(stack, expression, dictionary, viewer)
@@ -77,6 +84,11 @@ def repl(stack=(), dictionary=None):
Read-Evaluate-Print Loop
Accept input and run it on the stack, loop.
+
+ :param stack stack: The stack.
+ :param dict dictionary: A ``dict`` mapping names to Joy functions.
+ :rtype: stack
+
'''
if dictionary is None:
dictionary = {}
diff --git a/joy/parser.py b/joy/parser.py
index e0dd9fc..350bc9c 100644
--- a/joy/parser.py
+++ b/joy/parser.py
@@ -51,7 +51,7 @@ def text_to_expression(text):
Any unbalanced square brackets will raise a ParseError.
:param str text: Text to convert.
- :rtype: quote
+ :rtype: stack
:raises ParseError: if the parse fails.
'''
return _parse(_tokenize(text))
diff --git a/joy/utils/pretty_print.py b/joy/utils/pretty_print.py
index 5f71c01..5151ae1 100644
--- a/joy/utils/pretty_print.py
+++ b/joy/utils/pretty_print.py
@@ -18,7 +18,24 @@
# along with Thun. If not see .
#
'''
-Pretty printing support.
+Pretty printing support, e.g.::
+
+ Joy? 23 18 * 99 +
+ . 23 18 mul 99 add
+ 23 . 18 mul 99 add
+ 23 18 . mul 99 add
+ 414 . 99 add
+ 414 99 . add
+ 513 .
+
+ 513 <-top
+
+ joy?
+
+On each line the stack is printed with the top to the right, then a ``.`` to
+represent the current locus of processing, then the pending expression to the
+left.
+
'''
# (Kinda clunky and hacky. This should be swapped out in favor of much
# smarter stuff.)
@@ -29,29 +46,36 @@ from .stack import expression_to_string, stack_to_string
class TracePrinter(object):
'''
- This is what does the formatting, e.g.::
-
- Joy? 23 18 * 99 +
- . 23 18 mul 99 add
- 23 . 18 mul 99 add
- 23 18 . mul 99 add
- 414 . 99 add
- 414 99 . add
- 513 .
-
+ 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 viewer(self, stack, expression):
- '''Pass this method as the viewer to joy() function.'''
+ '''
+ 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))
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.
+
+ This method is called internally by the ``__str__()`` method.
+
+ :rtype: list(str)
+ '''
max_stack_length = 0
lines = []
for stack, expression in self.history:
diff --git a/joy/utils/stack.py b/joy/utils/stack.py
index 478521d..6bcc5b4 100644
--- a/joy/utils/stack.py
+++ b/joy/utils/stack.py
@@ -18,12 +18,13 @@
# along with Thun. If not see .
#
'''
-When talking about Joy we use the terms "stack", "list", "sequence",
-"quote" and others to mean the same thing: a simple linear datatype that
+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.
-We use the `cons list`_, a venerable two-tuple recursive sequence datastructure, where the
+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::
@@ -51,33 +52,36 @@ 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.)
+Unfortunately, the Sphinx documentation generator, which is used to generate this
+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)
+
+
+We have two very simple functions, one to build up a stack from a Python
+iterable 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
'''
-##We have two very simple functions to build up a stack from a Python
-##iterable and also to iterate through a stack and yield its items
-##one-by-one in order, and two functions to generate string representations
-##of stacks::
-##
-## list_to_stack()
-##
-## iter_stack()
-##
-## expression_to_string() (prints left-to-right)
-##
-## stack_to_string() (prints right-to-left)
-##
-##
-##A word about the stack data structure.
-
-
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.
+ :rtype: stack
+
'''
for item in reversed(el):
stack = item, stack
@@ -85,7 +89,11 @@ def list_to_stack(el, 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
@@ -98,6 +106,9 @@ def stack_to_string(stack):
The items are written right-to-left::
(top, (second, ...)) -> '... second top'
+
+ :param stack stack: A stack.
+ :rtype: str
'''
f = lambda stack: reversed(list(iter_stack(stack)))
return _to_string(stack, f)
@@ -110,6 +121,9 @@ def expression_to_string(expression):
The items are written left-to-right::
(top, (second, ...)) -> 'top second ...'
+
+ :param stack expression: A stack.
+ :rtype: str
'''
return _to_string(expression, iter_stack)
@@ -132,7 +146,16 @@ def pushback(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.
+ :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], pushback(quote[1], expression)) if quote else expression
# Original implementation.
@@ -149,15 +172,17 @@ def pushback(quote, expression):
## expression = item, expression
## return expression
- # This is the fastest, but will trigger
- # RuntimeError: maximum recursion depth exceeded
- # on quotes longer than sys.getrecursionlimit().
- return (quote[0], pushback(quote[1], expression)) if quote else expression
def pick(s, n):
'''
- Find the nth item on the stack. (Pick with zero is the same as "dup".)
+ Return the nth item on the stack.
+
+ :param stack s: 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 ``s``.
+ :rtype: whatever
'''
if n < 0:
raise ValueError