You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
bang on scanner2{5,6}
This commit is contained in:
@@ -37,7 +37,7 @@ entry_points={
|
|||||||
]}
|
]}
|
||||||
ftp_url = None
|
ftp_url = None
|
||||||
install_requires = ['spark-parser >= 1.2.1',
|
install_requires = ['spark-parser >= 1.2.1',
|
||||||
'xdis >= 1.0.4']
|
'xdis >= 1.0.5']
|
||||||
license = 'MIT'
|
license = 'MIT'
|
||||||
mailing_list = 'python-debugger@googlegroups.com'
|
mailing_list = 'python-debugger@googlegroups.com'
|
||||||
modname = 'uncompyle6'
|
modname = 'uncompyle6'
|
||||||
|
@@ -20,7 +20,6 @@ For example:
|
|||||||
Finally we save token information.
|
Finally we save token information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
@@ -79,6 +78,7 @@ class Scanner2(scan.Scanner):
|
|||||||
free = co.co_cellvars + co.co_freevars
|
free = co.co_cellvars + co.co_freevars
|
||||||
names = co.co_names
|
names = co.co_names
|
||||||
varnames = co.co_varnames
|
varnames = co.co_varnames
|
||||||
|
self.names = names
|
||||||
|
|
||||||
self.load_asserts = set()
|
self.load_asserts = set()
|
||||||
for i in self.op_range(0, n):
|
for i in self.op_range(0, n):
|
||||||
@@ -164,14 +164,7 @@ class Scanner2(scan.Scanner):
|
|||||||
elif op in self.opc.hasfree:
|
elif op in self.opc.hasfree:
|
||||||
pattr = free[oparg]
|
pattr = free[oparg]
|
||||||
|
|
||||||
if op in (self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
|
if op in self.varargs_ops:
|
||||||
self.opc.BUILD_SET, self.opc.BUILD_SLICE,
|
|
||||||
self.opc.UNPACK_SEQUENCE, self.opc.MAKE_FUNCTION,
|
|
||||||
self.opc.CALL_FUNCTION, self.opc.MAKE_CLOSURE,
|
|
||||||
self.opc.CALL_FUNCTION_VAR, self.opc.CALL_FUNCTION_KW,
|
|
||||||
self.opc.CALL_FUNCTION_VAR_KW, self.opc.DUP_TOPX,
|
|
||||||
self.opc.RAISE_VARARGS
|
|
||||||
):
|
|
||||||
# CE - Hack for >= 2.5
|
# CE - Hack for >= 2.5
|
||||||
# Now all values loaded via LOAD_CLOSURE are packed into
|
# Now all values loaded via LOAD_CLOSURE are packed into
|
||||||
# a tuple before calling MAKE_CLOSURE.
|
# a tuple before calling MAKE_CLOSURE.
|
||||||
@@ -328,14 +321,14 @@ class Scanner2(scan.Scanner):
|
|||||||
|
|
||||||
# linestarts is a tuple of (offset, line number).
|
# linestarts is a tuple of (offset, line number).
|
||||||
# Turn that in a has that we can index
|
# Turn that in a has that we can index
|
||||||
linestarts = list(findlinestarts(co))
|
self.linestarts = list(findlinestarts(co))
|
||||||
self.linestartoffsets = {}
|
self.linestartoffsets = {}
|
||||||
for offset, lineno in linestarts:
|
for offset, lineno in self.linestarts:
|
||||||
self.linestartoffsets[offset] = lineno
|
self.linestartoffsets[offset] = lineno
|
||||||
|
|
||||||
j = 0
|
j = 0
|
||||||
(prev_start_byte, prev_line_no) = linestarts[0]
|
(prev_start_byte, prev_line_no) = self.linestarts[0]
|
||||||
for (start_byte, line_no) in linestarts[1:]:
|
for (start_byte, line_no) in self.linestarts[1:]:
|
||||||
while j < start_byte:
|
while j < start_byte:
|
||||||
self.lines.append(linetuple(prev_line_no, start_byte))
|
self.lines.append(linetuple(prev_line_no, start_byte))
|
||||||
j += 1
|
j += 1
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
# Copyright (c) 2015-2016 by Rocky Bernstein
|
# Copyright (c) 2015-2016 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
# Copyright (c) 1999 John Aycock
|
|
||||||
#
|
#
|
||||||
"""
|
"""
|
||||||
Python 2.5 bytecode scanner/deparser
|
Python 2.5 bytecode scanner/deparser
|
||||||
|
@@ -15,7 +15,7 @@ from collections import namedtuple
|
|||||||
from array import array
|
from array import array
|
||||||
|
|
||||||
from uncompyle6.opcodes.opcode_26 import *
|
from uncompyle6.opcodes.opcode_26 import *
|
||||||
import dis
|
from xdis.bytecode import findlinestarts
|
||||||
import uncompyle6.scanners.scanner2 as scan
|
import uncompyle6.scanners.scanner2 as scan
|
||||||
|
|
||||||
class Scanner26(scan.Scanner2):
|
class Scanner26(scan.Scanner2):
|
||||||
@@ -43,6 +43,17 @@ class Scanner26(scan.Scanner2):
|
|||||||
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# opcodes with expect a variable number pushed values whose
|
||||||
|
# count is in the opcode. For parsing we generally change the
|
||||||
|
# opcode name to include that number.
|
||||||
|
self.varargs_ops = frozenset([
|
||||||
|
self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
|
||||||
|
self.opc.BUILD_SLICE, self.opc.UNPACK_SEQUENCE,
|
||||||
|
self.opc.MAKE_FUNCTION, self.opc.CALL_FUNCTION,
|
||||||
|
self.opc.MAKE_CLOSURE, self.opc.CALL_FUNCTION_VAR,
|
||||||
|
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
|
||||||
|
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS])
|
||||||
|
|
||||||
# opcodes that store values into a variable
|
# opcodes that store values into a variable
|
||||||
self.designator_ops = frozenset([
|
self.designator_ops = frozenset([
|
||||||
self.opc.STORE_FAST, self.opc.STORE_NAME,
|
self.opc.STORE_FAST, self.opc.STORE_NAME,
|
||||||
@@ -70,13 +81,12 @@ class Scanner26(scan.Scanner2):
|
|||||||
|
|
||||||
customize = {}
|
customize = {}
|
||||||
Token = self.Token # shortcut
|
Token = self.Token # shortcut
|
||||||
self.code = array('B', co.co_code)
|
|
||||||
for i in self.op_range(0, len(self.code)):
|
n = self.setup_code(co)
|
||||||
if self.code[i] in (RETURN_VALUE, END_FINALLY):
|
self.build_lines_data(co, n)
|
||||||
n = i + 1
|
|
||||||
self.code = array('B', co.co_code[:n])
|
|
||||||
# linestarts contains block code adresses (addr,block)
|
# linestarts contains block code adresses (addr,block)
|
||||||
self.linestarts = list(dis.findlinestarts(co))
|
self.linestarts = list(findlinestarts(co))
|
||||||
self.prev = [0]
|
self.prev = [0]
|
||||||
# class and names
|
# class and names
|
||||||
if classname:
|
if classname:
|
||||||
@@ -107,31 +117,10 @@ class Scanner26(scan.Scanner2):
|
|||||||
if self.op_hasArgument(op):
|
if self.op_hasArgument(op):
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
j = 0
|
|
||||||
linestarts = self.linestarts
|
|
||||||
self.lines = []
|
|
||||||
linetuple = namedtuple('linetuple', ['l_no', 'next'])
|
|
||||||
|
|
||||||
# linestarts is a tuple of (offset, line number).
|
|
||||||
# Turn that in a has that we can index
|
|
||||||
linestartoffsets = {}
|
|
||||||
for offset, lineno in linestarts:
|
|
||||||
linestartoffsets[offset] = lineno
|
|
||||||
|
|
||||||
(prev_start_byte, prev_line_no) = linestarts[0]
|
|
||||||
for (start_byte, line_no) in linestarts[1:]:
|
|
||||||
while j < start_byte:
|
|
||||||
self.lines.append(linetuple(prev_line_no, start_byte))
|
|
||||||
j += 1
|
|
||||||
prev_line_no = line_no
|
|
||||||
while j < codelen:
|
|
||||||
self.lines.append(linetuple(prev_line_no, codelen))
|
|
||||||
j+=1
|
|
||||||
# self.lines contains (block,addrLastInstr)
|
|
||||||
|
|
||||||
self.load_asserts = set()
|
self.load_asserts = set()
|
||||||
for i in self.op_range(0, codelen):
|
for i in self.op_range(0, codelen):
|
||||||
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
|
if self.code[i] == self.opc.PJIT and self.code[i + 3] == self.opc.LOAD_GLOBAL:
|
||||||
if names[self.get_argument(i+3)] == 'AssertionError':
|
if names[self.get_argument(i+3)] == 'AssertionError':
|
||||||
self.load_asserts.add(i+3)
|
self.load_asserts.add(i+3)
|
||||||
|
|
||||||
@@ -141,22 +130,24 @@ class Scanner26(scan.Scanner2):
|
|||||||
last_stmt = self.next_stmt[0]
|
last_stmt = self.next_stmt[0]
|
||||||
i = self.next_stmt[last_stmt]
|
i = self.next_stmt[last_stmt]
|
||||||
replace = {}
|
replace = {}
|
||||||
while i < codelen-1:
|
while i < codelen - 1:
|
||||||
if self.lines[last_stmt].next > i:
|
if self.lines[last_stmt].next > i:
|
||||||
if self.code[last_stmt] == PRINT_ITEM:
|
if self.code[last_stmt] == self.opc.PRINT_ITEM:
|
||||||
if self.code[i] == PRINT_ITEM:
|
if self.code[i] == self.opc.PRINT_ITEM:
|
||||||
replace[i] = 'PRINT_ITEM_CONT'
|
replace[i] = 'PRINT_ITEM_CONT'
|
||||||
elif self.code[i] == PRINT_NEWLINE:
|
elif self.code[i] == self.opc.PRINT_NEWLINE:
|
||||||
replace[i] = 'PRINT_NEWLINE_CONT'
|
replace[i] = 'PRINT_NEWLINE_CONT'
|
||||||
last_stmt = i
|
last_stmt = i
|
||||||
i = self.next_stmt[i]
|
i = self.next_stmt[i]
|
||||||
|
|
||||||
imports = self.all_instr(0, codelen, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR))
|
imports = self.all_instr(0, codelen,
|
||||||
|
(self.opc.IMPORT_NAME, self.opc.IMPORT_FROM,
|
||||||
|
self.opc.IMPORT_STAR))
|
||||||
if len(imports) > 1:
|
if len(imports) > 1:
|
||||||
last_import = imports[0]
|
last_import = imports[0]
|
||||||
for i in imports[1:]:
|
for i in imports[1:]:
|
||||||
if self.lines[last_import].next > i:
|
if self.lines[last_import].next > i:
|
||||||
if self.code[last_import] == IMPORT_NAME == self.code[i]:
|
if self.code[last_import] == self.opc.IMPORT_NAME == self.code[i]:
|
||||||
replace[i] = 'IMPORT_NAME_CONT'
|
replace[i] = 'IMPORT_NAME_CONT'
|
||||||
last_import = i
|
last_import = i
|
||||||
|
|
||||||
@@ -175,11 +166,11 @@ class Scanner26(scan.Scanner2):
|
|||||||
if self.op_hasArgument(op):
|
if self.op_hasArgument(op):
|
||||||
oparg = self.get_argument(offset) + extended_arg
|
oparg = self.get_argument(offset) + extended_arg
|
||||||
extended_arg = 0
|
extended_arg = 0
|
||||||
if op == EXTENDED_ARG:
|
if op == self.opc.EXTENDED_ARG:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
extended_arg = oparg * scan.L65536
|
extended_arg = oparg * scan.L65536
|
||||||
continue
|
continue
|
||||||
if op in hasconst:
|
if op in self.opc.hasconst:
|
||||||
const = co.co_consts[oparg]
|
const = co.co_consts[oparg]
|
||||||
# We can't use inspect.iscode() because we may be
|
# We can't use inspect.iscode() because we may be
|
||||||
# using a different version of Python than the
|
# using a different version of Python than the
|
||||||
@@ -204,59 +195,54 @@ class Scanner26(scan.Scanner2):
|
|||||||
pattr = '<code_object ' + const.co_name + '>'
|
pattr = '<code_object ' + const.co_name + '>'
|
||||||
else:
|
else:
|
||||||
pattr = const
|
pattr = const
|
||||||
elif op in hasname:
|
elif op in self.opc.hasname:
|
||||||
pattr = names[oparg]
|
pattr = names[oparg]
|
||||||
elif op in hasjrel:
|
elif op in self.opc.hasjrel:
|
||||||
pattr = repr(offset + 3 + oparg)
|
pattr = repr(offset + 3 + oparg)
|
||||||
elif op in hasjabs:
|
elif op in self.opc.hasjabs:
|
||||||
pattr = repr(oparg)
|
pattr = repr(oparg)
|
||||||
elif op in haslocal:
|
elif op in self.opc.haslocal:
|
||||||
pattr = varnames[oparg]
|
pattr = varnames[oparg]
|
||||||
elif op in hascompare:
|
elif op in self.opc.hascompare:
|
||||||
try:
|
pattr = self.opc.cmp_op[oparg]
|
||||||
pattr = cmp_op[oparg]
|
elif op in self.opc.hasfree:
|
||||||
except:
|
|
||||||
from trepan.api import debug; debug()
|
|
||||||
elif op in hasfree:
|
|
||||||
pattr = free[oparg]
|
pattr = free[oparg]
|
||||||
if offset in self.toChange:
|
if offset in self.toChange:
|
||||||
if self.code[offset] == JA and self.code[oparg] == WITH_CLEANUP:
|
if (self.code[offset] == self.opc.JA and
|
||||||
|
self.code[oparg] == self.opc.WITH_CLEANUP):
|
||||||
op_name = 'SETUP_WITH'
|
op_name = 'SETUP_WITH'
|
||||||
cf[oparg] = cf.get(oparg, []) + [offset]
|
cf[oparg] = cf.get(oparg, []) + [offset]
|
||||||
if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SLICE,
|
if op in self.varargs_ops:
|
||||||
UNPACK_SEQUENCE,
|
|
||||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
|
||||||
CALL_FUNCTION_VAR, CALL_FUNCTION_KW,
|
|
||||||
CALL_FUNCTION_VAR_KW, DUP_TOPX, RAISE_VARARGS
|
|
||||||
):
|
|
||||||
# CE - Hack for >= 2.5
|
# CE - Hack for >= 2.5
|
||||||
# Now all values loaded via LOAD_CLOSURE are packed into
|
# Now all values loaded via LOAD_CLOSURE are packed into
|
||||||
# a tuple before calling MAKE_CLOSURE.
|
# a tuple before calling MAKE_CLOSURE.
|
||||||
if op == BUILD_TUPLE and \
|
if (op == self.opc.BUILD_TUPLE and
|
||||||
self.code[self.prev[offset]] == LOAD_CLOSURE:
|
self.code[self.prev[offset]] == self.opc.LOAD_CLOSURE):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
op_name = '%s_%d' % (op_name, oparg)
|
op_name = '%s_%d' % (op_name, oparg)
|
||||||
if op != BUILD_SLICE:
|
if op != self.opc.BUILD_SLICE:
|
||||||
customize[op_name] = oparg
|
customize[op_name] = oparg
|
||||||
elif op == JA:
|
elif op == self.opc.JA:
|
||||||
target = self.get_target(offset)
|
target = self.get_target(offset)
|
||||||
if target < offset:
|
if target < offset:
|
||||||
if offset in self.stmts and self.code[offset+3] not in (END_FINALLY, POP_BLOCK) \
|
if (offset in self.stmts
|
||||||
and offset not in self.not_continue:
|
and self.code[offset + 3] not in (self.opc.END_FINALLY,
|
||||||
|
self.opc.POP_BLOCK)
|
||||||
|
and offset not in self.not_continue):
|
||||||
op_name = 'CONTINUE'
|
op_name = 'CONTINUE'
|
||||||
else:
|
else:
|
||||||
op_name = 'JUMP_BACK'
|
op_name = 'JUMP_BACK'
|
||||||
|
|
||||||
elif op == LOAD_GLOBAL:
|
elif op == self.opc.LOAD_GLOBAL:
|
||||||
if offset in self.load_asserts:
|
if offset in self.load_asserts:
|
||||||
op_name = 'LOAD_ASSERT'
|
op_name = 'LOAD_ASSERT'
|
||||||
elif op == RETURN_VALUE:
|
elif op == self.opc.RETURN_VALUE:
|
||||||
if offset in self.return_end_ifs:
|
if offset in self.return_end_ifs:
|
||||||
op_name = 'RETURN_END_IF'
|
op_name = 'RETURN_END_IF'
|
||||||
|
|
||||||
if offset in linestartoffsets:
|
if offset in self.linestartoffsets:
|
||||||
linestart = linestartoffsets[offset]
|
linestart = self.linestartoffsets[offset]
|
||||||
else:
|
else:
|
||||||
linestart = None
|
linestart = None
|
||||||
|
|
||||||
@@ -282,10 +268,15 @@ class Scanner26(scan.Scanner2):
|
|||||||
if i+opsize >= len(self.code):
|
if i+opsize >= len(self.code):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if opcode == EXTENDED_ARG:
|
if opcode == self.opc.EXTENDED_ARG:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
# modification of some jump structure
|
# modification of some jump structure
|
||||||
if opcode in (PJIF, PJIT, JA, JF, RETURN_VALUE):
|
if opcode in (self.opc.PJIF,
|
||||||
|
self.opc.PJIT,
|
||||||
|
self.opc.JA,
|
||||||
|
self.opc.JF,
|
||||||
|
self.opc.RETURN_VALUE):
|
||||||
toDel = []
|
toDel = []
|
||||||
# del POP_TOP
|
# del POP_TOP
|
||||||
if self.code[i+opsize] == POP_TOP:
|
if self.code[i+opsize] == POP_TOP:
|
||||||
@@ -445,24 +436,24 @@ class Scanner26(scan.Scanner2):
|
|||||||
if listDel:
|
if listDel:
|
||||||
for jmp in self.op_range(0, len(self.code)):
|
for jmp in self.op_range(0, len(self.code)):
|
||||||
op = self.code[jmp]
|
op = self.code[jmp]
|
||||||
if op in hasjrel+hasjabs:
|
if op in self.opc.hasjrel + self.opc.hasjabs:
|
||||||
offset = 0
|
offset = 0
|
||||||
jmpTarget = self.get_target(jmp)
|
jmpTarget = self.get_target(jmp)
|
||||||
for toDel in listDel:
|
for toDel in listDel:
|
||||||
if toDel < jmpTarget:
|
if toDel < jmpTarget:
|
||||||
if op in hasjabs or jmp < toDel:
|
if op in self.opc.hasjabs or jmp < toDel:
|
||||||
offset-=self.op_size(self.code[toDel])
|
offset-=self.op_size(self.code[toDel])
|
||||||
self.restructJump(jmp, jmpTarget+offset)
|
self.restructJump(jmp, jmpTarget+offset)
|
||||||
if listExp:
|
if listExp:
|
||||||
jmp = 0
|
jmp = 0
|
||||||
while jmp < len(self.code): # we can't use op_range for the moment
|
while jmp < len(self.code): # we can't use op_range for the moment
|
||||||
op = self.code[jmp]
|
op = self.code[jmp]
|
||||||
if op in hasjrel+hasjabs:
|
if op in self.opc.hasjrel + self.opc.hasjabs:
|
||||||
offset = 0
|
offset = 0
|
||||||
jmpTarget = self.get_target(jmp)
|
jmpTarget = self.get_target(jmp)
|
||||||
for toExp in listExp:
|
for toExp in listExp:
|
||||||
if toExp < jmpTarget:
|
if toExp < jmpTarget:
|
||||||
if op in hasjabs or jmp < toExp:
|
if op in self.opc.hasjabs or jmp < toExp:
|
||||||
offset+=2
|
offset+=2
|
||||||
self.restructJump(jmp, jmpTarget+offset)
|
self.restructJump(jmp, jmpTarget+offset)
|
||||||
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
||||||
@@ -520,9 +511,10 @@ class Scanner26(scan.Scanner2):
|
|||||||
i=0
|
i=0
|
||||||
while i < len(self.code): # we can't use op_range for the moment
|
while i < len(self.code): # we can't use op_range for the moment
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
if(op in (PJIF, PJIT)):
|
if op in self.pop_jump_if:
|
||||||
target = self.get_argument(i)
|
target = self.get_argument(i)
|
||||||
target += i + 3
|
target += i + 3
|
||||||
|
|
||||||
self.restructJump(i, target)
|
self.restructJump(i, target)
|
||||||
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
||||||
i += 3
|
i += 3
|
||||||
@@ -531,9 +523,9 @@ class Scanner26(scan.Scanner2):
|
|||||||
i=0
|
i=0
|
||||||
while i < len(self.code): # we can't use op_range for the moment
|
while i < len(self.code): # we can't use op_range for the moment
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
if(op in (PJIF, PJIT)):
|
if op in self.pop_jump_if:
|
||||||
target = self.get_target(i)
|
target = self.get_target(i)
|
||||||
if self.code[target] == JA:
|
if self.code[target] == self.opc.JA:
|
||||||
target = self.get_target(target)
|
target = self.get_target(target)
|
||||||
self.restructJump(i, target)
|
self.restructJump(i, target)
|
||||||
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
|
||||||
@@ -541,7 +533,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
else: i += 1
|
else: i += 1
|
||||||
|
|
||||||
def restructJump(self, pos, newTarget):
|
def restructJump(self, pos, newTarget):
|
||||||
if not (self.code[pos] in hasjabs+hasjrel):
|
if self.code[pos] not in self.opc.hasjabs + self.opc.hasjrel:
|
||||||
raise 'Can t change this argument. Opcode is not a jump'
|
raise 'Can t change this argument. Opcode is not a jump'
|
||||||
if newTarget > 0xFFFF:
|
if newTarget > 0xFFFF:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@@ -577,7 +569,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
end = _end
|
end = _end
|
||||||
parent = s
|
parent = s
|
||||||
|
|
||||||
if op == SETUP_LOOP:
|
if op == self.opc.SETUP_LOOP:
|
||||||
start = pos+3
|
start = pos+3
|
||||||
target = self.get_target(pos, op)
|
target = self.get_target(pos, op)
|
||||||
end = self.restrict_to_parent(target, parent)
|
end = self.restrict_to_parent(target, parent)
|
||||||
@@ -586,18 +578,19 @@ class Scanner26(scan.Scanner2):
|
|||||||
self.fixed_jumps[pos] = end
|
self.fixed_jumps[pos] = end
|
||||||
|
|
||||||
(line_no, next_line_byte) = self.lines[pos]
|
(line_no, next_line_byte) = self.lines[pos]
|
||||||
jump_back = self.last_instr(start, end, JA,
|
jump_back = self.last_instr(start, end, self.opc.JA, next_line_byte, False)
|
||||||
next_line_byte, False)
|
if (jump_back and jump_back != self.prev[end]
|
||||||
if jump_back and jump_back != self.prev[end] and code[jump_back+3] in (JA, JF):
|
and code[jump_back + 3] in (self.opc.JA, self.opc.JF)):
|
||||||
if code[self.prev[end]] == RETURN_VALUE or \
|
if (code[self.prev[end]] == self.opc.RETURN_VALUE
|
||||||
(code[self.prev[end]] == POP_BLOCK and code[self.prev[self.prev[end]]] == RETURN_VALUE):
|
or code[self.prev[end]] == self.opc.POP_BLOCK
|
||||||
|
and code[self.prev[self.prev[end]]] == self.opc.RETURN_VALUE):
|
||||||
jump_back = None
|
jump_back = None
|
||||||
if not jump_back: # loop suite ends in return. wtf right?
|
if not jump_back: # loop suite ends in return. wtf right?
|
||||||
jump_back = self.last_instr(start, end, RETURN_VALUE)
|
jump_back = self.last_instr(start, end, self.opc.JA, start, False)
|
||||||
if not jump_back:
|
if not jump_back:
|
||||||
return
|
return
|
||||||
jump_back += 1
|
jump_back += 1
|
||||||
if code[self.prev[next_line_byte]] not in (PJIF, PJIT):
|
if code[self.prev[next_line_byte]] not in self.pop_jump_if:
|
||||||
loop_type = 'for'
|
loop_type = 'for'
|
||||||
else:
|
else:
|
||||||
loop_type = 'while'
|
loop_type = 'while'
|
||||||
@@ -606,10 +599,9 @@ class Scanner26(scan.Scanner2):
|
|||||||
end = jump_back + 3
|
end = jump_back + 3
|
||||||
else:
|
else:
|
||||||
if self.get_target(jump_back) >= next_line_byte:
|
if self.get_target(jump_back) >= next_line_byte:
|
||||||
jump_back = self.last_instr(start, end, JA,
|
jump_back = self.last_instr(start, end, self.opc.JA, start, False)
|
||||||
start, False)
|
if end > jump_back + 4 and code[end] in (self.opc.JF, self.opc.JA):
|
||||||
if end > jump_back+4 and code[end] in (JF, JA):
|
if code[jump_back + 4] in (self.opc.JA, self.opc.JF):
|
||||||
if code[jump_back+4] in (JA, JF):
|
|
||||||
if self.get_target(jump_back+4) == self.get_target(end):
|
if self.get_target(jump_back+4) == self.get_target(end):
|
||||||
self.fixed_jumps[pos] = jump_back+4
|
self.fixed_jumps[pos] = jump_back+4
|
||||||
end = jump_back+4
|
end = jump_back+4
|
||||||
@@ -617,16 +609,16 @@ class Scanner26(scan.Scanner2):
|
|||||||
self.fixed_jumps[pos] = jump_back+4
|
self.fixed_jumps[pos] = jump_back+4
|
||||||
end = jump_back+4
|
end = jump_back+4
|
||||||
|
|
||||||
target = self.get_target(jump_back, JA)
|
target = self.get_target(jump_back, self.opc.JA)
|
||||||
|
|
||||||
if code[target] in (FOR_ITER, GET_ITER):
|
if code[target] in (self.opc.FOR_ITER, self.opc.GET_ITER):
|
||||||
loop_type = 'for'
|
loop_type = 'for'
|
||||||
else:
|
else:
|
||||||
loop_type = 'while'
|
loop_type = 'while'
|
||||||
test = self.prev[next_line_byte]
|
test = self.prev[next_line_byte]
|
||||||
if test == pos:
|
if test == pos:
|
||||||
loop_type = 'while 1'
|
loop_type = 'while 1'
|
||||||
elif self.code[test] in hasjabs+hasjrel:
|
elif self.code[test] in self.opc.hasjabs + self.opc.hasjrel:
|
||||||
self.ignore_if.add(test)
|
self.ignore_if.add(test)
|
||||||
test_target = self.get_target(test)
|
test_target = self.get_target(test)
|
||||||
if test_target > (jump_back+3):
|
if test_target > (jump_back+3):
|
||||||
@@ -640,7 +632,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
self.structs.append({'type': loop_type + '-else',
|
self.structs.append({'type': loop_type + '-else',
|
||||||
'start': jump_back+3,
|
'start': jump_back+3,
|
||||||
'end': end})
|
'end': end})
|
||||||
elif op == SETUP_EXCEPT:
|
elif op == self.opc.SETUP_EXCEPT:
|
||||||
start = pos+3
|
start = pos+3
|
||||||
target = self.get_target(pos, op)
|
target = self.get_target(pos, op)
|
||||||
end = self.restrict_to_parent(target, parent)
|
end = self.restrict_to_parent(target, parent)
|
||||||
@@ -656,12 +648,12 @@ class Scanner26(scan.Scanner2):
|
|||||||
|
|
||||||
# Add the except blocks
|
# Add the except blocks
|
||||||
i = end
|
i = end
|
||||||
while i < len(self.code) and self.code[i] != END_FINALLY:
|
while i < len(self.code) and self.code[i] != self.opc.END_FINALLY:
|
||||||
jmp = self.next_except_jump(i)
|
jmp = self.next_except_jump(i)
|
||||||
if jmp is None: # check
|
if jmp is None: # check
|
||||||
i = self.next_stmt[i]
|
i = self.next_stmt[i]
|
||||||
continue
|
continue
|
||||||
if self.code[jmp] == RETURN_VALUE:
|
if self.code[jmp] == self.opc.RETURN_VALUE:
|
||||||
self.structs.append({'type': 'except',
|
self.structs.append({'type': 'except',
|
||||||
'start': i,
|
'start': i,
|
||||||
'end': jmp+1})
|
'end': jmp+1})
|
||||||
@@ -669,7 +661,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
else:
|
else:
|
||||||
if self.get_target(jmp) != start_else:
|
if self.get_target(jmp) != start_else:
|
||||||
end_else = self.get_target(jmp)
|
end_else = self.get_target(jmp)
|
||||||
if self.code[jmp] == JF:
|
if self.code[jmp] == self.opc.JF:
|
||||||
self.fixed_jumps[jmp] = -1
|
self.fixed_jumps[jmp] = -1
|
||||||
self.structs.append({'type': 'except',
|
self.structs.append({'type': 'except',
|
||||||
'start': i,
|
'start': i,
|
||||||
@@ -686,7 +678,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
else:
|
else:
|
||||||
self.fixed_jumps[i] = i+1
|
self.fixed_jumps[i] = i+1
|
||||||
|
|
||||||
elif op in (PJIF, PJIT):
|
elif op in self.pop_jump_if:
|
||||||
start = pos+3
|
start = pos+3
|
||||||
target = self.get_target(pos, op)
|
target = self.get_target(pos, op)
|
||||||
rtarget = self.restrict_to_parent(target, parent)
|
rtarget = self.restrict_to_parent(target, parent)
|
||||||
@@ -697,7 +689,7 @@ class Scanner26(scan.Scanner2):
|
|||||||
return
|
return
|
||||||
# does this jump to right after another cond jump?
|
# does this jump to right after another cond jump?
|
||||||
# if so, it's part of a larger conditional
|
# if so, it's part of a larger conditional
|
||||||
if (code[pre[target]] in (PJIF, PJIT)) and (target > pos):
|
if code[pre[target]] in self.pop_jump_if and target > pos:
|
||||||
self.fixed_jumps[pos] = pre[target]
|
self.fixed_jumps[pos] = pre[target]
|
||||||
self.structs.append({'type': 'and/or',
|
self.structs.append({'type': 'and/or',
|
||||||
'start': start,
|
'start': start,
|
||||||
@@ -705,18 +697,19 @@ class Scanner26(scan.Scanner2):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# is this an if and
|
# is this an if and
|
||||||
if op == PJIF:
|
if op == self.opc.PJIF:
|
||||||
match = self.rem_or(start, self.next_stmt[pos], PJIF, target)
|
match = self.rem_or(start, self.next_stmt[pos], self.opc.PJIF, target)
|
||||||
match = self.remove_mid_line_ifs(match)
|
match = self.remove_mid_line_ifs(match)
|
||||||
if match:
|
if match:
|
||||||
if code[pre[rtarget]] in (JF, JA) \
|
if (code[pre[rtarget]] in (self.opc.JF, self.opc.JA)
|
||||||
and pre[rtarget] not in self.stmts \
|
and pre[rtarget] not in self.stmts
|
||||||
and self.restrict_to_parent(self.get_target(pre[rtarget]), parent) == rtarget:
|
and self.restrict_to_parent(self.get_target(pre[rtarget]), parent) == rtarget):
|
||||||
if code[pre[pre[rtarget]]] == JA \
|
if (code[pre[pre[rtarget]]] == self.opc.JA
|
||||||
and self.remove_mid_line_ifs([pos]) \
|
and self.remove_mid_line_ifs([pos])
|
||||||
and target == self.get_target(pre[pre[rtarget]]) \
|
and target == self.get_target(pre[pre[rtarget]])
|
||||||
and (pre[pre[rtarget]] not in self.stmts or self.get_target(pre[pre[rtarget]]) > pre[pre[rtarget]])\
|
and (pre[pre[rtarget]] not in self.stmts
|
||||||
and 1 == len(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], (PJIF, PJIT), target))):
|
or self.get_target(pre[pre[rtarget]]) > pre[pre[rtarget]])
|
||||||
|
and 1 == len(self.remove_mid_line_ifs(self.rem_or(start, pre[pre[rtarget]], self.pop_jump_if, target)))):
|
||||||
pass
|
pass
|
||||||
elif code[pre[pre[rtarget]]] == RETURN_VALUE \
|
elif code[pre[pre[rtarget]]] == RETURN_VALUE \
|
||||||
and self.remove_mid_line_ifs([pos]) \
|
and self.remove_mid_line_ifs([pos]) \
|
||||||
@@ -771,11 +764,11 @@ class Scanner26(scan.Scanner2):
|
|||||||
and not (code[rtarget] == JA and code[rtarget+3] == POP_BLOCK and code[pre[pre[rtarget]]] != JA):
|
and not (code[rtarget] == JA and code[rtarget+3] == POP_BLOCK and code[pre[pre[rtarget]]] != JA):
|
||||||
rtarget = pre[rtarget]
|
rtarget = pre[rtarget]
|
||||||
# does the if jump just beyond a jump op, then this is probably an if statement
|
# does the if jump just beyond a jump op, then this is probably an if statement
|
||||||
if code[pre[rtarget]] in (JA, JF):
|
if code[pre[rtarget]] in (self.opc.JA, self.opc.JF):
|
||||||
if_end = self.get_target(pre[rtarget])
|
if_end = self.get_target(pre[rtarget])
|
||||||
|
|
||||||
# is this a loop not an if?
|
# is this a loop not an if?
|
||||||
if (if_end < pre[rtarget]) and (code[pre[if_end]] == SETUP_LOOP):
|
if (if_end < pre[rtarget]) and (code[pre[if_end]] == self.opc.SETUP_LOOP):
|
||||||
if(if_end > start):
|
if(if_end > start):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -790,9 +783,9 @@ class Scanner26(scan.Scanner2):
|
|||||||
self.structs.append({'type': 'if-else',
|
self.structs.append({'type': 'if-else',
|
||||||
'start': rtarget,
|
'start': rtarget,
|
||||||
'end': end})
|
'end': end})
|
||||||
elif code[pre[rtarget]] == RETURN_VALUE:
|
elif code[pre[rtarget]] == self.opc.RETURN_VALUE:
|
||||||
# if it's an old JUMP_IF_FALSE_OR_POP, JUMP_IF_TRUE_OR_POP (return 1<2<3 case)
|
# if it's an old JUMP_IF_FALSE_OR_POP, JUMP_IF_TRUE_OR_POP (return 1<2<3 case)
|
||||||
if pos < rtarget and code[rtarget] == ROT_TWO:
|
if pos < rtarget and code[rtarget] == self.opc.ROT_TWO:
|
||||||
return
|
return
|
||||||
self.structs.append({'type': 'if-then',
|
self.structs.append({'type': 'if-then',
|
||||||
'start': start,
|
'start': start,
|
||||||
|
@@ -44,6 +44,19 @@ class Scanner27(Scanner2):
|
|||||||
self.opc.DELETE_SLICE_2, self.opc.DELETE_SLICE_3,
|
self.opc.DELETE_SLICE_2, self.opc.DELETE_SLICE_3,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# opcodes with expect a variable number pushed values whose
|
||||||
|
# count is in the opcode. For parsing we generally change the
|
||||||
|
# opcode name to include that number.
|
||||||
|
self.varargs_ops = frozenset([
|
||||||
|
self.opc.BUILD_LIST, self.opc.BUILD_TUPLE,
|
||||||
|
self.opc.BUILD_SLICE, self.opc.UNPACK_SEQUENCE,
|
||||||
|
self.opc.MAKE_FUNCTION, self.opc.CALL_FUNCTION,
|
||||||
|
self.opc.MAKE_CLOSURE, self.opc.CALL_FUNCTION_VAR,
|
||||||
|
self.opc.CALL_FUNCTION_KW, self.opc.CALL_FUNCTION_VAR_KW,
|
||||||
|
self.opc.DUP_TOPX, self.opc.RAISE_VARARGS,
|
||||||
|
# New in Python 2.7
|
||||||
|
self.opc.BUILD_SET])
|
||||||
|
|
||||||
# "setup" opcodes
|
# "setup" opcodes
|
||||||
self.setup_ops = frozenset([
|
self.setup_ops = frozenset([
|
||||||
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY,
|
||||||
|
Reference in New Issue
Block a user