OSDN Git Service

Change project name to Thun.
[joypy/Thun.git] / joy / joy.py
1 # -*- coding: utf-8 -*-
2 '''
3
4
5 A dialect of Joy in Python.
6
7
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.
13
14
15     Copyright © 2014, 2016, 2017 Simon Forman
16
17     This file is part of Thun.
18
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.
23
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.
28
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/>.
31
32
33 § joy()
34
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
38 executed.
39
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.
43
44 Exports:
45
46   joy(stack, expression, dictionary, viewer=None)
47
48   run(text, stack, dictionary, viewer=None)
49
50   repl(stack=(), dictionary=())
51
52 '''
53 from __future__ import print_function
54 try:
55   input = raw_input
56 except NameError:
57   pass
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
62
63
64 def joy(stack, expression, dictionary, viewer=None):
65   '''
66   Evaluate the Joy expression on the stack.
67   '''
68   while expression:
69
70     if viewer: viewer(stack, expression)
71
72     term, expression = expression
73     if isinstance(term, Symbol):
74       term = dictionary[term]
75       stack, expression, dictionary = term(stack, expression, dictionary)
76     else:
77       stack = term, stack
78
79   if viewer: viewer(stack, expression)
80   return stack, expression, dictionary
81
82
83 def run(text, stack, dictionary, viewer=None):
84   '''
85   Return the stack resulting from running the Joy code text on the stack.
86   '''
87   expression = text_to_expression(text)
88   return joy(stack, expression, dictionary, viewer)
89
90
91 def repl(stack=(), dictionary=None):
92   '''
93   Read-Evaluate-Print Loop
94
95   Accept input and run it on the stack, loop.
96   '''
97   if dictionary is None:
98     dictionary = {}
99   try:
100     while True:
101       print()
102       print(stack_to_string(stack), '<-top')
103       print()
104       try:
105         text = input('joy? ')
106       except (EOFError, KeyboardInterrupt):
107         break
108       viewer = TracePrinter()
109       try:
110         stack, _, dictionary = run(text, stack, dictionary, viewer.viewer)
111       except:
112         exc = format_exc() # Capture the exception.
113         viewer.print_() # Print the Joy trace.
114         print('-' * 73)
115         print(exc) # Print the original exception.
116       else:
117         viewer.print_()
118   except:
119     print_exc()
120   print()
121   return stack