I want to store the information returned by the dis function of the dis module in a structured way, using a dict, associating the mnemonics of each code of a line to the correspondent line number.
Note: Instruction is a subclass of _Instruction, defined in the dis module as a namedtuple.
Output:
disassembled_dict =
{
147: [ Instruction(opname='LOAD_FAST', opcode=124, arg=0, arg1=0, arg2=0, argval='x', argrepr='x', offset=0, starts_line=147, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=1, arg1=1, arg2=0, argval=1, argrepr='1', offset=3, starts_line=None, is_jump_target=False),
Instruction(opname='INPLACE_ADD', opcode=55, arg=None, arg1=None, arg2=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='STORE_FAST', opcode=125, arg=0, arg1=0, arg2=0, argval='x', argrepr='x', offset=7, starts_line=None, is_jump_target=False)
]
148: [ Instruction(opname='LOAD_FAST', opcode=124, arg=0, arg1=0, arg2=0, argval='x', argrepr='x', offset=10, starts_line=148, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, arg1=2, arg2=0, argval=2, argrepr='2', offset=13, starts_line=None, is_jump_target=False),
Instruction(opname='BINARY_POWER', opcode=19, arg=None, arg1=None, arg2=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, arg1=None, arg2=None, argval=None, argrepr='', offset=17, starts_line=None, is_jump_target=False)
]
}
Code:
import dis
def preatty_dis(function):
fcode = function.__code__
## call dis._get_instructions_bytes just the original dis function do
disassembled_raw = [instruction for instruction in
dis._get_instructions_bytes(fcode.co_code, fcode.co_varnames,
fcode.co_names, fcode.co_consts,
fcode.co_cellvars + fcode.co_freevars,
dict(dis.findlinestarts(fcode)))]
iter_instructions = iter(disassembled_raw)
disassembled_dict = {}
line_pack = []
while True:
try:
if not(line_pack):
instruction = next(iter_instructions)
line_pack.append(instruction)
else:
instruction = line_pack[0]
if(instruction.starts_line):
instruction = next(iter_instructions)
while(instruction.starts_line is None):
line_pack.append(instruction)
instruction = next(iter_instructions)
else:
## line_pack[0] is the first mnemonic of the code line
## line_pack[0].starts_line is the number of the code line
disassembled_dict.update({line_pack[0].starts_line : (line_pack)})
line_pack = [instruction]
else:
disassembled_dict.update({line_pack[0].starts_line : (line_pack)})
line_pack = []
except StopIteration:
## append the last group
print(line_pack)
disassembled_dict.update({line_pack[0].starts_line : (line_pack)})
line_pack = []
break
return disassembled_dict
The code works on Python 3.5, but I'm sure there are many chances to make it more idiomatic, cleaner and more readable...
Suggestions?
disassembled_dict.update({line_pack[0].starts_line : (line_pack)}), but I think that is atomic, I can't split it up... \$\endgroup\$