diff -r dda33191f7f5 -r 7cead6bf5832 Lib/dis.py --- a/Lib/dis.py Sun Apr 10 12:59:16 2011 +0300 +++ b/Lib/dis.py Sun Apr 10 23:49:35 2011 +1000 @@ -2,6 +2,7 @@ import sys import types +import collections from opcode import * from opcode import __all__ as _opcodes_all @@ -144,8 +145,11 @@ """Print details of methods, functions, or code to stdout.""" print(code_info(co)) -def disassemble(co, lasti=-1): - """Disassemble a code object.""" +OpInfo = collections.namedtuple("OpInfo", + "opindex opcode opname oparg details starts_line is_jump_target") + +def get_opinfo(co): + """Iterate over the opcodes in a code object""" code = co.co_code labels = findlabels(code) linestarts = dict(findlinestarts(co)) @@ -154,42 +158,66 @@ extended_arg = 0 free = None while i < n: + opindex = i op = code[i] - if i in linestarts: - if i > 0: - print() - print("%3d" % linestarts[i], end=' ') - else: - print(' ', end=' ') - - if i == lasti: print('-->', end=' ') - else: print(' ', end=' ') - if i in labels: print('>>', end=' ') - else: print(' ', end=' ') - print(repr(i).rjust(4), end=' ') - print(opname[op].ljust(20), end=' ') + linestart = linestarts.get(i, None) + is_jump_target = i in labels i = i+1 + oparg = None + details = '' if op >= HAVE_ARGUMENT: oparg = code[i] + code[i+1]*256 + extended_arg extended_arg = 0 i = i+2 if op == EXTENDED_ARG: extended_arg = oparg*65536 - print(repr(oparg).rjust(5), end=' ') if op in hasconst: - print('(' + repr(co.co_consts[oparg]) + ')', end=' ') + details = repr(co.co_consts[oparg]) elif op in hasname: - print('(' + co.co_names[oparg] + ')', end=' ') + details = co.co_names[oparg] elif op in hasjrel: - print('(to ' + repr(i + oparg) + ')', end=' ') + details = "to " + repr(i + oparg) elif op in haslocal: - print('(' + co.co_varnames[oparg] + ')', end=' ') + details = co.co_varnames[oparg] elif op in hascompare: - print('(' + cmp_op[oparg] + ')', end=' ') + details = cmp_op[oparg] elif op in hasfree: if free is None: free = co.co_cellvars + co.co_freevars - print('(' + free[oparg] + ')', end=' ') + details = free[oparg] + yield OpInfo(opindex, op, opname[op], oparg, + details, linestart, is_jump_target) + +def disassemble(co, lasti=-1): + """Disassemble a code object.""" + for opinfo in get_opinfo(co): + # Column: Source code line number + if opinfo.starts_line is not None: + if opinfo.opindex > 0: + print() + print("%3d" % opinfo.starts_line, end=' ') + else: + print(' ', end=' ') + # Column: Current instruction indicator + if opinfo.opindex == lasti: + print('-->', end=' ') + else: + print(' ', end=' ') + # Column: Jump target marker + if opinfo.is_jump_target: + print('>>', end=' ') + else: + print(' ', end=' ') + # Column: Instruction number + print(repr(opinfo.opindex).rjust(4), end=' ') + # Column: Opcode name + print(opinfo.opname.ljust(20), end=' ') + # Column: Opcode argument + if opinfo.oparg is not None: + print(repr(opinfo.oparg).rjust(5), end=' ') + # Column: Opcode argument details + if opinfo.details: + print('(' + opinfo.details + ')', end=' ') print() def _disassemble_bytes(code, lasti=-1, varnames=None, names=None,