1
0
infernal-interpreter/infernal_interpreter/TikzPainter.py

174 lines
5.1 KiB
Python
Raw Permalink Normal View History

2017-11-20 12:07:07 +00:00
import re
REG_STATUS_TO_COLOR = {
2024-07-09 23:15:47 +00:00
'insert': 'green',
'change': 'yellow',
'remove': 'red',
'none': 'black',
'jump': 'orange',
}
DEFAULT_OPTIONS = """register_node/.style={rectangle, draw=black!30,
2018-02-06 19:56:33 +00:00
fill=black!5, very thick, minimum size=0.5,
minimum width=20mm}, text_node/.style={}"""
2024-07-09 23:15:47 +00:00
class TikzPainter:
def __init__(
2024-07-09 23:19:26 +00:00
self,
registers=None,
max_stack_size=8,
stack_draw_mode='up',
options=None,
2024-07-09 23:15:47 +00:00
):
2018-02-06 19:56:33 +00:00
self.registers = registers if registers else REGISTERS
self.text = []
self.pos_x = 0
self.max_stack_size = max_stack_size
self.stack_draw_mode = stack_draw_mode
self.options = options if options else DEFAULT_OPTIONS
2024-07-09 23:15:47 +00:00
def addText(self, str, *args):
text = re.sub(r'[^\\]%', '\\%', str.format(*args))
2018-02-06 19:56:33 +00:00
self.text.append(text)
2024-07-09 23:15:47 +00:00
def getRegColor(self, reg_state):
2018-02-06 19:56:33 +00:00
return REG_STATUS_TO_COLOR[reg_state]
2024-07-09 23:15:47 +00:00
def drawStackUpward(self, pos, emu, x):
2018-02-06 19:56:33 +00:00
base_pointer = emu.getVal('%rbp')
pos -= 1.5
base_sp = min(emu.last_sp, emu.getVal('%rsp'))
2024-07-09 23:15:47 +00:00
pos += 0.5 * max(0, emu.getVal('%rsp') - emu.last_sp)
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),
):
reg_state = emu.regState('m' + str(index))
reg_dect = 'register_node, fill=' + self.getRegColor(reg_state) + '!10'
self.addText(
'\t\\node[{}]() at ({}, {}){{{}}};\n',
reg_dect,
x,
pos,
emu.stack[index],
)
2018-02-06 19:56:33 +00:00
if base_pointer == index:
2024-07-09 23:15:47 +00:00
self.addText(
2024-07-09 23:19:26 +00:00
'\t\\draw ({0},{2}) -- ({1},{2});\n',
x - 1.1,
x + 1.1,
pos - 0.25,
2024-07-09 23:15:47 +00:00
)
2018-02-06 19:56:33 +00:00
base_pointer = emu.stack[base_pointer]
pos -= 0.5
return pos, x
2024-07-09 23:15:47 +00:00
def drawStackDownward(self, pos, emu, x):
2018-02-06 19:56:33 +00:00
pos -= 1
2024-07-09 23:15:47 +00:00
for index in range(
2024-07-09 23:19:26 +00:00
emu.getVal('%rsp') - 8,
max(emu.last_sp, emu.getVal('%rsp')),
2024-07-09 23:15:47 +00:00
):
reg_state = emu.regState('m' + str(index))
reg_dect = 'register_node, fill=' + self.getRegColor(reg_state) + '!10'
self.addText(
'\t\\node[{}]() at ({}, {}){{{}}};\n',
reg_dect,
x,
pos,
emu.stack[index],
)
2018-02-06 19:56:33 +00:00
pos -= 0.5
return pos, x
2024-07-09 23:15:47 +00:00
def saveState(self, emu, line_nr=None):
x = (self.pos_x + 1) * 2.5 - 0.5
2018-02-06 19:56:33 +00:00
self.pos_x += 1
# Draw register cells
pos = 0.5
for reg_name in self.registers:
pos -= 0.5
2024-07-09 23:15:47 +00:00
if reg_name == '':
2018-02-06 19:56:33 +00:00
continue
reg_state = emu.regState(reg_name)
2024-07-09 23:15:47 +00:00
reg_dect = 'register_node, fill=' + self.getRegColor(reg_state) + '!10'
self.addText(
'\t\\node[{}]() at ({}, {}){{{}}};\n',
reg_dect,
x,
pos,
emu.getVal(reg_name),
)
2018-02-06 19:56:33 +00:00
# Draw stack
2024-07-09 23:15:47 +00:00
if self.stack_draw_mode == 'up':
2018-02-06 19:56:33 +00:00
pos, x = self.drawStackUpward(pos, emu, x)
else:
pos, x = self.drawStackDownward(pos, emu, x)
# Draw line signature
if line_nr == None:
return
pos = 2
signature = emu.getLineSignature(line_nr)
for token in signature:
2024-07-09 23:15:47 +00:00
self.addText(
2024-07-09 23:19:26 +00:00
'\t\\node[text_node]() at ({}, {}){{{}}};\n',
x - 1.25,
pos,
token,
2024-07-09 23:15:47 +00:00
)
2018-02-06 19:56:33 +00:00
pos -= 0.5
2024-07-09 23:15:47 +00:00
def drawNames(self, emu):
2018-02-06 19:56:33 +00:00
x = 0
pos = 0
for reg_name in self.registers:
2024-07-09 23:15:47 +00:00
self.addText(
2024-07-09 23:19:26 +00:00
'\t\\node[text_node]() at ({}, {}){{{}}};\n',
x,
pos,
reg_name[1:],
2024-07-09 23:15:47 +00:00
)
2018-02-06 19:56:33 +00:00
pos -= 0.5
# Draw stack
2024-07-09 23:15:47 +00:00
if self.stack_draw_mode == 'up':
2018-02-06 19:56:33 +00:00
self.drawStackNamesUpward(pos, emu, x)
else:
self.drawStackNamesDownward(pos, emu, x)
2024-07-09 23:15:47 +00:00
def drawStackNamesUpward(self, pos, emu, x):
self.addText('\t\\node[text_node]() at ({}, {}){{TOS+1}};\n', x, pos - 0.5)
self.addText('\t\\node[text_node]() at ({}, {}){{TOS}};\n', x, pos - 1.0)
2018-02-06 19:56:33 +00:00
pos -= 1
2024-07-09 23:15:47 +00:00
for index in range(1, self.max_stack_size):
2018-02-06 19:56:33 +00:00
pos -= 0.5
2024-07-09 23:15:47 +00:00
self.addText(
2024-07-09 23:19:26 +00:00
'\t\\node[text_node]() at ({}, {}){{TOS-{}}};\n',
x,
pos,
index,
2024-07-09 23:15:47 +00:00
)
2018-02-06 19:56:33 +00:00
2024-07-09 23:15:47 +00:00
def to_string(self, emu):
PRE = (
""" \\documentclass{standalone}
2018-02-06 19:56:33 +00:00
\\usepackage{tikz}
\\begin{document}
2024-07-09 23:15:47 +00:00
\\begin{tikzpicture}["""
+ self.options
+ ']'
)
2018-02-06 19:56:33 +00:00
POST = """\\end{tikzpicture}
\\end{document}"""
self.drawNames(emu)
2024-07-09 23:15:47 +00:00
return PRE + ''.join(self.text) + POST
2018-02-06 19:56:33 +00:00
2024-07-09 23:15:47 +00:00
def __str__(self):
2018-02-06 19:56:33 +00:00
return 'TikzPainter[]'