OSDN Git Service

Make sure joy.gui.main.__doc__ is at the top of the module.
[joypy/Thun.git] / joy / joy.py
1 # -*- coding: utf-8 -*-
2 #
3 #    Copyright © 2014, 2015, 2017, 2018 Simon Forman
4 #
5 #    This file is part of Thun
6 #
7 #    Thun is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation, either version 3 of the License, or
10 #    (at your option) any later version.
11 #
12 #    Thun is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with Thun.  If not see <http://www.gnu.org/licenses/>.
19 #
20 '''
21 This module implements an interpreter for a dialect of Joy that
22 attempts to stay very close to the spirit of Joy but does not precisely
23 match the behaviour of the original version(s) written in C.
24
25 '''
26 from __future__ import print_function
27 from builtins import input
28 from traceback import print_exc, format_exc
29 from .parser import text_to_expression, ParseError, Symbol
30 from .utils.stack import stack_to_string
31 from .utils.pretty_print import TracePrinter
32
33
34 def joy(stack, expression, dictionary, viewer=None):
35   '''Evaluate a Joy expression on a stack.
36
37   This function iterates through a sequence of terms which are either
38   literals (strings, numbers, sequences of terms) or function symbols.
39   Literals are put onto the stack and functions are looked up in the
40   disctionary and executed.
41
42   The viewer is a function that is called with the stack and expression
43   on every iteration, its return value is ignored.
44
45   :param stack stack: The stack.
46   :param stack expression: The expression to evaluate.
47   :param dict dictionary: A ``dict`` mapping names to Joy functions.
48   :param function viewer: Optional viewer function.
49   :rtype: (stack, (), dictionary)
50
51   '''
52   while expression:
53
54     if viewer: viewer(stack, expression)
55
56     term, expression = expression
57     if isinstance(term, Symbol):
58       term = dictionary[term]
59       stack, expression, dictionary = term(stack, expression, dictionary)
60     else:
61       stack = term, stack
62
63   if viewer: viewer(stack, expression)
64   return stack, expression, dictionary
65
66
67 def run(text, stack, dictionary, viewer=None):
68   '''
69   Return the stack resulting from running the Joy code text on the stack.
70
71   :param str text: Joy code.
72   :param stack stack: The stack.
73   :param dict dictionary: A ``dict`` mapping names to Joy functions.
74   :param function viewer: Optional viewer function.
75   :rtype: (stack, (), dictionary)
76
77   '''
78   expression = text_to_expression(text)
79   return joy(stack, expression, dictionary, viewer)
80
81
82 def repl(stack=(), dictionary=None):
83   '''
84   Read-Evaluate-Print Loop
85
86   Accept input and run it on the stack, loop.
87
88   :param stack stack: The stack.
89   :param dict dictionary: A ``dict`` mapping names to Joy functions.
90   :rtype: stack
91
92   '''
93   if dictionary is None:
94     dictionary = {}
95   try:
96     while True:
97       print()
98       print(stack_to_string(stack), '<-top')
99       print()
100       try:
101         text = input('joy? ')
102       except (EOFError, KeyboardInterrupt):
103         break
104       viewer = TracePrinter()
105       try:
106         stack, _, dictionary = run(text, stack, dictionary, viewer.viewer)
107       except:
108         exc = format_exc() # Capture the exception.
109         viewer.print_() # Print the Joy trace.
110         print('-' * 73)
111         print(exc) # Print the original exception.
112       else:
113         viewer.print_()
114   except:
115     print_exc()
116   print()
117   return stack