Refactor BrainFuck interpreter to use a Registers class for state management; introduce Lua interpreter with basic structure and register handling.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from sys import stdin, stdout
|
||||
from os import PathLike
|
||||
from interpreter import Interpreter, opcode
|
||||
from interpreter import Interpreter, Registers, opcode
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -32,48 +32,62 @@ class BrainFuckByteCodeCompiler:
|
||||
)
|
||||
|
||||
|
||||
class BrainFuckRegisters(Registers):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.memory_pointer: int = 0
|
||||
|
||||
|
||||
class BrainFuckInterpreter(Interpreter):
|
||||
def __init__(self, bits=8, memsize=None) -> None:
|
||||
super().__init__(bits, memsize)
|
||||
self._registers: BrainFuckRegisters = BrainFuckRegisters()
|
||||
|
||||
def load_program(self, program: bytearray) -> None:
|
||||
super().load_program(program)
|
||||
self._registers.memory_pointer = len(program) + 1
|
||||
|
||||
@opcode(BrainFuckByteCode[">"])
|
||||
def forward(self):
|
||||
self._memory_pointer += 1
|
||||
self._registers.memory_pointer += 1
|
||||
|
||||
@opcode(BrainFuckByteCode["<"])
|
||||
def backward(self):
|
||||
self._memory_pointer -= 1
|
||||
self._registers.memory_pointer -= 1
|
||||
|
||||
@opcode(BrainFuckByteCode["+"])
|
||||
def increment(self):
|
||||
val = self._memory[self._memory_pointer]
|
||||
self._memory[self._memory_pointer] = (val + 1) % 256
|
||||
val = self._memory[self._registers.memory_pointer]
|
||||
self._memory[self._registers.memory_pointer] = (val + 1) % 256
|
||||
|
||||
@opcode(BrainFuckByteCode["-"])
|
||||
def decrement(self):
|
||||
val = self._memory[self._memory_pointer]
|
||||
self._memory[self._memory_pointer] = (val - 1) & 255
|
||||
val = self._memory[self._registers.memory_pointer]
|
||||
self._memory[self._registers.memory_pointer] = (val - 1) & 255
|
||||
|
||||
@opcode(BrainFuckByteCode["."])
|
||||
def io_in(self):
|
||||
stdout.write(chr(self._memory[self._memory_pointer]))
|
||||
def io_out(self):
|
||||
stdout.write(chr(self._memory[self._registers.memory_pointer]))
|
||||
|
||||
@opcode(BrainFuckByteCode[","])
|
||||
def io_out(self):
|
||||
def io_in(self):
|
||||
stdout.flush()
|
||||
self._memory[self._memory_pointer] = ord(stdin.read(1))
|
||||
self._memory[self._registers.memory_pointer] = ord(stdin.read(1))
|
||||
|
||||
@opcode(BrainFuckByteCode["["])
|
||||
def loop_start(self):
|
||||
# Ignore opcode if mem_pointer == 0
|
||||
if self._memory[self._memory_pointer] > 0:
|
||||
if self._memory[self._registers.memory_pointer] > 0:
|
||||
pass
|
||||
elif self._memory[self._memory_pointer] == 0:
|
||||
self._program_counter = self.findNext() - 1
|
||||
elif self._memory[self._registers.memory_pointer] == 0:
|
||||
self._registers.program_counter = self.findNext() - 1
|
||||
|
||||
@opcode(BrainFuckByteCode["]"])
|
||||
def start_end(self):
|
||||
self._program_counter = self.findNext(-1)
|
||||
self._registers.program_counter = self.findNext(-1)
|
||||
|
||||
def findNext(self, incrementValue: int = 1) -> int:
|
||||
search_pointer = self._program_counter + incrementValue
|
||||
search_pointer = self._registers.program_counter + incrementValue
|
||||
bracket_counter = 1
|
||||
while bracket_counter != 0:
|
||||
opcode = self._memory[search_pointer]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from .__interpreter import Interpreter, opcode
|
||||
from .__interpreter import Interpreter, Registers, opcode
|
||||
|
||||
__all__ = ["Interpreter", "opcode"]
|
||||
__all__ = ["Interpreter", "Registers", "opcode"]
|
||||
@@ -9,7 +9,7 @@ from .util import hexdump
|
||||
Operation: TypeAlias = str | int
|
||||
Subroutine: TypeAlias = Callable
|
||||
|
||||
OPCODE_HEADER = "__enterpreter__opcode"
|
||||
OPCODE_HEADER = "__interpreter__opcode"
|
||||
|
||||
|
||||
def opcode(opcode: Operation):
|
||||
@@ -20,54 +20,60 @@ def opcode(opcode: Operation):
|
||||
return _helper
|
||||
|
||||
|
||||
class Registers:
|
||||
def __init__(self) -> None:
|
||||
self.program_counter: int = 0
|
||||
|
||||
|
||||
class Memory:
|
||||
def __init__(self, size: int) -> None:
|
||||
self.__memory_size: int = size
|
||||
self.__memory: bytearray = bytearray(self.__memory_size)
|
||||
|
||||
def __getitem__(self, idx) -> int:
|
||||
return self.__memory[idx]
|
||||
|
||||
def __setitem__(self, idx, value) -> None:
|
||||
self.__memory[idx] = value
|
||||
|
||||
def dump(self):
|
||||
return self.__memory
|
||||
|
||||
|
||||
class Interpreter:
|
||||
def __init__(self, bits=8, memsize=None) -> None:
|
||||
memsize = memsize or 2**bits
|
||||
self.__bits = bits
|
||||
|
||||
self.__memory_max_size = 2**self.__bits
|
||||
self.__memory_size = min(memsize, self.__memory_max_size)
|
||||
|
||||
self._memory = bytearray(self.__memory_size)
|
||||
self._memory_pointer: int = 0
|
||||
|
||||
self._program_counter: int = 0
|
||||
self.__memory_size = min(memsize or 2**bits, self.__memory_max_size)
|
||||
self._memory: Memory = Memory(self.__memory_size)
|
||||
self._registers: Registers = Registers()
|
||||
|
||||
self.__operations: dict[Operation, Subroutine] = dict()
|
||||
self.__init_opcodes()
|
||||
|
||||
def __init_opcodes(self):
|
||||
for func_name, func in getmembers(
|
||||
self, lambda obj: hasattr(obj, OPCODE_HEADER)
|
||||
):
|
||||
self._register_opcode(getattr(func, OPCODE_HEADER), func)
|
||||
|
||||
def _register_opcode(self, opcode: Operation, callback: Subroutine):
|
||||
self.__operations[opcode] = callback
|
||||
|
||||
def is_running(self) -> bool:
|
||||
return self._memory[self._program_counter] != 0
|
||||
for _, func in getmembers(self, lambda obj: hasattr(obj, OPCODE_HEADER)):
|
||||
opcode = getattr(func, OPCODE_HEADER)
|
||||
self.__operations[opcode] = func
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
# Keep running until you reach a null byte
|
||||
while self.is_running():
|
||||
opcode = self._memory[self._program_counter]
|
||||
while (opcode := self._memory[self._registers.program_counter]) != 0:
|
||||
self.__operations[opcode]()
|
||||
self._program_counter += 1
|
||||
self._registers.program_counter += 1
|
||||
except Exception as e:
|
||||
self.dump()
|
||||
print_exception(e)
|
||||
|
||||
def dump(self):
|
||||
hexdump(
|
||||
data=self._memory,
|
||||
program_counter=self._program_counter,
|
||||
memory_pointer=self._memory_pointer,
|
||||
data=self._memory.dump(),
|
||||
program_counter=self._registers.program_counter,
|
||||
memory_pointer=self._registers.memory_pointer
|
||||
)
|
||||
pprint(self.__operations)
|
||||
|
||||
def load_program(self, program: bytearray) -> None:
|
||||
self._memory[: len(program)] = program[:]
|
||||
|
||||
# Set new pointer immediately after code
|
||||
self._memory_pointer = len(program) + 1
|
||||
|
||||
0
src/lua/__init__.py
Normal file
0
src/lua/__init__.py
Normal file
16
src/lua/__lua.py
Normal file
16
src/lua/__lua.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from interpreter import Interpreter, Registers, opcode
|
||||
|
||||
|
||||
class LuaRegisters(Registers):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
class LuaByteCodeInterpreter(Interpreter):
|
||||
def __init__(self, bits=8, memsize=None) -> None:
|
||||
super().__init__(bits, memsize)
|
||||
self._registers = LuaRegisters()
|
||||
|
||||
...
|
||||
|
||||
def lua():
|
||||
...
|
||||
0
src/lua/__main__.py
Normal file
0
src/lua/__main__.py
Normal file
Reference in New Issue
Block a user