OSDN Git Service

clearing out cruft
authorSimon Forman <sforman@hushmail.com>
Sun, 11 Sep 2022 18:44:48 +0000 (11:44 -0700)
committerSimon Forman <sforman@hushmail.com>
Sun, 11 Sep 2022 18:45:46 +0000 (11:45 -0700)
implementations/Python/generated_library.py [moved from implementations/Python/joy/utils/generated_library.py with 100% similarity]
implementations/Python/joy/joy.py [deleted file]
implementations/Python/joy/library.py
implementations/Python/joy/parser.py [deleted file]
implementations/Python/joy/utils/errors.py [deleted file]
implementations/Python/joy/utils/stack.py [deleted file]

diff --git a/implementations/Python/joy/joy.py b/implementations/Python/joy/joy.py
deleted file mode 100644 (file)
index 76fc8f9..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#    Copyright © 2014, 2015, 2017, 2018 Simon Forman
-#
-#    This file is part of Thun
-#
-#    Thun is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    Thun is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with Thun.  If not see <http://www.gnu.org/licenses/>.
-#
-'''
-This module implements an interpreter for a dialect of Joy that
-attempts to stay very close to the spirit of Joy but does not precisely
-match the behaviour of the original version(s) written in C.
-
-'''
-from builtins import input
-from traceback import print_exc
-from joy.parser import text_to_expression, ParseError, Symbol
-from joy.utils.stack import stack_to_string
-from joy.utils.errors import (
-    NotAListError,
-    NotAnIntError,
-    StackUnderflowError,
-    )
-
-
-class UnknownSymbolError(KeyError): pass
-
-
-def joy(stack, expression, dictionary, viewer=None):
-    '''
-    Evaluate a Joy expression on a stack.
-
-    This function iterates through a sequence of terms which are either
-    literals (strings, numbers, sequences of terms) or function symbols.
-    Literals are put onto the stack and functions are looked up in the
-    dictionary and executed.
-
-    The viewer is a function that is called with the stack and expression
-    on every iteration, its return value is ignored.
-
-    :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:
-
-        if viewer: viewer(stack, expression)
-
-        term, expression = expression
-        if isinstance(term, Symbol):
-            if term not in dictionary:
-                raise UnknownSymbolError(term)
-            func = dictionary[term]
-            stack, expression, dictionary = func(stack, expression, dictionary)
-        else:
-            stack = term, stack
-
-    if viewer: viewer(stack, expression)
-    return stack, expression, dictionary
-
-
-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)
-
-
-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 = {}
-    try:
-        while True:
-            print()
-            print(stack_to_string(stack), '<-top')
-            print()
-            try:
-                text = input('joy? ')
-            except (EOFError, KeyboardInterrupt):
-                break
-            try:
-                stack, _, dictionary = run(text, stack, dictionary)
-            except:
-                print_exc()
-    except:
-        print_exc()
-    print()
-    return stack
-
-
-def interp(stack=(), dictionary=None):
-    '''
-    Simple REPL with no extra output, suitable for use in scripts.
-    '''
-    if dictionary is None:
-        dictionary = {}
-    try:
-        while True:
-            try:
-                text = input()
-            except (EOFError, KeyboardInterrupt):
-                break
-            try:
-                stack, _, dictionary = run(text, stack, dictionary)
-            except UnknownSymbolError as sym:
-                print('Unknown:', sym)
-            except StackUnderflowError as e:
-                print(e)  # 'Not enough values on stack.'
-            except NotAnIntError:
-                print('Not an integer.')
-            except NotAListError as e:
-                print(e)
-            except:
-                print_exc()
-            print(stack_to_string(stack))
-    except:
-        print_exc()
-    return stack
index f556f73..6cd5e0c 100644 (file)
-# -*- coding: utf-8 -*-
-#
-#    Copyright © 2014-2020 Simon Forman
-#
-#    This file is part of Thun
-#
-#    Thun is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    Thun is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with Thun.  If not see <http://www.gnu.org/licenses/>. 
-#
-'''
-This module contains the Joy function infrastructure and a library of
-functions.  Its main export is a Python function initialize() that
-returns a dictionary of Joy functions suitable for use with the joy()
-function.
-'''
-from pkg_resources import resource_stream
-from io import TextIOWrapper
-from inspect import getdoc, getmembers, isfunction
-from functools import wraps
-from itertools import count
-import operator, math
-
-from . import __name__ as _joy_package_name
-from .parser import text_to_expression, Symbol
-from .utils import generated_library as genlib
-from .utils.errors import (
-    NotAListError,
-    NotAnIntError,
-    StackUnderflowError,
-    )
-from .utils.stack import (
-    concat,
-    expression_to_string,
-    iter_stack,
-    list_to_stack,
-    pick,
-    )
-
-
-def default_defs(dictionary):
-    def_stream = TextIOWrapper(
-        resource_stream(_joy_package_name, 'defs.txt'),
-        encoding='UTF_8',
-        )
-    Def.load_definitions(def_stream, dictionary)
-
-
-HELP_TEMPLATE = '''\
-
-==== Help on %s ====
-
-%s
-
----- end ( %s )
-'''
-
-
-# This is the main dict we're building.
-_dictionary = {}
-
-
-def inscribe(function, d=_dictionary):
-    '''A decorator to inscribe functions into the default dictionary.'''
-    d[function.name] = function
-    return function
-
-
-def initialize():
-    '''Return a dictionary of Joy functions for use with joy().'''
-    return _dictionary.copy()
-
-
 ALIASES = (
-    ('add', ['+']),
-    ('and', ['&']),
     ('bool', ['truthy']),
-    ('mul', ['*']),
-    ('floordiv', ['/floor', '//', '/', 'div']),
     ('mod', ['%', 'rem', 'remainder', 'modulus']),
-    ('eq', ['=']),
-    ('ge', ['>=']),
     ('getitem', ['pick', 'at']),
-    ('gt', ['>']),
-    ('le', ['<=']),
-    ('lshift', ['<<']),
-    ('lt', ['<']),
-    ('ne', ['<>', '!=']),
-    ('rshift', ['>>']),
-    ('sub', ['-']),
     ('xor', ['^']),
-    ('succ', ['++']),
-    ('pred', ['--']),
-    ('rolldown', ['roll<']),
-    ('rollup', ['roll>']),
     ('eh', ['?']),
     ('id', [u'•']),
     )
 
-
-def add_aliases(D, A):
-    '''
-    Given a dict and a iterable of (name, [alias, ...]) pairs, create
-    additional entries in the dict mapping each alias to the named function
-    if it's in the dict.  Aliases for functions not in the dict are ignored.
-    '''
-    for name, aliases in A:
-        try:
-            F = D[name]
-        except KeyError:
-            continue
-        for alias in aliases:
-            D[alias] = F
-
-
-def FunctionWrapper(f):
-    '''Set name attribute.'''
-    if not f.__doc__:
-        raise ValueError('Function %s must have doc string.' % f.__name__)
-    f.name = f.__name__.rstrip('_')  # Don't shadow builtins.
-    return f
-
-
-def SimpleFunctionWrapper(f):
-    '''
-    Wrap functions that take and return just a stack.
-    '''
-    @FunctionWrapper
-    @wraps(f)
-    def inner(stack, expression, dictionary):
-        return f(stack), expression, dictionary
-    return inner
-
-
-def BinaryMathWrapper(f):
-    '''
-    Wrap functions that take two numbers and return a single result.
-    '''
-    @FunctionWrapper
-    @wraps(f)
-    def inner(stack, expression, dictionary):
-        try:
-            (a, (b, stack)) = stack
-        except ValueError:
-            raise StackUnderflowError('Not enough values on stack.')
-        if (   not isinstance(a, int)
-            or not isinstance(b, int)
-            # bool is int in Python.
-            or     isinstance(a, bool)
-            or     isinstance(b, bool)
-            ):
-            raise NotAnIntError
-        result = f(b, a)
-        return (result, stack), expression, dictionary
-    return inner
-
-
-def BinaryLogicWrapper(f):
-    '''
-    Wrap functions that take two numbers and return a single result.
-    '''
-    @FunctionWrapper
-    @wraps(f)
-    def inner(stack, expression, dictionary):
-        try:
-            (a, (b, stack)) = stack
-        except ValueError:
-            raise StackUnderflowError('Not enough values on stack.')
-##        if (not isinstance(a, bool)
-##            or not isinstance(b, bool)
-##            ):
-##            raise NotABoolError
-        result = f(b, a)
-        return (result, stack), expression, dictionary
-    return inner
-
-
-def UnaryBuiltinWrapper(f):
-    '''
-    Wrap functions that take one argument and return a single result.
-    '''
-    @FunctionWrapper
-    @wraps(f)
-    def inner(stack, expression, dictionary):
-        (a, stack) = stack
-        result = f(a)
-        return (result, stack), expression, dictionary
-    return inner
-
-
-class Def(object):
-    '''
-    Definitions created by inscribe.
-    '''
-
-    def __init__(self, name, body):
-        self.name = name
-        self.body = body
-        self._body = tuple(iter_stack(body))
-        self.__doc__ = expression_to_string(body)
-        self._compiled = None
-
-    def __call__(self, stack, expression, dictionary):
-        if self._compiled:
-            return self._compiled(stack, expression, dictionary)  # pylint: disable=E1102
-        expression = list_to_stack(self._body, expression)
-        return stack, expression, dictionary
-
-    @classmethod
-    def load_definitions(class_, stream, dictionary):
-        for line in stream:
-            if line.lstrip().startswith('#'):
-                continue
-            name, body = text_to_expression(line)
-            if name not in dictionary:
-                inscribe(class_(name, body), dictionary)
-##            inscribe(class_(name, body), dictionary)
-
-
-#
-# Functions
-#
-
-
 @inscribe
 @FunctionWrapper
 def inscribe_(stack, expression, dictionary):
@@ -247,16 +23,6 @@ def inscribe_(stack, expression, dictionary):
     return stack, expression, dictionary
 
 
-# @inscribe
-# @SimpleFunctionWrapper
-# def infer_(stack):
-#     '''Attempt to infer the stack effect of a Joy expression.'''
-#     E, stack = stack
-#     effects = infer_expression(E)
-#     e = list_to_stack([(fi, (fo, ())) for fi, fo in effects])
-#     return e, stack
-
-
 @inscribe
 @SimpleFunctionWrapper
 def getitem(stack):
@@ -464,21 +230,6 @@ def sort_(S):
 
 @inscribe
 @SimpleFunctionWrapper
-def clear(stack):
-    '''Clear everything from the stack.
-    ::
-
-        clear == stack [pop stack] loop
-
-           ... clear
-        ---------------
-
-    '''
-    return ()
-
-
-@inscribe
-@SimpleFunctionWrapper
 def disenstacken(stack):
     '''
     The disenstacken operator expects a list on top of the stack and makes that
