DebugClients/Python/coverage/bytecode.py

branch
Py2 comp.
changeset 3495
fac17a82b431
parent 790
2c0ea0163ef4
child 3499
f2d4b02c7e88
equal deleted inserted replaced
3485:f1cbc18f88b2 3495:fac17a82b431
1 """Bytecode manipulation for coverage.py""" 1 """Bytecode manipulation for coverage.py"""
2 2
3 import opcode, sys, types 3 import opcode, types
4
5 from .backward import byte_to_int
4 6
5 class ByteCode(object): 7 class ByteCode(object):
6 """A single bytecode.""" 8 """A single bytecode."""
7 def __init__(self): 9 def __init__(self):
10 # The offset of this bytecode in the code object.
8 self.offset = -1 11 self.offset = -1
12
13 # The opcode, defined in the `opcode` module.
9 self.op = -1 14 self.op = -1
15
16 # The argument, a small integer, whose meaning depends on the opcode.
10 self.arg = -1 17 self.arg = -1
18
19 # The offset in the code object of the next bytecode.
11 self.next_offset = -1 20 self.next_offset = -1
21
22 # The offset to jump to.
12 self.jump_to = -1 23 self.jump_to = -1
13 24
14 25
15 class ByteCodes(object): 26 class ByteCodes(object):
16 """Iterator over byte codes in `code`. 27 """Iterator over byte codes in `code`.
17 28
18 Returns `ByteCode` objects. 29 Returns `ByteCode` objects.
19 30
20 """ 31 """
32 # pylint: disable=R0924
21 def __init__(self, code): 33 def __init__(self, code):
22 self.code = code 34 self.code = code
23 self.offset = 0
24 35
25 if sys.hexversion > 0x03000000: 36 def __getitem__(self, i):
26 def __getitem__(self, i): 37 return byte_to_int(self.code[i])
27 return self.code[i]
28 else:
29 def __getitem__(self, i):
30 return ord(self.code[i])
31 38
32 def __iter__(self): 39 def __iter__(self):
33 return self 40 offset = 0
41 while offset < len(self.code):
42 bc = ByteCode()
43 bc.op = self[offset]
44 bc.offset = offset
34 45
35 def __next__(self): 46 next_offset = offset+1
36 if self.offset >= len(self.code): 47 if bc.op >= opcode.HAVE_ARGUMENT:
37 raise StopIteration 48 bc.arg = self[offset+1] + 256*self[offset+2]
49 next_offset += 2
38 50
39 bc = ByteCode() 51 label = -1
40 bc.op = self[self.offset] 52 if bc.op in opcode.hasjrel:
41 bc.offset = self.offset 53 label = next_offset + bc.arg
54 elif bc.op in opcode.hasjabs:
55 label = bc.arg
56 bc.jump_to = label
42 57
43 next_offset = self.offset+1 58 bc.next_offset = offset = next_offset
44 if bc.op >= opcode.HAVE_ARGUMENT: 59 yield bc
45 bc.arg = self[self.offset+1] + 256*self[self.offset+2]
46 next_offset += 2
47
48 label = -1
49 if bc.op in opcode.hasjrel:
50 label = next_offset + bc.arg
51 elif bc.op in opcode.hasjabs:
52 label = bc.arg
53 bc.jump_to = label
54
55 bc.next_offset = self.offset = next_offset
56 return bc
57
58 next = __next__ # Py2k uses an old-style non-dunder name.
59 60
60 61
61 class CodeObjects(object): 62 class CodeObjects(object):
62 """Iterate over all the code objects in `code`.""" 63 """Iterate over all the code objects in `code`."""
63 def __init__(self, code): 64 def __init__(self, code):
64 self.stack = [code] 65 self.stack = [code]
65 66
66 def __iter__(self): 67 def __iter__(self):
67 return self 68 while self.stack:
68
69 def __next__(self):
70 if self.stack:
71 # We're going to return the code object on the stack, but first 69 # We're going to return the code object on the stack, but first
72 # push its children for later returning. 70 # push its children for later returning.
73 code = self.stack.pop() 71 code = self.stack.pop()
74 for c in code.co_consts: 72 for c in code.co_consts:
75 if isinstance(c, types.CodeType): 73 if isinstance(c, types.CodeType):
76 self.stack.append(c) 74 self.stack.append(c)
77 return code 75 yield code
78
79 raise StopIteration
80
81 next = __next__
82
83 #
84 # eflag: FileType = Python2

eric ide

mercurial