Source code for joy.joy

# -*- 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 __future__ import print_function
try:
  input = raw_input
except NameError:
  pass
from traceback import print_exc, format_exc
from .parser import text_to_expression, ParseError, Symbol
from .utils.stack import stack_to_string
from .utils.pretty_print import TracePrinter


[docs]def joy(stack, expression, dictionary, viewer=None): '''Evaluate the Joy expression on the stack. The basic joy() function is quite straightforward. It iterates through a sequence of terms which are either literals (strings, numbers, sequences) or functions. Literals are put onto the stack and functions are executed. :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): term = dictionary[term] stack, expression, dictionary = term(stack, expression, dictionary) else: stack = term, stack if viewer: viewer(stack, expression) return stack, expression, dictionary
[docs]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)
[docs]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 viewer = TracePrinter() try: stack, _, dictionary = run(text, stack, dictionary, viewer.viewer) except: exc = format_exc() # Capture the exception. viewer.print_() # Print the Joy trace. print('-' * 73) print(exc) # Print the original exception. else: viewer.print_() except: print_exc() print() return stack