@@ -505,22 +256,6 @@ def reverse(S):
 
 @inscribe
 @SimpleFunctionWrapper
-def concat_(S):
-    '''
-    Concatinate the two lists on the top of the stack.
-    ::
-
-           [a b c] [d e f] concat
-        ----------------------------
-               [a b c d e f]
-
-    '''
-    (tos, (second, stack)) = S
-    return concat(second, tos), stack
-
-
-@inscribe
-@SimpleFunctionWrapper
 def shunt(stack):
     '''
     Like concat but reverses the top list into the second.
@@ -607,26 +342,6 @@ def divmod_(S):
     return r, (q, stack)
 
 
-def sqrt(a):
-    '''
-    Return the square root of the number a.
-    Negative numbers return complex roots.
-    '''
-    try:
-        r = math.sqrt(a)
-    except ValueError:
-        assert a < 0, repr(a)
-        r = math.sqrt(-a) * 1j
-    return r
-
-
-#def execute(S):
-#  (text, stack) = S
-#  if isinstance(text, str):
-#    return run(text, stack)
-#  return stack
-
-
 @inscribe
 @SimpleFunctionWrapper
 def id_(stack):
@@ -634,31 +349,6 @@ def id_(stack):
     return stack
 
 
-@inscribe
-@SimpleFunctionWrapper
-def void(stack):
-    '''True if the form on TOS is void otherwise False.'''
-    form, stack = stack
-    return _void(form), stack
-
-
-def _void(form):
-    return any(not _void(i) for i in iter_stack(form))
-
-
-
-##  transpose
-##  sign
-##  take
-
-
-@inscribe
-@FunctionWrapper
-def words(stack, expression, dictionary):
-    '''Print all the words in alphabetical order.'''
-    print(' '.join(sorted(dictionary)))
-    return stack, expression, dictionary
-
 
 @inscribe
 @FunctionWrapper
@@ -693,35 +383,6 @@ def warranty(stack, expression, dictionary):
     return stack, expression, dictionary
 
 
-# def simple_manual(stack):
-#   '''
-#   Print words and help for each word.
-#   '''
-#   for name, f in sorted(FUNCTIONS.items()):
-#     d = getdoc(f)
-#     boxline = '+%s+' % ('-' * (len(name) + 2))
-#     print('\n'.join((
-#       boxline,
-#       '| %s |' % (name,),
-#       boxline,
-#       d if d else '   ...',
-#       '',
-#       '--' * 40,
-#       '',
-#       )))
-#   return stack
-
-
-@inscribe
-@FunctionWrapper
-def help_(S, expression, dictionary):
-    '''Accepts a quoted symbol on the top of the stack and prints its docs.'''
-    ((symbol, _), stack) = S
-    word = dictionary[symbol]
-    print(HELP_TEMPLATE % (symbol, getdoc(word), symbol))
-    return stack, expression, dictionary
-
-
 #
 # § Combinators
 #
