Fix: rename enterpreter to interpreter

This commit is contained in:
2025-04-10 14:24:55 +01:00
parent 753f65384b
commit 17fd5f7acf
10 changed files with 59 additions and 17 deletions

View File

@@ -0,0 +1,73 @@
from collections.abc import Callable
from inspect import getmembers
from typing import TypeAlias
from traceback import print_exception
from pprint import pprint
from .util import hexdump
Operation: TypeAlias = str | int
Subroutine: TypeAlias = Callable
OPCODE_HEADER = "__enterpreter__opcode"
def opcode(opcode: Operation):
def _helper(func: Callable):
setattr(func, OPCODE_HEADER, opcode)
return func
return _helper
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.__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
def run(self) -> None:
try:
# Keep running until you reach a null byte
while self.is_running():
opcode = self._memory[self._program_counter]
self.__operations[opcode]()
self._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,
)
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