1 # -*- coding: utf-8 -*-
5 A dialect of Joy in Python.
8 Joy is a programming language created by Manfred von Thun that is easy to
9 use and understand and has many other nice properties. This Python script
10 is an interpreter for a dialect of Joy that attempts to stay very close
11 to the spirit of Joy but does not precisely match the behaviour of the
12 original version(s) written in C. A Tkinter GUI is provided as well.
15 Copyright © 2014, 2016, 2017 Simon Forman
17 This file is part of Thun.
19 Thun is free software: you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation, either version 3 of the License, or
22 (at your option) any later version.
24 Thun is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
29 You should have received a copy of the GNU General Public License
30 along with Thun. If not see <http://www.gnu.org/licenses/>.
35 The basic joy() function is quite straightforward. It iterates through a
36 sequence of terms which are either literals (strings, numbers, sequences)
37 or functions. Literals are put onto the stack and functions are
40 Every Joy function is an unary mapping from stacks to stacks. Even
41 literals are considered to be functions that accept a stack and return a
42 new stack with the literal value on top.
46 joy(stack, expression, dictionary, viewer=None)
48 run(text, stack, dictionary, viewer=None)
50 repl(stack=(), dictionary=())
53 from __future__ import print_function
58 from traceback import print_exc, format_exc
59 from .parser import text_to_expression, ParseError, Symbol
60 from .utils.stack import stack_to_string
61 from .utils.pretty_print import TracePrinter
64 def joy(stack, expression, dictionary, viewer=None):
66 Evaluate the Joy expression on the stack.
70 if viewer: viewer(stack, expression)
72 term, expression = expression
73 if isinstance(term, Symbol):
74 term = dictionary[term]
75 stack, expression, dictionary = term(stack, expression, dictionary)
79 if viewer: viewer(stack, expression)
80 return stack, expression, dictionary
83 def run(text, stack, dictionary, viewer=None):
85 Return the stack resulting from running the Joy code text on the stack.
87 expression = text_to_expression(text)
88 return joy(stack, expression, dictionary, viewer)
91 def repl(stack=(), dictionary=None):
93 Read-Evaluate-Print Loop
95 Accept input and run it on the stack, loop.
97 if dictionary is None:
102 print(stack_to_string(stack), '<-top')
105 text = input('joy? ')
106 except (EOFError, KeyboardInterrupt):
108 viewer = TracePrinter()
110 stack, _, dictionary = run(text, stack, dictionary, viewer.viewer)
112 exc = format_exc() # Capture the exception.
113 viewer.print_() # Print the Joy trace.
115 print(exc) # Print the original exception.