Misc refactorings

This commit is contained in:
rocky 2016-06-02 16:58:42 -04:00
parent 3bd41b68ec
commit 167f5af5e6
6 changed files with 20 additions and 113 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*_dis
*.pyc
*~
/.cache
/.eggs

View File

@ -84,9 +84,10 @@ for usage help.
Known Bugs/Restrictions
-----------------------
Python 2 deparsing decompiles about the first 140 or so of the Python
2.7.10 and 2.7.11 standard library files and all but less that 10%
verify. So as such, it is probably a little better than uncompyle2.
Python 2 deparsing decompiles each and all the Python 2.7.10 and 2.7.11 installed packages
I have on my system. All but less that 10%
verify. Some of thse failures may be bugs in the verification process.
So as such, it is probably a little better than uncompyle2.
Other Python 2 versions do worse.
Python 3 deparsing before 3.5 is okay, but even there, more work is needed to

View File

@ -1,9 +1,6 @@
# Copyright (c) 1999 John Aycock
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2015 Rocky Bernstein
#
# See LICENSE for license
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 1999 John Aycock
"""
A spark grammar for Python 2.x.
@ -20,15 +17,11 @@ from __future__ import print_function
from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
from uncompyle6.parsers.astnode import AST
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6 import PYTHON3
class Python2Parser(PythonParser):
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
if PYTHON3:
super().__init__(AST, 'stmts', debug=debug_parser)
else:
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
super(Python2Parser, self).__init__(AST, 'stmts', debug=debug_parser)
self.customized = {}
def p_list_comprehension2(self, args):

View File

@ -49,9 +49,11 @@ class Scanner2(scan.Scanner):
dis.disassemble().
"""
## FIXME: DRY with disassemble_native
# import dis; dis.disassemble(co) # DEBUG
# DEBUG
# from xdis.bytecode import Bytecode
# bytecode = Bytecode(co, self.opc)
# for instr in bytecode.get_instructions(co):
# print(instr._disassemble())
# Container for tokens
tokens = []
@ -60,6 +62,7 @@ class Scanner2(scan.Scanner):
Token = self.Token # shortcut
n = self.setup_code(co)
self.build_lines_data(co, n)
self.build_prev_op(n)
@ -203,75 +206,6 @@ class Scanner2(scan.Scanner):
tokens.append(Token(replace[offset], oparg, pattr, offset, linestart))
return tokens, customize
def disassemble_native(self, co, classname=None, code_objects={}):
"""
Like disassemble3 but doesn't try to adjust any opcodes.
"""
## FIXME: DRY with disassemble
# Container for tokens
tokens = []
customize = {}
Token = self.Token # shortcut
n = self.setup_code(co)
self.build_lines_data(co, n)
# self.lines contains (block,addrLastInstr)
if classname:
classname = '_' + classname.lstrip('_') + '__'
def unmangle(name):
if name.startswith(classname) and name[-2:] != '__':
return name[len(classname) - 2:]
return name
free = [ unmangle(name) for name in (co.co_cellvars + co.co_freevars) ]
names = [ unmangle(name) for name in co.co_names ]
varnames = [ unmangle(name) for name in co.co_varnames ]
else:
free = co.co_cellvars + co.co_freevars
names = co.co_names
varnames = co.co_varnames
extended_arg = 0
for offset in self.op_range(0, n):
op = self.code[offset]
op_name = self.opc.opname[op]
oparg = None; pattr = None
if op >= self.opc.HAVE_ARGUMENT:
oparg = self.get_argument(offset) + extended_arg
extended_arg = 0
if op == self.opc.EXTENDED_ARG:
extended_arg = oparg * scan.L65536
continue
if op in self.opc.hasconst:
pattr = co.co_consts[oparg]
elif op in self.opc.hasname:
pattr = names[oparg]
elif op in self.opc.hasjrel:
pattr = repr(offset + 3 + oparg)
elif op in self.opc.hasjabs:
pattr = repr(oparg)
elif op in self.opc.haslocal:
pattr = varnames[oparg]
elif op in self.opc.hascompare:
pattr = self.opc.cmp_op[oparg]
elif op in self.opc.hasfree:
pattr = free[oparg]
if offset in self.linestartoffsets:
linestart = self.linestartoffsets[offset]
else:
linestart = None
tokens.append(Token(op_name, oparg, pattr, offset, linestart))
pass
return tokens, customize
def op_size(self, op):
"""
Return size of operator with its arguments

View File

@ -73,7 +73,10 @@ class Scanner26(scan.Scanner2):
dis.disassemble().
'''
# import dis; dis.disassemble(co) # DEBUG
# from xdis.bytecode import Bytecode
# bytecode = Bytecode(co, self.opc)
# for instr in bytecode.get_instructions(co):
# print(instr._disassemble())
# Container for tokens
tokens = []
@ -82,7 +85,8 @@ class Scanner26(scan.Scanner2):
Token = self.Token # shortcut
n = self.setup_code(co)
self.build_lines_data(co, n)
self.build_lines_data(co, n-1)
# linestarts contains block code adresses (addr,block)
self.linestarts = list(findlinestarts(co))

View File

@ -176,32 +176,6 @@ class Scanner3(scan.Scanner):
pass
return tokens, {}
def disassemble_native(self, co, classname=None, code_objects={}):
"""
Like disassemble3 but doesn't try to adjust any opcodes.
"""
# Container for tokens
tokens = []
self.code = array('B', co.co_code)
bytecode = Bytecode(co, self.opc)
for inst in bytecode:
pattr = inst.argrepr
opname = inst.opname
tokens.append(
Token(
type_ = opname,
attr = inst.argval,
pattr = pattr,
offset = inst.offset,
linestart = inst.starts_line,
)
)
pass
return tokens, {}
def build_lines_data(self, code_obj):
"""
Generate various line-related helper data.