Remove build dir from version control.

This commit is contained in:
Simon Forman 2018-04-16 21:26:31 -07:00
parent 9805f479be
commit f454014248
8 changed files with 0 additions and 1787 deletions

View File

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2014, 2015, 2017 Simon Forman
#
# This file is part of joy.py
#
# joy.py 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.
#
# joy.py 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 joy.py. If not see <http://www.gnu.org/licenses/>.
#
from .library import initialize
from .joy import repl
print '''\
Joypy - Copyright © 2017 Simon Forman
This program comes with ABSOLUTELY NO WARRANTY; for details type "warranty".
This is free software, and you are welcome to redistribute it
under certain conditions; type "sharing" for details.
Type "words" to see a list of all words, and "[<name>] help" to print the
docs for a word.
'''
stack = repl(dictionary=initialize())

View File

@ -1,125 +0,0 @@
# -*- coding: utf-8 -*-
'''
A dialect of Joy in Python.
Joy is a programming language created by Manfred von Thun that is easy to
use and understand and has many other nice properties. This Python script
is 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. A Tkinter GUI is provided as well.
Copyright © 2014, 2016, 2017 Simon Forman
This file is part of Joypy.
Joypy 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.
Joypy 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 Joypy. If not see <http://www.gnu.org/licenses/>.
§ joy()
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.
Every Joy function is an unary mapping from stacks to stacks. Even
literals are considered to be functions that accept a stack and return a
new stack with the literal value on top.
Exports:
joy(stack, expression, dictionary, viewer=None)
run(text, stack, dictionary, viewer=None)
repl(stack=(), dictionary=())
'''
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
def joy(stack, expression, dictionary, viewer=None):
'''
Evaluate the Joy expression on the stack.
'''
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
def run(text, stack, dictionary, viewer=None):
'''
Return the stack resulting from running the Joy code text on the stack.
'''
try:
expression = text_to_expression(text)
except ParseError as err:
print('Err:', err.message)
return stack, (), dictionary
return joy(stack, expression, dictionary, viewer)
def repl(stack=(), dictionary=None):
'''
Read-Evaluate-Print Loop
Accept input and run it on the stack, loop.
'''
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

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2014, 2015, 2016, 2017 Simon Forman
#
# This file is part of Joypy.
#
# Joypy 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.
#
# Joypy 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 Joypy. If not see <http://www.gnu.org/licenses/>.
#
'''
§ Converting text to a joy expression.
This module exports a single function:
text_to_expression(text)
As well as a single Symbol class and a single Exception type:
ParseError
When supplied with a string this function returns a Python datastructure
that represents the Joy datastructure described by the text expression.
Any unbalanced square brackets will raise a ParseError.
'''
from re import Scanner
from .utils.stack import list_to_stack
class Symbol(str):
__repr__ = str.__str__
def text_to_expression(text):
'''
Convert a text to a Joy expression.
'''
return _parse(_tokenize(text))
class ParseError(ValueError): pass
def _tokenize(text):
'''
Convert a text into a stream of tokens, converting symbols using
symbol(token). Raise ValueError (with some of the failing text)
if the scan fails.
'''
tokens, rest = _scanner.scan(text)
if rest:
raise ParseError(
'Scan failed at position %i, %r'
% (len(text) - len(rest), rest[:10])
)
return tokens
def _parse(tokens):
'''
Return a stack/list expression of the tokens.
'''
frame = []
stack = []
for tok in tokens:
if tok == '[':
stack.append(frame)
frame = []
stack[-1].append(frame)
elif tok == ']':
try:
frame = stack.pop()
except IndexError:
raise ParseError('One or more extra closing brackets.')
frame[-1] = list_to_stack(frame[-1])
else:
frame.append(tok)
if stack:
raise ParseError('One or more unclosed brackets.')
return list_to_stack(frame)
def _scan_identifier(scanner, token): return Symbol(token)
def _scan_bracket(scanner, token): return token
def _scan_float(scanner, token): return float(token)
def _scan_int(scanner, token): return int(token)
def _scan_dstr(scanner, token): return token[1:-1].replace('\\"', '"')
def _scan_sstr(scanner, token): return token[1:-1].replace("\\'", "'")
_scanner = Scanner([
(r'-?\d+\.\d*', _scan_float),
(r'-?\d+', _scan_int),
(r'[•\w!@$%^&*()_+<>?|\/;:`~,.=-]+', _scan_identifier),
(r'\[|\]', _scan_bracket),
(r'"(?:[^"\\]|\\.)*"', _scan_dstr),
(r"'(?:[^'\\]|\\.)*'", _scan_sstr),
(r'\s+', None),
])

