2.6- bug: while..and: stmt - on one line

If 2.6 or before POP_BLOCK after a JUMP_IF_FALSE does not
constitute a new statement. The POP_BLOCK is really part
of the JUMP_IF_FALSE. In Python 2.7+ it's a single op.
This commit is contained in:
rocky
2016-09-01 20:44:17 -04:00
parent 1d567d5d9a
commit f5eeed6759
4 changed files with 39 additions and 16 deletions

Binary file not shown.

View File

@@ -0,0 +1,9 @@
# From Python 2.6/MimeWriter.py
#
# Bug is detecting that "del" starts a statement
# and is not: del not lines[-1] and lines[-1]
#
# A complicating factor is that the "while"
# and statement are on the same line.
lines = __file__.split("\n")
while lines and not lines[-1]: del lines[-1]

View File

@@ -56,13 +56,18 @@ class Scanner2(scan.Scanner):
"""
show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'before'
# show_asm = 'both'
if show_asm in ('both', 'before'):
from xdis.bytecode import Bytecode
bytecode = Bytecode(co, self.opc)
for instr in bytecode.get_instructions(co):
print(instr._disassemble())
# from xdis.bytecode import Bytecode
# bytecode = Bytecode(co, self.opc)
# for instr in bytecode.get_instructions(co):
# print(instr._disassemble())
# Container for tokens
tokens = []
@@ -77,7 +82,7 @@ class Scanner2(scan.Scanner):
self.build_lines_data(co, n)
self.build_prev_op(n)
# self.lines contains (block,addrLastInstr)
# class and names
if classname:
classname = '_' + classname.lstrip('_') + '__'
@@ -120,6 +125,7 @@ class Scanner2(scan.Scanner):
cf = self.find_jump_targets()
# contains (code, [addrRefToCode])
last_stmt = self.next_stmt[0]
i = self.next_stmt[last_stmt]
replace = {}
@@ -316,7 +322,7 @@ class Scanner2(scan.Scanner):
self.lines = []
linetuple = namedtuple('linetuple', ['l_no', 'next'])
# linestarts is a tuple of (offset, line number).
# self.linestarts is a tuple of (offset, line number).
# Turn that in a has that we can index
self.linestarts = list(self.opc.findlinestarts(co))
self.linestartoffsets = {}
@@ -382,10 +388,13 @@ class Scanner2(scan.Scanner):
while code[j] == self.opc.JUMP_ABSOLUTE:
j = self.prev[j]
if (self.version >= 2.3 and
code[j] == self.opc.LIST_APPEND): # list comprehension
self.opc.opname[code[j]] == 'LIST_APPEND'): # list comprehension
stmts.remove(s)
continue
elif code[s] == self.opc.POP_TOP and code[self.prev[s]] == self.opc.ROT_TWO:
elif code[s] == self.opc.POP_TOP:
prev = code[self.prev[s]]
if (prev == self.opc.ROT_TWO or
self.version <= 2.6 and prev == self.opc.JUMP_IF_FALSE):
stmts.remove(s)
continue
elif code[s] in self.designator_ops:
@@ -654,7 +663,7 @@ class Scanner2(scan.Scanner):
'end': pre[target]})
return
# Is it an "and" inside an "if" block
# Is it an "and" inside an "if" or "while" block
if op == self.opc.PJIF:
# Search for other POP_JUMP_IF_FALSE targetting the same op,
# in current statement, starting from current offset, and filter

View File

@@ -71,12 +71,20 @@ class Scanner26(scan.Scanner2):
return
def disassemble(self, co, classname=None, code_objects={}, show_asm=None):
'''
Disassemble a code object, returning a list of 'Token'.
"""
Pick out tokens from an uncompyle6 code object, and transform them,
returning a list of uncompyle6 'Token's.
The main part of this procedure is modelled after
dis.disassemble().
'''
The tranformations are made to assist the deparsing grammar.
Specificially:
- various types of LOAD_CONST's are categorized in terms of what they load
- COME_FROM instructions are added to assist parsing control structures
- MAKE_FUNCTION and FUNCTION_CALLS append the number of positional arguments
Also, when we encounter certain tokens, we add them to a set which will cause custom
grammar rules. Specifically, variable arg tokens like MAKE_FUNCTION or BUILD_LIST
cause specific rules for the specific number of arguments they take.
"""
show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'both'
@@ -102,9 +110,6 @@ class Scanner26(scan.Scanner2):
self.build_lines_data(co, n)
self.build_prev_op(n)
# linestarts contains block code adresses (addr,block)
self.linestarts = list(self.opc.findlinestarts(co))
# class and names
if classname:
classname = '_' + classname.lstrip('_') + '__'