5
5
6
6
from __future__ import annotations
7
7
8
+ import collections
8
9
import dis
9
10
10
11
from types import CodeType
@@ -98,7 +99,9 @@ def walk(
98
99
99
100
100
101
TBranchTrail = tuple [set [TOffset ], Optional [TArc ]]
101
- TBranchTrails = dict [TOffset , list [TBranchTrail ]]
102
+ #TBranchTrails = dict[TOffset, list[TBranchTrail]]
103
+
104
+ TBranchTrails = dict [TOffset , dict [Optional [TArc ], set [TOffset ]]]
102
105
103
106
104
107
def branch_trails (code : CodeType ) -> TBranchTrails :
@@ -117,7 +120,7 @@ def branch_trails(code: CodeType) -> TBranchTrails:
117
120
arc from the original instruction's line to the new source line.
118
121
119
122
"""
120
- the_trails : TBranchTrails = {}
123
+ the_trails : TBranchTrails = collections . defaultdict ( lambda : collections . defaultdict ( set ))
121
124
iwalker = InstructionWalker (code )
122
125
for inst in iwalker .walk (follow_jumps = False ):
123
126
if not inst .jump_target :
@@ -131,7 +134,7 @@ def branch_trails(code: CodeType) -> TBranchTrails:
131
134
if from_line is None :
132
135
continue
133
136
134
- def walk_one_branch (start_at : TOffset ) -> TBranchTrail :
137
+ def walk_one_branch (start_at : TOffset ) -> tuple [ Optional [ TArc ], set [ TOffset ]] :
135
138
# pylint: disable=cell-var-from-loop
136
139
inst_offsets : set [TOffset ] = set ()
137
140
to_line = None
@@ -146,27 +149,26 @@ def walk_one_branch(start_at: TOffset) -> TBranchTrail:
146
149
to_line = - code .co_firstlineno
147
150
break
148
151
if to_line is not None :
149
- return inst_offsets , (from_line , to_line )
152
+ return (from_line , to_line ), inst_offsets
150
153
else :
151
- return set (), None
154
+ return None , set ()
152
155
153
156
# Calculate two trails: one from the next instruction, and one from the
154
157
# jump_target instruction.
155
- trails = [
156
- walk_one_branch (start_at = inst .offset + 2 ),
157
- walk_one_branch (start_at = inst .jump_target ),
158
- ]
158
+ trails = collections .defaultdict (set )
159
+ arc , offsets = walk_one_branch (start_at = inst .offset + 2 )
160
+ trails [arc ].update (offsets )
161
+ arc , offsets = walk_one_branch (start_at = inst .jump_target )
162
+ trails [arc ].update (offsets )
159
163
the_trails [inst .offset ] = trails
160
164
161
165
# Sometimes we get BRANCH_RIGHT or BRANCH_LEFT events from instructions
162
166
# other than the original jump possibility instruction. Register each
163
167
# trail under all of their offsets so we can pick up in the middle of a
164
168
# trail if need be.
165
- for trail in trails :
166
- for offset in trail [0 ]:
167
- if offset not in the_trails :
168
- the_trails [offset ] = []
169
- the_trails [offset ].append (trail )
169
+ for arc , offsets in trails .items ():
170
+ for offset in offsets :
171
+ the_trails [offset ][arc ].update (offsets )
170
172
171
173
return the_trails
172
174
0 commit comments