OSDN Git Service

Working on the Sphinx docs.
[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 try:
28   input = raw_input
29 except NameError:
30   pass
31 from traceback import print_exc, format_exc
32 from .parser import text_to_expression, ParseError, Symbol
33 from .utils.stack import stack_to_string
34 from .utils.pretty_print import TracePrinter
35
36
37 def joy(stack, expression, dictionary, viewer=None):
38   '''Evaluate the Joy expression on the stack.
39   
40   The basic joy() function is quite straightforward.  It iterates through a
41   sequence of terms which are either literals (strings, numbers, sequences)
42   or functions.  Literals are put onto the stack and functions are
43   executed.
44
45
46   :param quote stack: The stack.
47   :param quote expression: The expression to evaluate.
48   :param dict dictionary: A `dict` mapping names to Joy functions.
49   :param function viewer: Optional viewer function.
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   expression = text_to_expression(text)
72   return joy(stack, expression, dictionary, viewer)
73
74
75 def repl(stack=(), dictionary=None):
76   '''
77   Read-Evaluate-Print Loop
78
79   Accept input and run it on the stack, loop.
80   '''
81   if dictionary is None:
82     dictionary = {}
83   try:
84     while True:
85       print()
86       print(stack_to_string(stack), '<-top')
87       print()
88       try:
89         text = input('joy? ')
90       except (EOFError, KeyboardInterrupt):
91         break
92       viewer = TracePrinter()
93       try:
94         stack, _, dictionary = run(text, stack, dictionary, viewer.viewer)
95       except:
96         exc = format_exc() # Capture the exception.
97         viewer.print_() # Print the Joy trace.
98         print('-' * 73)
99         print(exc) # Print the original exception.
100       else:
101         viewer.print_()
102   except:
103     print_exc()
104   print()
105   return stack