fix: address infinite loops and improve perf
This commit is contained in:
84
dopey.py
84
dopey.py
@@ -1,19 +1,24 @@
|
|||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
|
from typing import Dict, List
|
||||||
|
|
||||||
class MismatchBracketException(Exception):
|
class MismatchBracketException(Exception):
|
||||||
""" TODO line number and column """
|
""" TODO line number and column """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class MemoryException(Exception):
|
||||||
|
""" TODO line number and column """
|
||||||
|
pass
|
||||||
|
|
||||||
class Memory:
|
class Memory:
|
||||||
BUFFER_SIZE = 30_000
|
BUFFER_SIZE = 300_000
|
||||||
buffer = [0 for _ in range(BUFFER_SIZE)]
|
buffer = [0 for _ in range(BUFFER_SIZE)]
|
||||||
pointer = 0
|
pointer = 0
|
||||||
input_buffer = []
|
input_buffer = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_pointer(cls) -> int:
|
def get_pointer(cls) -> int:
|
||||||
# TODO add logic to roll around buffer
|
|
||||||
return cls.pointer
|
return cls.pointer
|
||||||
|
|
||||||
class Operation:
|
class Operation:
|
||||||
@@ -29,29 +34,22 @@ class Operation:
|
|||||||
loop_stack = []
|
loop_stack = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def perform(cls, operation: str, file: TextIOWrapper) -> None:
|
def perform(cls, operation: str, program: List, switch: Dict) -> 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:
|
if operation not in switch:
|
||||||
return
|
return
|
||||||
switch[operation](file)
|
switch[operation](program)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def shift_left(cls, _) -> None:
|
def shift_left(cls, _) -> None:
|
||||||
Memory.pointer -= 1
|
Memory.pointer -= 1
|
||||||
|
if Memory.pointer < 0:
|
||||||
|
raise MemoryException
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def shift_right(cls, _) -> None:
|
def shift_right(cls, _) -> None:
|
||||||
Memory.pointer += 1
|
Memory.pointer += 1
|
||||||
|
if Memory.pointer >= Memory.BUFFER_SIZE:
|
||||||
|
raise MemoryException
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def increment(cls, _) -> None:
|
def increment(cls, _) -> None:
|
||||||
@@ -63,36 +61,57 @@ class Operation:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def output(cls, _) -> None:
|
def output(cls, _) -> None:
|
||||||
print(chr(Memory.buffer[Memory.get_pointer()]), end="") # TODO rollover if too big in ASCII
|
sys.stdout.write(chr(Memory.buffer[Memory.get_pointer()])) # TODO rollover if too big in ASCII
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def input(cls, _) -> None:
|
def input(cls, _) -> None:
|
||||||
|
# flush text to terminal before asking for input
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
if not len(Memory.input_buffer):
|
if not len(Memory.input_buffer):
|
||||||
input_ = input()
|
input_ = sys.stdin.readline()
|
||||||
Memory.input_buffer += list(input_)
|
Memory.input_buffer += list(input_)
|
||||||
if len(Memory.input_buffer):
|
if len(Memory.input_buffer):
|
||||||
Memory.buffer[Memory.get_pointer()] = ord(Memory.input_buffer.pop(0))
|
Memory.buffer[Memory.get_pointer()] = ord(Memory.input_buffer.pop(0))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def open_loop(cls, file: TextIOWrapper) -> None:
|
def open_loop(cls, program: List) -> None:
|
||||||
if not Memory.buffer[Memory.get_pointer()]:
|
if not Memory.buffer[Memory.get_pointer()]:
|
||||||
while True:
|
# TODO redo this section to be more readable
|
||||||
operation = file.read(1)
|
stack = [Operation.OPEN_LOOP]
|
||||||
|
while program[1] < len(program[0]):
|
||||||
|
operation = program[0][program[1]]
|
||||||
|
program[1] += 1
|
||||||
if operation == Operation.CLOSE_LOOP:
|
if operation == Operation.CLOSE_LOOP:
|
||||||
break
|
stack.pop()
|
||||||
elif not operation:
|
if not len(stack):
|
||||||
|
return
|
||||||
|
elif operation == Operation.OPEN_LOOP:
|
||||||
|
stack.append(Operation.OPEN_LOOP)
|
||||||
raise MismatchBracketException
|
raise MismatchBracketException
|
||||||
else:
|
else:
|
||||||
cls.loop_stack.append(file.tell()-1)
|
cls.loop_stack.append(program[1]-1)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def close_loop(cls, file: TextIOWrapper) -> None:
|
def close_loop(cls, program: List) -> None:
|
||||||
if not len(cls.loop_stack):
|
if not len(cls.loop_stack):
|
||||||
raise MismatchBracketException
|
raise MismatchBracketException
|
||||||
|
|
||||||
last_open_loop_pos = cls.loop_stack.pop()
|
last_open_loop_pos = cls.loop_stack.pop()
|
||||||
if Memory.buffer[Memory.get_pointer()]:
|
if Memory.buffer[Memory.get_pointer()]:
|
||||||
file.seek(last_open_loop_pos, 0)
|
program[1] = last_open_loop_pos
|
||||||
|
|
||||||
|
def get_operations_in_switch() -> Dict:
|
||||||
|
return {
|
||||||
|
Operation.SHIFT_LEFT: Operation.shift_left,
|
||||||
|
Operation.SHIFT_RIGHT: Operation.shift_right,
|
||||||
|
Operation.INCREMENT: Operation.increment,
|
||||||
|
Operation.DECREMENT: Operation.decrement,
|
||||||
|
Operation.OUTPUT: Operation.output,
|
||||||
|
Operation.INPUT: Operation.input,
|
||||||
|
Operation.OPEN_LOOP: Operation.open_loop,
|
||||||
|
Operation.CLOSE_LOOP: Operation.close_loop
|
||||||
|
}
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
file_location = None
|
file_location = None
|
||||||
@@ -103,13 +122,16 @@ def main() -> None:
|
|||||||
file_location = sys.argv[1]
|
file_location = sys.argv[1]
|
||||||
|
|
||||||
file = open(file_location, "r")
|
file = open(file_location, "r")
|
||||||
while True:
|
program = [file.read(), 0] # TODO create files class
|
||||||
operation = file.read(1)
|
|
||||||
if not operation:
|
|
||||||
break
|
|
||||||
Operation.perform(operation, file)
|
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
|
switch = Operation.get_operations_in_switch()
|
||||||
|
|
||||||
|
while program[1] < len(program[0]):
|
||||||
|
operation = program[0][program[1]]
|
||||||
|
program[1] += 1
|
||||||
|
Operation.perform(operation, program, switch)
|
||||||
|
|
||||||
if len(Operation.loop_stack):
|
if len(Operation.loop_stack):
|
||||||
raise MismatchBracketException
|
raise MismatchBracketException
|
||||||
|
|
||||||
|
|||||||
41
test.bf
41
test.bf
@@ -1 +1,40 @@
|
|||||||
,>,>,>,>,<<<<.>.>.>.>.
|
--->--->>>>->->->>>>>-->>>>>>>>>>>>>>>>>>+>>++++++++++[
|
||||||
|
<<++[
|
||||||
|
--<+<<+<<+>>>>[
|
||||||
|
>[<->>+++>>[-]+++<<<+[<++>>+<--]]+>+++++[>>+++++++++<<-]
|
||||||
|
>>++++.[-]>>+[<<<<+>>+>>-]<<<<<<[>+<-]<<
|
||||||
|
]++++++++++.[-]>++
|
||||||
|
]-->>[-->[-]>]<<[
|
||||||
|
>>--[
|
||||||
|
-[
|
||||||
|
-[
|
||||||
|
-----[>+>+++++++<<+]-->>-.----->,[<->-]<[[<]+[->>]<-]<[<<,[-]]>>>>
|
||||||
|
]>
|
||||||
|
]<[
|
||||||
|
>-[+<+++]+<+++[+[---->]+<<<<<<[>>]<[-]]
|
||||||
|
>[<+[---->]++[<]<[>]>[[>]+>+++++++++<<-[<]]]>[>>>>]
|
||||||
|
]<[
|
||||||
|
-[[>+>+<<-]>[<+>-]++>+>>]<[<<++[-->>[-]]>[[-]>[<<+>>-]>]]
|
||||||
|
]<[
|
||||||
|
[[<<]-[>>]<+<-]>[-<+]<<[<<]-<[>[+>>]>[>]>[-]]
|
||||||
|
>[[+>>]<-->>[>]+>>>]
|
||||||
|
]<[
|
||||||
|
-[
|
||||||
|
--[+<<<<--[+>[-]>[<<+>+>-]<<[>>+<<-]]++[>]]
|
||||||
|
<<[>+>+<<-]>--[<+>-]++>>>
|
||||||
|
]<[<<<[-]+++>[-]>[<+>>>+<<-]+>>>]
|
||||||
|
]<[
|
||||||
|
+[[<]<<[<<]-<->>+>[>>]>[>]<-]+[-<+]<++[[>+<-]++<[<<->>+]<++]<
|
||||||
|
<<<<<< +> > >+> > >+[
|
||||||
|
<<< ->+>+>+[
|
||||||
|
<<<<<<< +>->+> > >->->+[
|
||||||
|
<<<<< ->+>+> >+>+[
|
||||||
|
<<<< ->->+>->+[
|
||||||
|
<<<<<<<<+>-> >+> > >->+>+[
|
||||||
|
<<<<< -> >+> >->+[
|
||||||
|
<<<< +>->+> >+]]]]]]]
|
||||||
|
+++[[>+<-]<+++]--->>[-[<->-]<++>>]++[[<->-]>>]>[>]
|
||||||
|
]<
|
||||||
|
]
|
||||||
|
]<
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user