1
0
infernal-interpreter/AsciiPainter.py

98 lines
3.5 KiB
Python
Raw Normal View History

import re
import subprocess
NORMAL_COLOR = '\033[0m'
REG_STATUS_TO_COLOR = {
"insert": '\033[32m',
"change": '\033[33m',
"remove": '\033[31m',
"none": '\033[0m',
"jump": '\033[36m'
}
class AsciiPainter:
def __init__ (self, registers=None, max_stack_size=8, stack_draw_mode="up"):
self.registers = registers if registers else REGISTERS
self.states = []
self.max_stack_size = max_stack_size
self.stack_draw_mode = stack_draw_mode
def saveState (self, emu, line_nr=None):
# Init state
state = []
self.states.append(state)
# Write opcode to state
if line_nr != None:
signature = emu.getLineSignature(line_nr)
for token in signature:
state.append({ 'state': 'none', 'val': token })
#
for i in range(3-len(state)): state.append({'state':'none', 'val': ''})
for i in range(len(state)-3): state.pop()
state.append({'state':'none', 'val':''})
# Write registers to state
for reg_name in self.registers:
if reg_name =="":
state.append({'state':'none', 'val':''})
continue
reg_state = emu.regState(reg_name)
state.append({ 'state': reg_state, 'val': emu.getVal(reg_name) })
# Write stack to state
stack_base_pointer = emu.getVal('%rbp')
print(emu.last_sp, emu.getVal('%rsp'))
base_sp = emu.getVal('%rsp')
assert(isinstance(emu.getVal('%rsp'), (int, long)))
state.append({'state':'none', 'val': ''})
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]})
else:
state.append({'state': 'none', 'val': ''})
for index in range(0, self.max_stack_size):
stack_i = base_sp + index
print(index, stack_i)
if stack_i < emu.max_stack_size:
state.append({ 'state': emu.regState("m"+str(stack_i)), 'val': emu.stack[stack_i] })
if stack_base_pointer == index:
stack_base_pointer = emu.stack[base_pointer]
# TODO: Draw stack frame seperators
else:
state.append({'state':'none', 'val': ''})
def to_string (self, emu):
number_states = len(self.states)
number_state_vars = len(self.states[0])
term_width = int(subprocess.check_output(['tput', 'cols']))
number_states_pr_block = term_width / (10+2) - 1
separator = '-' * term_width
l = []
for base_state in range(0, number_states, number_states_pr_block):
l.append(separator)
for var_i in range(0, number_state_vars):
l.append('{:10}'.format(self.nameOfVar(var_i-4)))
for state_i in range(0, min(number_states_pr_block, number_states - base_state)):
var = self.states[base_state+state_i][var_i]
l.append('{}{:>10}{} '.format(REG_STATUS_TO_COLOR[var['state']], var['val'], NORMAL_COLOR))
l.append('\n')
l.append(separator)
return ''.join(l)
def nameOfVar (self, i):
if i < 0: return ''
if i < len(self.registers):
return self.registers[i]
elif i != len(self.registers):
state_i = i-len(self.registers) - 2
return 'TOS{}{}'.format('+' if state_i < 0 else '-', abs(state_i))
else:
return ''
def __str__ (self):
return 'TikzPainter[]'