@@ -44,43 +44,11 @@ def disassemble(self, co, classname=None, code_objects={}):
4444
4545 customize = {}
4646 Token = self .Token # shortcut
47- self .code = array ('B' , co .co_code )
48-
49- for i in self .op_range (0 , len (self .code )):
50- if self .code [i ] in (RETURN_VALUE , END_FINALLY ):
51- n = i + 1
52- self .code = array ('B' , co .co_code [:n ])
53-
54- self .prev = [0 ]
55- # mapping addresses of instruction & argument
56- for i in self .op_range (0 , n ):
57- op = self .code [i ]
58- self .prev .append (i )
59- if op >= HAVE_ARGUMENT :
60- self .prev .append (i )
61- self .prev .append (i )
62-
63- self .lines = []
64- linetuple = namedtuple ('linetuple' , ['l_no' , 'next' ])
65-
66- j = 0
6747
68- # linestarts is a tuple of (offset, line number).
69- # Turn that in a has that we can index
70- linestarts = list (dis .findlinestarts (co ))
71- linestartoffsets = {}
72- for offset , lineno in linestarts :
73- linestartoffsets [offset ] = lineno
48+ n = self .setup_code (co )
49+ self .build_lines_data (co , n )
50+ self .build_prev_op (n )
7451
75- (prev_start_byte , prev_line_no ) = linestarts [0 ]
76- for (start_byte , line_no ) in linestarts [1 :]:
77- while j < start_byte :
78- self .lines .append (linetuple (prev_line_no , start_byte ))
79- j += 1
80- prev_line_no = start_byte
81- while j < n :
82- self .lines .append (linetuple (prev_line_no , n ))
83- j += 1
8452 # self.lines contains (block,addrLastInstr)
8553 if classname :
8654 classname = '_' + classname .lstrip ('_' ) + '__'
@@ -104,7 +72,7 @@ def unmangle(name):
10472 if names [self .get_argument (i + 3 )] == 'AssertionError' :
10573 self .load_asserts .add (i + 3 )
10674
107- cf = self .find_jump_targets (self . code )
75+ cf = self .find_jump_targets ()
10876 # contains (code, [addrRefToCode])
10977 last_stmt = self .next_stmt [0 ]
11078 i = self .next_stmt [last_stmt ]
@@ -213,8 +181,8 @@ def unmangle(name):
213181 if offset in self .return_end_ifs :
214182 op_name = 'RETURN_END_IF'
215183
216- if offset in linestartoffsets :
217- linestart = linestartoffsets [offset ]
184+ if offset in self . linestartoffsets :
185+ linestart = self . linestartoffsets [offset ]
218186 else :
219187 linestart = None
220188
@@ -224,6 +192,63 @@ def unmangle(name):
224192 tokens .append (Token (replace [offset ], oparg , pattr , offset , linestart ))
225193 return tokens , customize
226194
195+ def setup_code (self , co ):
196+ """
197+ Creates Python-independent bytecode structure (byte array) in
198+ self.code and records previous instruction in self.prev
199+ The size of self.code is returned
200+ """
201+ self .code = array ('B' , co .co_code )
202+
203+ n = - 1
204+ for i in self .op_range (0 , len (self .code )):
205+ if self .code [i ] in (RETURN_VALUE , END_FINALLY ):
206+ n = i + 1
207+ pass
208+ pass
209+ assert n > - 1 , "Didn't find RETURN_VALUE or END_FINALLY FINALLY"
210+ self .code = array ('B' , co .co_code [:n ])
211+
212+ return n
213+
214+ def build_prev_op (self , n ):
215+ self .prev = [0 ]
216+ # mapping addresses of instruction & argument
217+ for i in self .op_range (0 , n ):
218+ op = self .code [i ]
219+ self .prev .append (i )
220+ if op >= HAVE_ARGUMENT :
221+ self .prev .append (i )
222+ self .prev .append (i )
223+ pass
224+ pass
225+
226+ def build_lines_data (self , co , n ):
227+ """
228+ Initializes self.lines and self.linesstartoffsets
229+ """
230+ self .lines = []
231+ linetuple = namedtuple ('linetuple' , ['l_no' , 'next' ])
232+
233+ # linestarts is a tuple of (offset, line number).
234+ # Turn that in a has that we can index
235+ linestarts = list (dis .findlinestarts (co ))
236+ self .linestartoffsets = {}
237+ for offset , lineno in linestarts :
238+ self .linestartoffsets [offset ] = lineno
239+
240+ j = 0
241+ (prev_start_byte , prev_line_no ) = linestarts [0 ]
242+ for (start_byte , line_no ) in linestarts [1 :]:
243+ while j < start_byte :
244+ self .lines .append (linetuple (prev_line_no , start_byte ))
245+ j += 1
246+ prev_line_no = start_byte
247+ while j < n :
248+ self .lines .append (linetuple (prev_line_no , n ))
249+ j += 1
250+ return
251+
227252 def build_stmt_indices (self ):
228253 code = self .code
229254 start = 0
@@ -585,7 +610,7 @@ def detect_structure(self, pos, op=None):
585610 target = self .get_target (pos , op )
586611 self .fixed_jumps [pos ] = self .restrict_to_parent (target , parent )
587612
588- def find_jump_targets (self , code ):
613+ def find_jump_targets (self ):
589614 '''
590615 Detect all offsets in a byte code which are jump targets.
591616
@@ -595,28 +620,30 @@ def find_jump_targets(self, code):
595620 for each target the number of jumps are counted.
596621 '''
597622
598- n = len (code )
623+ n = len (self . code )
599624 self .structs = [{'type' : 'root' ,
600625 'start' : 0 ,
601626 'end' : n - 1 }]
602627 self .loops = [] # All loop entry points
603628 self .fixed_jumps = {} # Map fixed jumps to their real destination
604629 self .ignore_if = set ()
605630 self .build_stmt_indices ()
631+
632+ # Containers filled by detect_structure()
606633 self .not_continue = set ()
607634 self .return_end_ifs = set ()
608635
609636 targets = {}
610637 for i in self .op_range (0 , n ):
611- op = code [i ]
638+ op = self . code [i ]
612639
613640 # Determine structures and fix jumps in Python versions
614641 # since 2.3
615642 self .detect_structure (i , op )
616643
617644 if op >= HAVE_ARGUMENT :
618645 label = self .fixed_jumps .get (i )
619- oparg = code [i + 1 ] + code [i + 2 ] * 256
646+ oparg = self . code [i + 1 ] + self . code [i + 2 ] * 256
620647 if label is None :
621648 if op in hasjrel and op != FOR_ITER :
622649 label = i + 3 + oparg
@@ -634,7 +661,8 @@ def find_jump_targets(self, code):
634661
635662if __name__ == "__main__" :
636663 co = inspect .currentframe ().f_code
637- tokens , customize = Scanner27 ().disassemble (co )
664+ from uncompyle6 import PYTHON_VERSION
665+ tokens , customize = Scanner27 (PYTHON_VERSION ).disassemble (co )
638666 for t in tokens :
639667 print (t )
640668 pass
0 commit comments