1
0

Porting to Python 3 v2: Something works now

This commit is contained in:
Jon Michael Aanes 2024-07-10 01:09:11 +02:00
parent e0f8c0c2a1
commit 683c22cea2
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
5 changed files with 38 additions and 45 deletions

View File

@ -19,12 +19,12 @@ class AsciiPainter:
self.max_stack_size = max_stack_size self.max_stack_size = max_stack_size
self.stack_draw_mode = stack_draw_mode self.stack_draw_mode = stack_draw_mode
def saveState (self, emu, line_nr=None): def saveState (self, emu, line_nr: int | None=None) -> None:
# Init state # Init state
state = [] state = []
self.states.append(state) self.states.append(state)
# Write opcode to state # Write opcode to state
if line_nr != None: if line_nr is not None:
signature = emu.getLineSignature(line_nr) signature = emu.getLineSignature(line_nr)
for token in signature: for token in signature:
state.append({ 'state': 'none', 'val': token }) state.append({ 'state': 'none', 'val': token })
@ -42,7 +42,7 @@ class AsciiPainter:
# Write stack to state # Write stack to state
stack_base_pointer = emu.getVal('%rbp') stack_base_pointer = emu.getVal('%rbp')
base_sp = emu.getVal('%rsp') base_sp = emu.getVal('%rsp')
assert(isinstance(emu.getVal('%rsp'), (int, long))) assert(isinstance(emu.getVal('%rsp'), int))
state.append({'state':'none', 'val': ''}) state.append({'state':'none', 'val': ''})
if emu.regState('m'+str(base_sp-1)) == 'remove': if emu.regState('m'+str(base_sp-1)) == 'remove':
state.append({'state': emu.regState('m'+str(base_sp-1)), 'val': emu.stack[base_sp-1]}) state.append({'state': emu.regState('m'+str(base_sp-1)), 'val': emu.stack[base_sp-1]})
@ -58,47 +58,48 @@ class AsciiPainter:
else: else:
state.append({'state':'none', 'val': ''}) state.append({'state':'none', 'val': ''})
def getWidthOfColumns(self, number_states, number_states_pr_block, number_state_vars): def getWidthOfColumns(self, number_states: int, number_states_per_block: int, number_state_vars: int) -> list[int]:
widths = [0 for i in range(0, number_states_pr_block)] widths = [0 for i in range(0, number_states_per_block)]
for base_state in range(0, number_states, number_states_pr_block): for base_state in range(0, number_states, number_states_per_block):
for var_i in range(0, number_state_vars): for var_i in range(0, number_state_vars):
for state_i in range(0, min(number_states_pr_block, number_states - base_state)): for state_i in range(0, min(number_states_per_block, number_states - base_state)):
width = len(str(self.states[base_state+state_i][var_i]['val'])) width = len(str(self.states[base_state+state_i][var_i]['val']))
widths[state_i] = max(widths[state_i], width) widths[state_i] = max(widths[state_i], width)
return widths return widths
def getWidthOfNameColumn (self, number_state_vars): def getWidthOfNameColumn (self, number_state_vars: int) -> int:
widest = 0 widest = 0
for var_i in range(0, number_state_vars): for var_i in range(0, number_state_vars):
widest = max(widest, len(self.nameOfVar(var_i-4))) widest = max(widest, len(self.nameOfVar(var_i-4)))
return widest return widest
def to_string (self, emu): def to_string (self, emu) -> str:
number_states = len(self.states) number_states = len(self.states)
number_state_vars = len(self.states[0]) number_state_vars = len(self.states[0])
term_width = int(subprocess.check_output(['tput', 'cols'])) term_width = int(subprocess.check_output(['tput', 'cols']))
number_states_pr_block = term_width / (10+2) - 1 number_states_per_block: int = term_width // (10+2) - 1
separator = '-' * term_width separator = '-' * term_width
l = [] output: list[str] = []
name_fmt = '{}{:'+str(self.getWidthOfNameColumn(number_state_vars))+'} ' name_fmt = '{}{:'+str(self.getWidthOfNameColumn(number_state_vars))+'} '
column_fmt = map(lambda width: '{}{:>'+str(width)+'} ', self.getWidthOfColumns(number_states, number_states_pr_block, number_state_vars)) column_fmt = ['{}{:>'+str(width)+'} ' for width in self.getWidthOfColumns(number_states, number_states_per_block, number_state_vars)]
for base_state in range(0, number_states, number_states_pr_block): for base_state in range(0, number_states, number_states_per_block):
l.append(separator) output.append(separator)
for var_i in range(0, number_state_vars): for var_i in range(0, number_state_vars):
l.append(name_fmt.format(NORMAL_COLOR, self.nameOfVar(var_i-4))) output.append(name_fmt.format(NORMAL_COLOR, self.nameOfVar(var_i-4)))
for state_i in range(0, min(number_states_pr_block, number_states - base_state)): for state_i in range(0, min(number_states_per_block, number_states - base_state)):
var = self.states[base_state+state_i][var_i] var = self.states[base_state+state_i][var_i]
l.append(column_fmt[state_i].format(REG_STATUS_TO_COLOR[var['state']], var['val'], NORMAL_COLOR)) output.append(column_fmt[state_i].format(REG_STATUS_TO_COLOR[var['state']], var['val'], NORMAL_COLOR))
l.append('\n') output.append('\n')
l.append(separator) output.append(separator)
return ''.join(l) return ''.join(output)
def nameOfVar (self, i): def nameOfVar (self, i):
if i < 0: return '' if i < 0:
return ''
if i < len(self.registers): if i < len(self.registers):
return self.registers[i] return self.registers[i]
elif i != len(self.registers): elif i != len(self.registers):