View File

@ -1,72 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2016 Simon Forman
#
# This file is part of Joypy.
#
# Joypy 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.
#
# Joypy 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 Joypy. If not see <http://www.gnu.org/licenses/>.
#
'''
Pretty printing support.
This is what does the formatting, e.g.:
. 23 18 mul 99 add
23 . 18 mul 99 add
23 18 . mul 99 add
414 . 99 add
414 99 . add
513 .
'''
# (Kinda clunky and hacky. This should be swapped out in favor of much
# smarter stuff.)
from __future__ import print_function
from traceback import print_exc
from .stack import expression_to_string, stack_to_string
class TracePrinter(object):
def __init__(self):
self.history = []
def viewer(self, stack, expression):
'''Pass this method as the viewer to joy() function.'''
self.history.append((stack, expression))
def __str__(self):
return '\n'.join(self.go())
def go(self):
max_stack_length = 0
lines = []
for stack, expression in self.history:
stack = stack_to_string(stack)
expression = expression_to_string(expression)
n = len(stack)
if n > max_stack_length:
max_stack_length = n
lines.append((n, '%s . %s' % (stack, expression)))
return [ # Prefix spaces to line up '.'s.
(' ' * (max_stack_length - length) + line)
for length, line in lines
]
def print_(self):
try:
print(self)
except:
print_exc()
print('Exception while printing viewer.')

View File

@ -1,154 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2014, 2015, 2017 Simon Forman
#
# This file is part of joy.py
#
# joy.py 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.
#
# joy.py 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 joy.py. If not see <http://www.gnu.org/licenses/>.
#
'''
§ Stack
When talking about Joy we use the terms "stack", "list", "sequence" and
"aggregate" to mean the same thing: a simple datatype that permits
certain operations such as iterating and pushing and popping values from
(at least) one end.
We use the venerable two-tuple recursive form of sequences where the
empty tuple () is the empty stack and (head, rest) gives the recursive
form of a stack with one or more items on it.
()
(1, ())
(2, (1, ()))
(3, (2, (1, ())))
...
And so on.
We have two very simple functions to build up a stack from a Python
iterable and also to iterate through a stack and yield its items
one-by-one in order, and two functions to generate string representations
of stacks:
list_to_stack()
iter_stack()
expression_to_string() (prints left-to-right)
stack_to_string() (prints right-to-left)
A word about the stack data structure.
Python has very nice "tuple packing and unpacking" in its syntax which
means we can directly "unpack" the expected arguments to a Joy function.
For example:
def dup(stack):
head, tail = stack
return head, (head, tail)
We replace the argument "stack" by the expected structure of the stack,
in this case "(head, tail)", and Python takes care of de-structuring the
incoming argument and assigning values to the names. Note that Python
syntax doesn't require parentheses around tuples used in expressions
where they would be redundant.
'''
def list_to_stack(el, stack=()):
'''Convert a list (or other sequence) to a stack.
[1, 2, 3] -> (1, (2, (3, ())))
'''
for item in reversed(el):
stack = item, stack
return stack
def iter_stack(stack):
'''Iterate through the items on the stack.'''
while stack:
item, stack = stack
yield item
def stack_to_string(stack):
'''
Return a "pretty print" string for a stack.
The items are written right-to-left:
(top, (second, ...)) -> '... second top'
'''
f = lambda stack: reversed(list(iter_stack(stack)))
return _to_string(stack, f)
def expression_to_string(expression):
'''
Return a "pretty print" string for a expression.
The items are written left-to-right:
(top, (second, ...)) -> 'top second ...'
'''
return _to_string(expression, iter_stack)
def _to_string(stack, f):
if isinstance(stack, long): return str(stack).rstrip('L')
if not isinstance(stack, tuple): return repr(stack)
if not stack: return '' # shortcut
return ' '.join(map(_s, f(stack)))
_s = lambda s: (
'[%s]' % expression_to_string(s) if isinstance(s, tuple)
else str(s).rstrip('L') if isinstance(s, long)
else repr(s)
)
def pushback(quote, expression):
'''Concatinate quote onto expression.
In joy [1 2] [3 4] would become [1 2 3 4].
'''
return list_to_stack(list(iter_stack(quote)), expression)
def pick(s, n):
'''
Find the nth item on the stack. (Pick with zero is the same as "dup".)
'''
if n < 0:
raise ValueError
while True:
try:
item, s = s
except ValueError:
raise IndexError
n -= 1
if n < 0:
break
return item