Add basic interpreter and start of exampl
This commit is contained in:
commit
b3e3ea3427
16
bf_to_bw.py
Normal file
16
bf_to_bw.py
Normal file
@ -0,0 +1,16 @@
|
||||
import sys
|
||||
|
||||
commands = {
|
||||
'>': 'ee ee ee',
|
||||
'<': 'ee ee o',
|
||||
'+': 'ee o ee',
|
||||
'-': 'ee o o',
|
||||
'.': 'o ee ee',
|
||||
',': 'o ee o',
|
||||
'[': 'o o ee',
|
||||
']': 'o o o',
|
||||
}
|
||||
|
||||
for line in sys.stdin:
|
||||
for char in line:
|
||||
print commands.get(char, '')
|
95
bookworm.bw
Normal file
95
bookworm.bw
Normal file
@ -0,0 +1,95 @@
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o ee ee
|
||||
o o ee
|
||||
ee o o
|
||||
o o o
|
161
bookworm.py
Normal file
161
bookworm.py
Normal file
@ -0,0 +1,161 @@
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def generate_words(input_file):
|
||||
"""Generator that yields words from a file-like object.
|
||||
|
||||
:param input_file: the file-like object
|
||||
:yield: words from the file-like object until EOF
|
||||
|
||||
"""
|
||||
for line in input_file:
|
||||
for word in line.split():
|
||||
yield word
|
||||
|
||||
|
||||
def words_to_bits(words):
|
||||
"""Converts a lit of words to a string of bits. The '0's correspond
|
||||
with an even length word, and the '1's correspond with odd-length
|
||||
words.
|
||||
|
||||
>>> words_to_bits(["Hi,", "I'm", "Paul"])
|
||||
"110"
|
||||
|
||||
:param words: List of words to convert into bits
|
||||
:return: string of ASCII 1s and 0s representing the bits
|
||||
|
||||
"""
|
||||
evenness = ['0' if len(word) % 2 == 0 else '1' for word in words]
|
||||
return ''.join(evenness)
|
||||
|
||||
|
||||
class BookwormInterpreter(object):
|
||||
"""A bookworm interpreter executes a program written in the Bookworm
|
||||
programming language for a particular file."""
|
||||
|
||||
code = {}
|
||||
data = defaultdict(lambda: 0)
|
||||
address = 0
|
||||
instruction_pointer = 0
|
||||
|
||||
def __init__(self, input_file):
|
||||
"""Initializer for bookworm interpreters.
|
||||
|
||||
:param input_file: the file to interpret
|
||||
|
||||
"""
|
||||
self.word_generator = generate_words(input_file)
|
||||
|
||||
self.commands = {
|
||||
"000": self.move_right,
|
||||
"001": self.move_left,
|
||||
"010": self.increment,
|
||||
"011": self.decrement,
|
||||
"100": self.output,
|
||||
"101": self.read,
|
||||
"110": self.open_bracket,
|
||||
"111": self.close_bracket,
|
||||
}
|
||||
|
||||
def move_right(self):
|
||||
"""Moves the address on the data tape right."""
|
||||
self.address += 1
|
||||
|
||||
def move_left(self):
|
||||
"""Moves the address on the data tape left."""
|
||||
self.address -= 1
|
||||
|
||||
def increment(self):
|
||||
"""Increments the value of the data tape at the address."""
|
||||
self.data[self.address] = self.data[self.address] + 1
|
||||
|
||||
def decrement(self):
|
||||
"""Decrements the value of the data tape at the address."""
|
||||
self.data[self.address] = self.data[self.address] - 1
|
||||
|
||||
def output(self):
|
||||
"""Outputs the current value of the data tape to stdout."""
|
||||
sys.stdout.write(chr(self.data[self.address]))
|
||||
|
||||
def read(self):
|
||||
"""Writes from stdin one byte into the data tape."""
|
||||
self.data[self.address] = sys.stdin.read(1)
|
||||
|
||||
def open_bracket(self):
|
||||
"""If the current value of the data tape is 0, jumps to the next
|
||||
matching close_bracket (denoted by opcode '111')."""
|
||||
if self.data[self.address] == 0:
|
||||
curr_byte = self.code[self.instruction_pointer]
|
||||
num_unresolved_pairs = 1
|
||||
while num_unresolved_pairs > 0:
|
||||
self.instruction_pointer += 1
|
||||
curr_byte = self.get_op_code_at(self.instruction_pointer)
|
||||
if curr_byte == '110':
|
||||
num_unresolved_pairs += 1
|
||||
elif curr_byte == '111':
|
||||
num_unresolved_pairs -= 1
|
||||
|
||||
def close_bracket(self):
|
||||
"""If the current value of the data tape is 0, jumps back to
|
||||
the next matching open_bracket (denoted by opcode '110')."""
|
||||
if self.data[self.address] != 0:
|
||||
curr_byte = None
|
||||
num_unresolved_pairs = 1
|
||||
while num_unresolved_pairs > 0:
|
||||
self.instruction_pointer -= 1
|
||||
curr_byte = self.get_op_code_at(self.instruction_pointer)
|
||||
if curr_byte == '110':
|
||||
num_unresolved_pairs -= 1
|
||||
elif curr_byte == '111':
|
||||
num_unresolved_pairs += 1
|
||||
|
||||
def get_op_code_at(self, index):
|
||||
"""Returns the opcode stored in the code tape at the given
|
||||
index. Reads it from the file if it's not available. Assumes
|
||||
that if the given index is not already in the code tape, we have
|
||||
to read the next opcode from the word generator.
|
||||
|
||||
:param index: The index on the code tape
|
||||
:return: The value of the code tape at the given index
|
||||
|
||||
"""
|
||||
if index not in self.code:
|
||||
self.code[index] = self.get_op_code()
|
||||
return self.code[index]
|
||||
|
||||
def get_op_code(self):
|
||||
""""""
|
||||
words = []
|
||||
while len(words) < 3:
|
||||
words.append(next(self.word_generator))
|
||||
return words_to_bits(words)
|
||||
|
||||
def execute_code(self):
|
||||
"""Executes code by getting the opcodes one at a time and
|
||||
executing them sequentially."""
|
||||
op_code = self.get_op_code_at(self.instruction_pointer)
|
||||
command = self.commands[op_code]
|
||||
command()
|
||||
self.instruction_pointer += 1
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function for this interpreter command line interface."""
|
||||
|
||||
# Check num args
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("Usage: {} <input file>")
|
||||
|
||||
input_file = open(sys.argv[1])
|
||||
bookworm = BookwormInterpreter(input_file)
|
||||
|
||||
while True:
|
||||
try:
|
||||
bookworm.execute_code()
|
||||
except StopIteration:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
106
hello.bw
Normal file
106
hello.bw
Normal file
@ -0,0 +1,106 @@
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee ee o
|
||||
ee ee o
|
||||
ee ee o
|
||||
ee ee o
|
||||
ee o o
|
||||
o o o
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee ee ee
|
||||
ee o o
|
||||
ee ee ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
o o ee
|
||||
ee ee o
|
||||
o o o
|
||||
ee ee o
|
||||
ee o o
|
||||
o o o
|
||||
ee ee ee
|
||||
ee ee ee
|
||||
o ee ee
|
||||
ee ee ee
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
o ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o ee ee
|
||||
o ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o ee ee
|
||||
ee ee ee
|
||||
ee ee ee
|
||||
o ee ee
|
||||
ee ee o
|
||||
ee o o
|
||||
o ee ee
|
||||
ee ee o
|
||||
o ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o ee ee
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
o ee ee
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
ee o o
|
||||
o ee ee
|
||||
ee ee ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
o ee ee
|
||||
ee ee ee
|
||||
ee o ee
|
||||
ee o ee
|
||||
o ee ee
|
1
idiomatic_hello.bw
Normal file
1
idiomatic_hello.bw
Normal file
@ -0,0 +1 @@
|
||||
This program is Bookworm's reference "Hello World" implementation. Please do not take this example as "the one true way" since many possible alternative programs could certainly be used instead. This particular program took over one hour to write as Bookworm's constraints make you carefully consider each individual character. Fortunately, idiomatic Bookworm programs are self-documenting in that source code and comments become combined. In actuality, the source code consists entirely of comments! We strongly believe that code ought to document itself so that other people (read: your colleagues) will very quickly understand what the code is doing by reading the code. There could be no comments at all as well as zero documentation. The only resource that your fellow programmers would need is your source code as it stands. That's exactly why Bookworm programs will typically avoid the use of explicit comment markers. o o o o o ee ee ee ee ee ee o ee ee ee ee ee ee o o ee o o ee o o o ee ee ee o ee ee o ee ee o ee ee o ee ee o ee ee o ee ee o ee o ee ee o ee ee ee o ee ee o ee ee o ee o ee ee ee ee ee ee ee ee o ee ee ee ee o ee o o o ee ee ee ee o o ee ee ee o ee ee o ee ee o ee o ee ee ee o o ee o o ee o o ee o o ee o o ee o o o ee ee ee o o ee o o ee o o ee o o ee o o ee o o ee o o ee o o o ee ee ee ee ee ee ee ee ee o ee o ee ee ee ee ee ee o ee ee o ee o ee ee
|
Loading…
x
Reference in New Issue
Block a user