Cześć, przerabiam sobie książkę gynvaela (jak ktoś nie czytał to polecam :) ) i jestem na etapie tworzenia interpretera języka brainfuck. Wybrałem język python i bazowałem dość mocno na vm'ce z tego rozdziału, ale to tak na marginesie.

Byłbym wdzięczny jakby ktoś doświadczony rzucił okiem pod kątem jakości kodu i ogólnego podejścia do problemu, czy jest to optymalne rozwiązanie czy można coś zrobić lepiej. Z góry dzięki za każdą opinie :)

BF (main class)

import sys
from bf_memory import BFMemory
from bf_instr import BF_INSTR

class BF:
    def __init__(self):
        self.mem = BFMemory()
        self.mem_counter = 0
        self.terminated = False

        self.program = bytearray(30000)
        self.instr = BF_INSTR
        self.program_counter = 0

        self.start_of_the_loop = 0
        self.loop_counter = 0

    def crash(self):
      self.terminated = True
      print("The program has crashed.")

    def load_program_from_file(self, addr, name):
        with open(name, 'rb') as f:
            data = f.read(30*1024)
        return self.mem.store_many(addr, data)

    def run(self):
      while self.mem.fetch_byte(self.mem_counter) in BF_INSTR and not self.terminated:
        self.instr[self.mem.fetch_byte(self.mem_counter)](self)
        self.mem_counter += 1




if __name__ == '__main__':
  if len(sys.argv) != 2:
    print("usage: bf.py <filename>")
    sys.exit(1)

  bf = BF()
  bf.load_program_from_file(0, sys.argv[1])
  bf.run()

class BFMemory

class BFMemory:
    def __init__(self):
        self._mem = bytearray(30*1024) # 30 KB memory size

    def store_many(self, addr, array):
        if addr + len(array) - 1 >= len(self._mem):
            return False
        for i, value in enumerate(array):
            self._mem[addr + i] = value
        return True

    def fetch_byte(self, addr):
        if addr < 0 or addr >= len(self._mem):
            return None

        return self._mem[addr]

Instructions

import sys

def INC(bf):
    bf.program[bf.program_counter] = (bf.program[bf.program_counter] + 1) & 0xff
def DEC(bf):
    bf.program[bf.program_counter] = (bf.program[bf.program_counter] - 1) & 0xff
# stdout
def WRITE_STDOUT(bf):
    sys.stdout.write(chr(bf.program[bf.program_counter]))
# stdin
def READ_STDIN(bf): #
    ch = sys.stdin.read(1)
    bf.program[bf.program_counter] = ord(ch)
# go left
def DEC_PTR(bf):
    if bf.program_counter < len(bf.program):
        bf.program_counter -= 1
    else:
        bf.crash()
# go right
def INC_PTR(bf):
    if bf.program_counter < len(bf.program):
        bf.program_counter += 1
    else:
        bf.crash()
# open loop
def OPEN_LOOP(bf):
    bf.start_of_the_loop = bf.mem_counter
    bf.loop_counter = bf.program_counter
# close loop
def CLOSE_LOOP(bf):
    if bf.program[bf.loop_counter] > 0:
        bf.mem_counter = bf.start_of_the_loop

BF_INSTR = {
    0x2b: INC, # +
    0x2d: DEC, # -
    0x2e: WRITE_STDOUT, # .
    0x2c: READ_STDIN, # ,
    0x5b: OPEN_LOOP, # [
    0x5d: CLOSE_LOOP, # ]
    0x3c: DEC_PTR, # <
    0x3e: INC_PTR # >
}