1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5from __future__ import absolute_import, print_function, unicode_literals
6
7import dis
8import inspect
9
10
11# dis.dis only outputs to stdout. This is a modified version that
12# returns an iterator.
13def disassemble_as_iter(co):
14    if inspect.ismethod(co):
15        co = co.im_func
16    if inspect.isfunction(co):
17        co = co.func_code
18    code = co.co_code
19    n = len(code)
20    i = 0
21    extended_arg = 0
22    free = None
23    while i < n:
24        c = code[i]
25        op = ord(c)
26        opname = dis.opname[op]
27        i += 1;
28        if op >= dis.HAVE_ARGUMENT:
29            arg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg
30            extended_arg = 0
31            i += 2
32            if op == dis.EXTENDED_ARG:
33                extended_arg = arg * 65536L
34                continue
35            if op in dis.hasconst:
36                yield opname, co.co_consts[arg]
37            elif op in dis.hasname:
38                yield opname, co.co_names[arg]
39            elif op in dis.hasjrel:
40                yield opname, i + arg
41            elif op in dis.haslocal:
42                yield opname, co.co_varnames[arg]
43            elif op in dis.hascompare:
44                yield opname, dis.cmp_op[arg]
45            elif op in dis.hasfree:
46                if free is None:
47                    free = co.co_cellvars + co.co_freevars
48                yield opname, free[arg]
49            else:
50                yield opname, None
51        else:
52            yield opname, None
53