@@ -1347,48 +1008,8 @@ def cmp_(stack, expression, dictionary):
 #  FunctionWrapper(while_),
 
 
-for F in (
-
-    #divmod_ = pm = __(n2, n1), __(n4, n3)
-
-    BinaryMathWrapper(operator.eq),
-    BinaryMathWrapper(operator.ge),
-    BinaryMathWrapper(operator.gt),
-    BinaryMathWrapper(operator.le),
-    BinaryMathWrapper(operator.lt),
-    BinaryMathWrapper(operator.ne),
-
-    BinaryMathWrapper(operator.xor),
-    BinaryMathWrapper(operator.lshift),
-    BinaryMathWrapper(operator.rshift),
-
-    BinaryLogicWrapper(operator.and_),
-    BinaryLogicWrapper(operator.or_),
-
-    BinaryMathWrapper(operator.add),
-    BinaryMathWrapper(operator.floordiv),
-    BinaryMathWrapper(operator.mod),
-    BinaryMathWrapper(operator.mul),
-    BinaryMathWrapper(operator.pow),
-    BinaryMathWrapper(operator.sub),
-##    BinaryMathWrapper(operator.truediv),
-
-    UnaryBuiltinWrapper(bool),
-    UnaryBuiltinWrapper(operator.not_),
-
-    UnaryBuiltinWrapper(abs),
-    UnaryBuiltinWrapper(operator.neg),
-    UnaryBuiltinWrapper(sqrt),
-
-    UnaryBuiltinWrapper(floor),
-    UnaryBuiltinWrapper(round),
-    ):
-    inscribe(F)
-del F  # Otherwise Sphinx autodoc will pick it up.
-
 
 for name, primitive in getmembers(genlib, isfunction):
     inscribe(SimpleFunctionWrapper(primitive))
 
 
