refactor: improve code readability
This commit is contained in:
116
dopey.py
116
dopey.py
@@ -2,19 +2,20 @@ import sys
|
|||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
from blessed import Terminal
|
from blessed import Terminal
|
||||||
|
|
||||||
# create memory buffer and pointer
|
class MismatchBracketException(Exception):
|
||||||
|
""" TODO line number and column """
|
||||||
|
pass
|
||||||
|
|
||||||
class Memory:
|
class Memory:
|
||||||
BUFFER_SIZE = 30_000
|
BUFFER_SIZE = 30_000
|
||||||
buffer = [0 for _ in range(BUFFER_SIZE)]
|
buffer = [0 for _ in range(BUFFER_SIZE)]
|
||||||
pointer = 0
|
pointer = 0
|
||||||
loop_stack = []
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_pointer(cls) -> int:
|
def get_pointer(cls) -> int:
|
||||||
# TODO add logic to roll around buffer
|
# TODO add logic to roll around buffer
|
||||||
return cls.pointer
|
return cls.pointer
|
||||||
|
|
||||||
# define bf commands
|
|
||||||
class Operation:
|
class Operation:
|
||||||
SHIFT_LEFT = "<"
|
SHIFT_LEFT = "<"
|
||||||
SHIFT_RIGHT = ">"
|
SHIFT_RIGHT = ">"
|
||||||
@@ -25,8 +26,73 @@ class Operation:
|
|||||||
OPEN_LOOP = "["
|
OPEN_LOOP = "["
|
||||||
CLOSE_LOOP = "]"
|
CLOSE_LOOP = "]"
|
||||||
|
|
||||||
|
terminal = Terminal()
|
||||||
|
loop_stack = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def perform(cls, operation: str, file: TextIOWrapper) -> None:
|
||||||
|
switch = {
|
||||||
|
cls.SHIFT_LEFT: cls.shift_left,
|
||||||
|
cls.SHIFT_RIGHT: cls.shift_right,
|
||||||
|
cls.INCREMENT: cls.increment,
|
||||||
|
cls.DECREMENT: cls.decrement,
|
||||||
|
cls.OUTPUT: cls.output,
|
||||||
|
cls.INPUT: cls.input,
|
||||||
|
cls.OPEN_LOOP: cls.open_loop,
|
||||||
|
cls.CLOSE_LOOP: cls.close_loop
|
||||||
|
}
|
||||||
|
|
||||||
|
if operation not in switch:
|
||||||
|
return
|
||||||
|
switch[operation](file)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def shift_left(cls, _) -> None:
|
||||||
|
Memory.pointer -= 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def shift_right(cls, _) -> None:
|
||||||
|
Memory.pointer += 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def increment(cls, _) -> None:
|
||||||
|
Memory.buffer[Memory.get_pointer()] += 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def decrement(cls, _) -> None:
|
||||||
|
Memory.buffer[Memory.get_pointer()] -= 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def output(cls, _) -> None:
|
||||||
|
print(chr(Memory.buffer[Memory.get_pointer()]), end="") # TODO rollover if too big in ASCII
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def input(cls, _) -> None:
|
||||||
|
with cls.terminal.cbreak():
|
||||||
|
Memory.buffer[Memory.get_pointer()] = ord(cls.terminal.inkey())
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def open_loop(cls, file: TextIOWrapper) -> None:
|
||||||
|
if not Memory.buffer[Memory.get_pointer()]:
|
||||||
|
while True:
|
||||||
|
operation = file.read(1)
|
||||||
|
if operation == Operation.CLOSE_LOOP:
|
||||||
|
break
|
||||||
|
elif not operation:
|
||||||
|
raise MismatchBracketException
|
||||||
|
else:
|
||||||
|
cls.loop_stack.append(file.tell()-1)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def close_loop(cls, file: TextIOWrapper) -> None:
|
||||||
|
if not len(cls.loop_stack):
|
||||||
|
raise MismatchBracketException
|
||||||
|
|
||||||
|
last_open_loop_pos = cls.loop_stack.pop()
|
||||||
|
if Memory.buffer[Memory.get_pointer()]:
|
||||||
|
file.seek(last_open_loop_pos, 0)
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
# get bf file location
|
|
||||||
file_location = None
|
file_location = None
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Invalid or missing arguments...")
|
print("Invalid or missing arguments...")
|
||||||
@@ -34,52 +100,16 @@ def main() -> None:
|
|||||||
else:
|
else:
|
||||||
file_location = sys.argv[1]
|
file_location = sys.argv[1]
|
||||||
|
|
||||||
# open file
|
|
||||||
file = open(file_location, "r")
|
file = open(file_location, "r")
|
||||||
while True:
|
while True:
|
||||||
operation = file.read(1)
|
operation = file.read(1)
|
||||||
if not operation:
|
if not operation:
|
||||||
break
|
break
|
||||||
|
Operation.perform(operation, file)
|
||||||
# perform operation
|
|
||||||
perform_operation(operation, file)
|
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
|
if len(Operation.loop_stack):
|
||||||
def perform_operation(operation: str, file: TextIOWrapper) -> None:
|
raise MismatchBracketException
|
||||||
if operation == Operation.SHIFT_LEFT:
|
|
||||||
Memory.pointer -= 1
|
|
||||||
elif operation == Operation.SHIFT_RIGHT:
|
|
||||||
Memory.pointer += 1
|
|
||||||
elif operation == Operation.INCREMENT:
|
|
||||||
Memory.buffer[Memory.get_pointer()] += 1
|
|
||||||
elif operation == Operation.DECREMENT:
|
|
||||||
Memory.buffer[Memory.get_pointer()] -= 1
|
|
||||||
elif operation == Operation.OUTPUT:
|
|
||||||
print(chr(Memory.buffer[Memory.get_pointer()]), end="")
|
|
||||||
elif operation == Operation.INPUT:
|
|
||||||
term = Terminal()
|
|
||||||
with term.cbreak():
|
|
||||||
Memory.buffer[Memory.get_pointer()] = ord(term.inkey())
|
|
||||||
elif operation == Operation.OPEN_LOOP:
|
|
||||||
if Memory.buffer[Memory.get_pointer()] == 0:
|
|
||||||
while True:
|
|
||||||
operation = file.read(1)
|
|
||||||
if operation == Operation.CLOSE_LOOP:
|
|
||||||
break
|
|
||||||
elif not operation:
|
|
||||||
print("Mismatched bracket...") # TODO add line number and column on line
|
|
||||||
sys.exit()
|
|
||||||
else:
|
|
||||||
Memory.loop_stack.append(file.tell()-1)
|
|
||||||
elif operation == Operation.CLOSE_LOOP:
|
|
||||||
if len(Memory.loop_stack) == 0:
|
|
||||||
print("Mismatched bracket...") # TODO add line number and column on line
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
open_loop_position = Memory.loop_stack.pop()
|
|
||||||
if Memory.buffer[Memory.get_pointer()] != 0:
|
|
||||||
file.seek(open_loop_position, 0)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user