View File

@ -49,7 +49,7 @@ class Emulator:
self.last_sp = i-1 self.last_sp = i-1
def setRegs (self, **reg_dict): def setRegs (self, **reg_dict):
for reg_name, reg_val in reg_dict.iteritems(): for reg_name, reg_val in reg_dict.items():
assert(reg_name[0] != '%') assert(reg_name[0] != '%')
self.registers["%"+reg_name] = reg_val self.registers["%"+reg_name] = reg_val
@ -115,7 +115,7 @@ class Emulator:
if len(conditions)>0 and self.status["i"]: if len(conditions)>0 and self.status["i"]:
raise Junk.JunkComparisonException(*self.status['i']) raise Junk.JunkComparisonException(*self.status['i'])
and_, or_ = True, False and_, or_ = True, False
for cnd_name, cnd_val in conditions.iteritems(): for cnd_name, cnd_val in conditions.items():
if self.status[cnd_name] == cnd_val: if self.status[cnd_name] == cnd_val:
or_ = True or_ = True
else: else:
@ -129,9 +129,9 @@ class Emulator:
def iterate (self): def iterate (self):
old_rip = self.registers['%rip'] old_rip = self.registers['%rip']
self.last_sp = self.registers['%rsp'] self.last_sp = self.registers['%rsp']
if self.registers['%rip'] >= len(self.code) or isinstance(self.registers['%rip'], Junk.Junk): if isinstance(old_rip , Junk.Junk) or old_rip >= len(self.code):
return None return None
if not isinstance(self.registers['%rip'], (int, long)): if not isinstance(self.registers['%rip'], int):
raise InternalExecutionException("Register %rip should be integer, but was "+str(self.registers['%rip'])) raise InternalExecutionException("Register %rip should be integer, but was "+str(self.registers['%rip']))
instruct = self.code[self.registers['%rip']] instruct = self.code[self.registers['%rip']]
opcode = instruct[0] opcode = instruct[0]
@ -149,7 +149,7 @@ class Emulator:
def __iter__(self): def __iter__(self):
return self return self
def next(self): def __next__(self):
output = self.iterate() output = self.iterate()
if output is None: if output is None:
raise StopIteration() raise StopIteration()
@ -157,5 +157,5 @@ class Emulator:
return output return output
def getUsedRegisters (self): def getUsedRegisters (self):
return [reg_name for reg_name, reg_val in self.registers.iteritems() if not isinstance(reg_val, Junk.Junk)] return [reg_name for reg_name, reg_val in self.registers.items() if not isinstance(reg_val, Junk.Junk)]

View File

@ -1,23 +1,24 @@
import dataclasses
class JunkComparisonException(BaseException): class JunkComparisonException(BaseException):
def __str__ (self): def __str__ (self):
return "Attempting to perform calculations involving junk values." return "Attempting to perform calculations involving junk values."
@dataclasses.dataclass
class Junk: class Junk:
represents: str | None = None
def __init__ (self, represents: str = None):
assert represents is None or isinstance(represents, str)
self.repr = represents
def __str__ (self): def __str__ (self):
if self.repr: return '[{}]'.format(self.represents or 'junk')
return '['+self.repr+']'
return "[junk]"
def __repr__ (self): def __repr__ (self):
return self.__str__() return self.__str__()
def __format__ (self, format):
return self.__str__()
def __add__ (self, other): def __add__ (self, other):
return self return self

View File

@ -36,7 +36,7 @@ class TikzPainter:
pos -= 1.5 pos -= 1.5
base_sp = min(emu.last_sp, emu.getVal('%rsp')) base_sp = min(emu.last_sp, emu.getVal('%rsp'))
pos += 0.5 * max(0, emu.getVal('%rsp')-emu.last_sp) pos += 0.5 * max(0, emu.getVal('%rsp')-emu.last_sp)
assert(isinstance(emu.getVal('%rsp'), (int, long))) assert(isinstance(emu.getVal('%rsp'), int))
for index in range(base_sp, 3+min(emu.max_stack_size, emu.getVal('%rsp')+self.max_stack_size)): for index in range(base_sp, 3+min(emu.max_stack_size, emu.getVal('%rsp')+self.max_stack_size)):
reg_state = emu.regState("m"+str(index)) reg_state = emu.regState("m"+str(index))
reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10" reg_dect = "register_node, fill="+self.getRegColor(reg_state)+"!10"

View File

@ -13,13 +13,4 @@ Compiling the LaTeX requires both a LaTeX compiler, and packages
Please ignore the `/tests` folder. It is very old, and unsupported, Please ignore the `/tests` folder. It is very old, and unsupported,
but kept for archival purposes. but kept for archival purposes.
## License ##
License is `beerware`:
<jonjmaa@gmail.com> wrote this program. As long as you retain
this notice you can do whatever you want with this stuff. If we
meet some day, and you think this stuff is worth it, you can buy
me a beer in return.
""" """