brainfuck/bf.py
Rupus Reinefjord cd00cb787a add files
2017-07-16 20:35:06 +02:00

123 lines
3.2 KiB
Python
Executable file

#!/usr/bin/python3
import collections
import ctypes
import re
import sys
class Mixin:
def __add__(self, other):
return self.value + other
def __sub__(self, other):
return self.value - other
def __radd__(self, other):
return self.value + other
def __rsub__(self, other):
return self.value - other
def __iadd__(self, other):
self.value += other
return self
def __isub__(self, other):
self.value -= other
return self
def __eq__(self, other):
return self.value == other
def __hash__(self):
return hash(self.value)
class Byte(Mixin, ctypes.c_byte):
pass
class UByte(Mixin, ctypes.c_ubyte):
pass
Int = lambda x: x
TYPE = Byte
class Machine:
def __init__(self, program):
self.program = program
cells = {}
self.cells = collections.defaultdict(lambda: TYPE(0), cells)
self.data_pointer = TYPE(0)
self.instruction_pointer = 0
self.command_map = {
'>': self.increment_data_pointer,
'<': self.decrement_data_pointer,
'+': self.increment_cell,
'-': self.decrement_cell,
'.': self.print_cell,
',': self.set_cell,
'[': self.loop_start,
']': self.loop_end
}
def increment_data_pointer(self):
self.data_pointer += 1
def decrement_data_pointer(self):
self.data_pointer -= 1
def increment_cell(self):
self.cells[self.data_pointer] += 1
def decrement_cell(self):
self.cells[self.data_pointer] -= 1
def print_cell(self):
print(chr(self.cells[self.data_pointer]), end='')
def set_cell(self):
self.cells[self.data_pointer] = TYPE(ord(input('=> ')))
def loop_start(self):
if self.cells[self.data_pointer] == 0:
loop_starts = 0
self.instruction_pointer += 1
instruction = self.program[self.instruction_pointer]
while loop_starts > 0 or instruction != ']':
if instruction == '[':
loop_starts += 1
if instruction == ']':
loop_starts -= 1
self.instruction_pointer += 1
instruction = self.program[self.instruction_pointer]
def loop_end(self):
if self.cells[self.data_pointer] != 0:
loop_ends = 0
self.instruction_pointer -= 1
instruction = self.program[self.instruction_pointer]
while loop_ends > 0 or instruction != '[':
if instruction == ']':
loop_ends += 1
if instruction == '[':
loop_ends -= 1
self.instruction_pointer -= 1
instruction = self.program[self.instruction_pointer]
def run(self):
while self.instruction_pointer < len(self.program):
self.command_map[self.program[self.instruction_pointer]]()
self.instruction_pointer += 1
if __name__ == "__main__":
with open(sys.argv[1], 'r') as f:
program = re.findall(f"[{re.escape('<>+-.,[]')}]", f.read())
machine = Machine(program)
machine.run()
print("\nExiting...")