Compare commits

...

5 Commits

3 changed files with 67 additions and 15 deletions

View File

@ -1,4 +1,5 @@
from dpdebugger import Debugger
from vm import VMException, VMExceptionType, VMStatus
from dataclasses import dataclass
from typing import cast
import math
@ -86,13 +87,41 @@ class DebuggerUI:
user_input = self.commands_history[0]
self.history_index = 0
self.commands_history.appendleft("")
dbg_output = self.dbg.do_command(user_input.split())
self.terminal_panel.write(dbg_output)
try:
dbg_output = self.dbg.do_command(user_input.split())
except VMException as vme:
self._terminal_append(
"VM Exception: " + vme.message
)
return
# self._terminal_append(dbg_output)
self._terminal_append(dbg_output)
self._display_source_lines()
self.commands_history[0] = user_input
def _terminal_append(self, text: str):
self.terminal_panel.write(text)
viewport_height = self.terminal_panel.get_viewport_height()
contents = self.terminal_panel.get().split('\n')[-viewport_height:]
self.terminal_panel.set_text("\n".join(contents))
def _display_source_lines(self):
active_line = self.dbg.get_current_source_line_number()
if self.dbg._vm.status == VMStatus.FINISHED:
return
try:
active_line = self.dbg.get_current_source_line_number()
except KeyError:
self._terminal_append(
"Cant find source line your are on. "
"May be you reached end of program. "
)
self._terminal_append(
"Please type \"reset\" to reset vm "
"it's initial state"
)
return
lines = _get_source_lines(
srcline=active_line,
lines=self.srclines,

View File

@ -75,7 +75,8 @@ class Debugger:
"run": self._run,
"r": self._run,
"inspect": self._inspect,
"i": self._inspect
"i": self._inspect,
"reset": self._reset
}
def do_command(self, command: list[str]) -> str:
@ -84,6 +85,13 @@ class Debugger:
return "Unknown command"
return self._callbacks_table[callback_name](command[1:])
def get_current_source_line_number(self) -> int:
return self._dbg_dict["instructions"][self._vm.pc.value]['srcline']
def _reset(self, args: list[str]) -> str:
self._vm.reset()
return "VM reseted"
def _step(self, args: list[str]) -> str:
try:
self._vm.step()
@ -93,9 +101,6 @@ class Debugger:
return f"Virtual machine exception: {e.message}"
return ""
def get_current_source_line_number(self) -> int:
return self._dbg_dict["instructions"][self._vm.pc.value]['srcline']
def _continue(self, args: list[str]) -> str:
try:
self._vm.continue_()
@ -134,7 +139,10 @@ class Debugger:
f"z: {flags.z}\n"
)
elif re.fullmatch(r'r\d+', to_print):
elif re.fullmatch(
# r0-r255
r'r(0|[1-9][0-9]|1[0-9][0-9]|2[1-4][1-9]|25[1-5])',
to_print):
index = int(to_print[1:])
return f"{to_print}: {self._vm.registers[index].value}"

View File

@ -25,6 +25,11 @@ class VMCC(IntFlag):
NEGATIVE = 1 << 1
ZERO = 1 << 0
class VMStatus(Enum):
RUNNING = auto()
INITED = auto()
FINISHED = auto()
@dataclass
class Breakpoint(Exception):
address: int
@ -48,15 +53,12 @@ class VM:
registers: list[c_int32]
breakpoints: set[int]
_vm_flags: VMFlags
status: VMStatus
def __init__(self, mem: bytearray):
self.mem: bytearray = mem
self.cc: VMCC = VMCC(0)
self.pc: c_uint32 = c_uint32(0)
self.registers: list[c_int32] = [c_int32(0) for _ in range(256)]
self.breakpoints: set[int] = set()
self._vm_flags: VMFlags = VMFlags(0)
self._initial_mem = mem.copy()
self.__init_callbacks__()
self.reset()
def __init_callbacks__(self):
VM.instr_callbacks = {
@ -119,16 +121,27 @@ class VM:
self._branch_indexed_callback
}
def reset(self):
self.mem: bytearray = self._initial_mem.copy()
self.cc: VMCC = VMCC(0)
self.pc: c_uint32 = c_uint32(0)
self.registers: list[c_int32] = [c_int32(0) for _ in range(256)]
self.breakpoints: set[int] = set()
self._vm_flags: VMFlags = VMFlags(0)
self.status = VMStatus.INITED
def step(self) -> None:
"""
Make one step (only step into)
"""
if self._to_raw_bytes_offset(self.pc) > len(self.mem) - WORD_SIZE:
self.status = VMStatus.FINISHED
raise VMException(
VMExceptionType.END_OF_MEM,
self.pc.value,
"couldn't perform step because end of memory occured"
)
self.status = VMStatus.RUNNING
opcode, *_ = instr = self._fetch_instr()
opdesc = self._get_opcode_desc(opcode)
args: tuple[int, ...] = self._parse_instr_fields(bytes(instr))
@ -148,14 +161,16 @@ class VM:
if self.pc.value in self.breakpoints:
raise Breakpoint(self.pc.value)
self.step()
self.status = VMStatus.FINISHED
def run(self) -> None:
"""
Run from very beginning
"""
self.pc = c_uint32(0)
self.reset()
while (self._to_raw_bytes_offset(self.pc.value) < len(self.mem)):
self.continue_()
self.status = VMStatus.FINISHED
def _fetch_instr(self) -> bytearray:
"""