-add_aliases(_dictionary, ALIASES)
diff --git a/implementations/Python/joy/parser.py b/implementations/Python/joy/parser.py
deleted file mode 100644 (file)
index 4b6f2f0..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#    Copyright © 2014, 2015, 2016, 2017 Simon Forman
-#
-#    This file is part of Thun.
-#
-#    Thun is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    Thun is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with Thun.  If not see <http://www.gnu.org/licenses/>.
-#
-'''
-This module exports a single function for converting text to a joy
-expression as well as a single Symbol class and a single Exception type.
-
-The Symbol string class is used by the interpreter to recognize literals
-by the fact that they are not Symbol objects.
-
-A crude grammar::
-
-    joy = term*
-    term = integer | '[' joy ']' | symbol
-
-A Joy expression is a sequence of zero or more terms.  A term is a
-literal value (integer or Joy expression) or a function symbol.
-Function symbols are sequences of non-blanks and cannot contain square
-brackets.   Terms must be separated by blanks, which can be omitted
-around square brackets.
-
-'''
-from re import Scanner
-from joy.utils.stack import list_to_stack
-from joy.utils.snippets import (
-    pat as SNIPPETS,
-    from_string,
-    Snippet,
-    )
-
-
-BRACKETS = r'\[|\]'  # Left or right square bracket.
-BLANKS = r'\s+'  # One-or-more blankspace.
-WORDS = (
-    '['  # Character class
-        '^'   # not a
-        '['   # left square bracket nor a
-        '\]'  # right square bracket (escaped so it doesn't close the character class)
-        '\s'  # nor blankspace
-    ']+'  # end character class, one-or-more.
-    )
-
-
-token_scanner = Scanner([
-    (SNIPPETS, lambda _, token: from_string(token)),
-    (BRACKETS, lambda _, token: token),
-    (BLANKS, None),
-    (WORDS, lambda _, token: token),
-    ])
-
-
-class Symbol(str):
-    '''A string class that represents Joy function names.'''
-    __repr__ = str.__str__
-
-
-def text_to_expression(text):
-    '''Convert a string to a Joy expression.
-
-    When supplied with a string this function returns a Python datastructure
-    that represents the Joy datastructure described by the text expression.
-    Any unbalanced square brackets will raise a ParseError.
-
-    :param str text: Text to convert.
-    :rtype: stack
-    :raises ParseError: if the parse fails.
-    '''
-    return _parse(_tokenize(text))
-
-
-class ParseError(ValueError):
-    '''Raised when there is a error while parsing text.'''
-
-
-def _tokenize(text):
-    '''Convert a text into a stream of tokens.
-
-    Converts function names to Symbols.
-
-    Raise ParseError (with some of the failing text) if the scan fails.
-    '''
-    tokens, rest = token_scanner.scan(text)
-    if rest:
-        raise ParseError(
-            'Scan failed at position %i, %r'
-            % (len(text) - len(rest), rest[:10])
-            )
-    return tokens
-
-
-def _parse(tokens):
-    '''
-    Return a stack/list expression of the tokens.
-    '''
-    frame = []
-    stack = []
-    for tok in tokens:
-        if tok == '[':
-            stack.append(frame)
-            frame = []
-        elif tok == ']':
-            v = frame
-            try: frame = stack.pop()
-            except IndexError:
-                raise ParseError('Extra closing bracket.') from None
-            frame.append(list_to_stack(v))
-        elif tok == 'true': frame.append(True)
-        elif tok == 'false': frame.append(False)
-        elif isinstance(tok, Snippet): frame.append(tok)
-        else:
-            try: thing = int(tok)
-            except ValueError: thing = Symbol(tok)
-            frame.append(thing)
-    if stack: raise ParseError('Unclosed bracket.')
-    return list_to_stack(frame)
diff --git a/implementations/Python/joy/utils/errors.py b/implementations/Python/joy/utils/errors.py
deleted file mode 100644 (file)
index 4834ad3..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-class NotAListError(Exception): pass
-class NotAnIntError(Exception): pass
-class StackUnderflowError(Exception): pass
-
-
diff --git a/implementations/Python/joy/utils/stack.py b/implementations/Python/joy/utils/stack.py
deleted file mode 100644 (file)
index c722bf4..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#    Copyright © 2014, 2015, 2017 Simon Forman
-#
-#    This file is part of Thun
-#
-#    Thun is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    Thun is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with Thun.  If not see <http://www.gnu.org/licenses/>.
-#
-'''
-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.
-
-For example::
-
-    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
-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
-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
-
-'''
-from .errors import NotAListError
-from .snippets import Snippet, to_string as snip_to_string
-
-
-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 stack_to_string(stack):
-    '''
-    Return a "pretty print" string for a 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)
-
-
-def expression_to_string(expression):
-    '''
-    Return a "pretty print" string for a 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)
-
-
-JOY_BOOL_LITERALS = 'false', 'true'
-
-
-def _joy_repr(thing):
-    if isinstance(thing, bool): return JOY_BOOL_LITERALS[thing]
-    if isinstance(thing, Snippet): return snip_to_string(thing)
-    return repr(thing)
-
-
-def _to_string(stack, f):
-    if not isinstance(stack, tuple): return _joy_repr(stack)
-    if not stack: return ''  # shortcut
-    if isinstance(stack, Snippet): return snip_to_string(stack)
-    return ' '.join(map(_s, f(stack)))
-
-
-_s = lambda s: (
-    '[%s]' % expression_to_string(s)
-        if isinstance(s, tuple)
-        and not isinstance(s, Snippet)
-        # Is it worth making a non-tuple class for Snippet?
-        # Doing this check on each tuple seems a bit much.
-    else _joy_repr(s)
-    )
-
-
-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 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.)
-
-    if not isinstance(quote, tuple):
-        raise NotAListError('Not a list.')
-    temp = []
-    while quote:
-        item, quote = quote
-        temp.append(item)
-    for item in reversed(temp):
-        expression = item, expression
-    return expression
-
-
-
-def dnd(stack, from_index, to_index):
-    '''
-    Given a stack and two indices return a rearranged stack.
-    First remove the item at from_index and then insert it at to_index,
-    the second index is relative to the stack after removal of the item
-    at from_index.
-
-    This function reuses all of the items and as much of the stack as it
-    can.  It's meant to be used by remote clients to support drag-n-drop
-    rearranging of the stack from e.g. the StackListbox.
-    '''
-    assert 0 <= from_index
-    assert 0 <= to_index
-    if from_index == to_index:
-        return stack
-    head, n = [], from_index
-    while True:
-        item, stack = stack
-        n -= 1
-        if n < 0:
-            break
-        head.append(item)
-    assert len(head) == from_index
-    # now we have two cases:
-    diff = from_index - to_index
-    if diff < 0:
-        # from < to
-        # so the destination index is still in the stack
-        while diff:
-            h, stack = stack
-            head.append(h)
-            diff += 1
-    else:
-        # from > to
-        # so the destination is in the head list
-        while diff:
-            stack = head.pop(), stack
-            diff -= 1
-    stack = item, stack
-    while head:
-        stack = head.pop(), stack
-    return stack
-
-
-def pick(stack, n):
-    '''
-    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