Nick Coghlan added the comment:
Sorry for the long delay in doing anything with this patch. Unfortunately, trunk has moved on quite a bit since this patch was submitted, and it's no longer directly applicable.
However, the basic principle is sound, so this is a new patch that aligns with the changes made in 3.4 to provide an iterator based bytecode introspection API. It also changes the indenting to be based on the structure of the bytecode disassembly - nested lines start aligned with the opcode *name* on the preceding line. This will get unreadable with more than two or three levels of nesting, but at that point, hard to read disassembly for the top level function is the least of your worries. (A potentially useful option may to be add a flag to turn off the implicit recursion, easily restoring the old single level behaviour. I'd like the recursive version to be the default though, since it's far more useful given that Python 3 comprehensions all involve a nested code object)
A descriptive header makes the new output more self-explanatory. Note that I did try repeating the code object repr from the LOAD_CONST opcode in the new header - it was pretty unreadable, and redundant given the preceding line of disassembly.
Two examples, one showing Torsten's list comprehension from above, and another showing that the nested line numbers work properly.
This can't be applied as is - it's still missing tests, docs, and fixes to disassembly output tests that assume the old behaviour.
dis.dis('[x**2 for x in range(3)]')
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7f459ec4a0c0, file "<dis>", line 1>)
Disassembly for nested code object
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
6 FOR_ITER 16 (to 25)
9 STORE_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 LOAD_CONST 0 (2)
18 BINARY_POWER
19 LIST_APPEND 2
22 JUMP_ABSOLUTE 6
25 RETURN_VALUE
3 LOAD_CONST 1 ('<listcomp>')
6 MAKE_FUNCTION 0
9 LOAD_NAME 0 (range)
12 LOAD_CONST 2 (3)
15 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
18 GET_ITER
19 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
22 RETURN_VALUE
... print("Hello")
... def g():
... for x in range(10):
... yield x
... return g
...
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 1 ('Hello')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
3 10 LOAD_CONST 2 (<code object g at 0x7f459ec4a540, file "<stdin>", line 3>)
Disassembly for nested code object
4 0 SETUP_LOOP 25 (to 28)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (10)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 GET_ITER
13 FOR_ITER 11 (to 27)
16 STORE_FAST 0 (x)
5 19 LOAD_FAST 0 (x)
22 YIELD_VALUE
23 POP_TOP
24 JUMP_ABSOLUTE 13
27 POP_BLOCK
28 LOAD_CONST 0 (None)
31 RETURN_VALUE
13 LOAD_CONST 3 ('f.<locals>.g')
16 MAKE_FUNCTION 0
19 STORE_FAST 0 (g)
6 22 LOAD_FAST 0 (g)
25 RETURN_VALUE
----------
Added file: http://bugs.python.org/file36565/issue11822_nested_disassembly.diff
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue11822>
_______________________________________