More python2 -> python3 compatibility

This commit is contained in:
rocky
2015-12-11 17:54:30 -05:00
parent d3c732298c
commit b3c8cbb83f
19 changed files with 387 additions and 286 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
*.pyc
*~
/.python-version
/uncompyle6.egg-info
build

56
__pkginfo__.py Normal file
View File

@@ -0,0 +1,56 @@
"""uncompyle6 packaging information"""
# To the extent possible we make this file look more like a
# configuration file rather than code like setup.py. I find putting
# configuration stuff in the middle of a function call in setup.py,
# which for example requires commas in between parameters, is a little
# less elegant than having it here with reduced code, albeit there
# still is some room for improvement.
# Things that change more often go here.
copyright = """
Copyright (C) 2015 Rocky Bernstein <rocky@gnu.org>.
"""
# classifiers = ['Development Status :: 5 - Production/Stable',
# 'Environment :: Console',
# 'Intended Audience :: Developers',
# 'License :: OSI Approved :: GNU General Public License (GPL)',
# 'Operating System :: OS Independent',
# 'Programming Language :: Python',
# 'Topic :: Software Development :: Debuggers',
# 'Topic :: Software Development :: Libraries :: Python Modules',
# ]
# The rest in alphabetic order
author = "Rocky Bernstein"
author_email = "rocky@gnu.org"
ftp_url = None
# license = 'GPL'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'
packages = ['uncompyle6', 'uncompyle6.opcodes']
py_modules = None
short_desc = 'Python byte-code to source-code converter'
import os
import os.path, sys
def get_srcdir():
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
return os.path.realpath(filename)
# VERSION.py sets variable VERSION.
ns = {}
version = '2.0'
web = 'https://github.com/rocky/uncompyle6/'
# tracebacks in zip files are funky and not debuggable
zip_safe = False
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
long_description = ( read("README.rst") + '\n' )

View File

@@ -1,15 +1,38 @@
#! python
"""Setup script for the 'uncompyle' distribution."""
"""Setup script for the 'uncompyle6' distribution."""
from distutils.core import setup, Extension
setup (name = "uncompyle6",
version = "2.0",
description = "Python byte-code to source-code converter",
author = "Mysterie",
author_email = "kajusska@gmail.com",
url = "http://github.com/Mysterie/uncompyle2",
packages=['uncompyle6', 'uncompyle6.opcode'],
scripts=['scripts/uncompyle6']
)
# Get the package information used in setup().
# from __pkginfo__ import \
# author, author_email, classifiers, \
# install_requires, license, long_description, \
# modname, packages, py_modules, \
# short_desc, version, web, zip_safe
from __pkginfo__ import \
author, author_email, \
long_description, \
modname, packages, py_modules, \
short_desc, version, web, zip_safe
__import__('pkg_resources')
from setuptools import setup
setup(
author = author,
author_email = author_email,
# classifiers = classifiers,
description = short_desc,
# install_requires = install_requires,
# license = license,
long_description = long_description,
py_modules = py_modules,
name = modname,
packages = packages,
test_suite = 'nose.collector',
url = web,
setup_requires = ['nose>=1.0'],
version = version,
zip_safe = zip_safe)

View File

@@ -1,4 +1,6 @@
#! python
#!/usr/bin/env python
from __future__ import print_function
"""
compile_tests -- compile test patterns for the decompyle test suite
"""
@@ -20,8 +22,8 @@ for opt, val in opts:
if args:
raise 'This tool does not want any arguments'
print "Using files in dir %s" % src_dir
print "Compiling into dir %s" % work_dir
print("Using files in dir %s" % src_dir)
print("Compiling into dir %s" % work_dir)
tests = {}
@@ -46,6 +48,7 @@ tests['2.3'] = tests['2.2']
tests['2.5'] = tests['2.3']
tests['2.6'] = tests['2.5']
tests['2.7'] = ['mine'] + tests['2.6']
tests['3.4'] = ['mine']
total_tests = len(tests['2.7'])
#tests['2.2'].sort(); print tests['2.2']
@@ -62,13 +65,13 @@ def compile_for_version(version):
os.mkdir(target_dir)
for file in tests[version]:
compile(file, target_dir)
try:
version = '%i.%i' % sys.version_info[:2]
except AttributeError:
version = sys.version[:3]
print 'Compiling test files for Python', version,
print '(%i/%i files)' % (len(tests[version]), total_tests)
print('Compiling test files for Python', version)
print('(%i/%i files)' % (len(tests[version]), total_tests))
compile_for_version(version)
print 'Done.'
print('Done.')

View File

@@ -1,4 +1,5 @@
#! python
#!/usr/bin/env python
from __future__ import print_function
'''
test_pythonlib -- uncompyle and verify Python libraries
@@ -19,7 +20,7 @@ Step 2: Run the test:
test_pythonlib --mylib --verify # decompile verify 'mylib'
'''
from uncompyle2 import main, verify
from uncompyle6 import main, verify
import getopt, sys
import os, time, shutil
from fnmatch import fnmatch
@@ -44,11 +45,11 @@ test_options = {
#-----
def help():
print 'Usage-Examples:'
print 'test_pythonlib --all # decompile all tests (suite + libs)'
print 'test_pythonlib --all --verify # decomyile all tests and verify results'
print 'test_pythonlib --test # decompile only the testsuite'
print 'test_pythonlib --2.2 --verify # decompile and verify python lib 2.2'
print('Usage-Examples:')
print('test_pythonlib --all # decompile all tests (suite + libs)')
print('test_pythonlib --all --verify # decomyile all tests and verify results')
print('test_pythonlib --test # decompile only the testsuite')
print('test_pythonlib --2.2 --verify # decompile and verify python lib 2.2')
def do_tests(src_dir, patterns, target_dir, start_with=None, do_verify=0):
def visitor(files, dirname, names):
@@ -69,18 +70,18 @@ def do_tests(src_dir, patterns, target_dir, start_with=None, do_verify=0):
try:
start_with = files.index(start_with)
files = files[start_with:]
print '>>> starting with file', files[0]
print('>>> starting with file', files[0])
except ValueError:
pass
print time.ctime()
print 'Working directory: ', src_dir
print(time.ctime())
print('Working directory: ', src_dir)
try:
main(src_dir, target_dir, files, [], do_verify=do_verify)
except (KeyboardInterrupt, OSError):
print
print
exit(1)
if __name__ == '__main__':
do_verify = 0
test_dirs = []

View File

@@ -1,6 +1,6 @@
import uncompyle2
from uncompyle2 import uncompyle, walker, verify, magics
from uncompyle2.spark import GenericASTTraversal, GenericASTTraversalPruningException
import uncompyle6
from uncompyle6 import uncompyle, walker, verify, magics
from uncompyle6.spark import GenericASTTraversal, GenericASTTraversalPruningException
import sys, inspect, types, cStringIO
from collections import namedtuple
@@ -137,7 +137,7 @@ def uncompyle_find(version, co, find_offset, out=sys.stdout, showasm=0, showast=
# store final output stream for case of error
__real_out = out or sys.stdout
if version == 2.7:
import uncompyle2.scanner27 as scan
import uncompyle6.scanner27 as scan
scanner = scan.Scanner27()
elif version == 2.6:
import scanner26 as scan

View File

@@ -1,3 +1,6 @@
from __future__ import print_function
'''
Copyright (c) 1999 John Aycock
Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
@@ -68,9 +71,9 @@ def _load_module(filename):
try:
version = float(magics.versions[magic])
except KeyError:
raise ImportError, "Unknown magic number %s in %s" % (ord(magic[0])+256*ord(magic[1]), filename)
raise ImportError("Unknown magic number %s in %s" % (ord(magic[0])+256*ord(magic[1]), filename))
if (version > 2.7) or (version < 2.5):
raise ImportError, "This is a Python %s file! Only Python 2.5 to 2.7 files are supported." % version
raise ImportError("This is a Python %s file! Only Python 2.5 to 2.7 files are supported." % version)
#print version
fp.read(4) # timestamp
co = dis.marshalLoad(fp)
@@ -105,7 +108,7 @@ def uncompyle(version, co, out=None, showasm=0, showast=0):
walk = walker.Walker(out, scanner, showast=showast)
try:
ast = walk.build_ast(tokens, customize)
except walker.ParserError, e : # parser failed, dump disassembly
except walker.ParserError as e : # parser failed, dump disassembly
print >>__real_out, e
raise
del tokens # save memory
@@ -223,9 +226,9 @@ def main(in_base, out_base, files, codes, outfile=None,
if do_verify:
try:
verify.compare_code_with_srcfile(infile, outfile)
if not outfile: print '\n# okay decompyling', infile, __memUsage()
if not outfile: print('\n# okay decompyling', infile, __memUsage())
okay_files += 1
except verify.VerifyCmpError, e:
except verify.VerifyCmpError as e:
verify_failed_files += 1
os.rename(outfile, outfile + '_unverified')
if not outfile:
@@ -233,7 +236,7 @@ def main(in_base, out_base, files, codes, outfile=None,
print >>sys.stderr, e
else:
okay_files += 1
if not outfile: print '\n# okay decompyling', infile, __memUsage()
if not outfile: print('\n# okay decompyling', infile, __memUsage())
if outfile:
sys.stdout.write("decompiled %i files: %i okay, %i failed, %i verify failed\r" % (tot_files, okay_files, failed_files, verify_failed_files))
sys.stdout.flush()

View File

@@ -1,16 +1,20 @@
from __future__ import print_function
import struct
import struct, sys
__all__ = ['magics', 'versions']
def __build_magic(magic):
return struct.pack('Hcc', magic, '\r', '\n')
if (sys.version_info > (3, 0)):
return struct.pack('Hcc', magic, bytes('\r', 'utf-8'), bytes('\n', 'utf-8'))
else:
return struct.pack('Hcc', magic, '\r', '\n')
by_magic = {}
by_version = {}
def __by_version(magics):
for m, v in magics.items():
for m, v in list(magics.items()):
by_magic[m] = v
by_version[v] = m
return by_version
@@ -77,6 +81,7 @@ def test():
magic_20 = magics['2.0']
current = imp.get_magic()
current_version = struct.unpack('HBB', current)[0]
from trepan.api import debug; debug()
magic_current = by_magic[ current ]
print(type(magic_20), len(magic_20), repr(magic_20))
print()

View File

@@ -1,3 +1,5 @@
from __future__ import print_function
'''
Copyright (c) 1999 John Aycock
Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
@@ -9,8 +11,13 @@
__all__ = ['parse', 'AST', 'ParserError', 'Parser']
from spark import GenericASTBuilder
import string, exceptions, sys
from UserList import UserList
import string, sys
if (sys.version_info > (3, 0)):
intern = sys.intern
from collections import UserList
else:
from UserList import UserList
from scanner import Token
@@ -44,9 +51,10 @@ class ParserError(Exception):
def __str__(self):
return "Syntax error at or near `%r' token at offset %s\n" % \
(self.token, self.offset)
class Parser(GenericASTBuilder):
def __init__(self):
GenericASTBuilder.__init__(self, AST, 'stmts')
self.customized = {}
@@ -57,7 +65,7 @@ class Parser(GenericASTBuilder):
collector to collect this object.
"""
for dict in (self.rule2func, self.rules, self.rule2name):
for i in dict.keys():
for i in list(dict.keys()):
dict[i] = None
for i in dir(self):
setattr(self, i, None)
@@ -67,7 +75,7 @@ class Parser(GenericASTBuilder):
def typestring(self, token):
return token.type
def p_funcdef(self, args):
'''
stmt ::= funcdef
@@ -92,26 +100,26 @@ class Parser(GenericASTBuilder):
list_iter ::= lc_body
_come_from ::= COME_FROM
_come_from ::=
_come_from ::=
list_for ::= expr _for designator list_iter JUMP_BACK
list_if ::= expr jmp_false list_iter
list_if_not ::= expr jmp_true list_iter
list_if ::= expr jmp_false list_iter
list_if_not ::= expr jmp_true list_iter
lc_body ::= expr LIST_APPEND
'''
def p_setcomp(self, args):
'''
expr ::= setcomp
setcomp ::= LOAD_SETCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= setcomp_func
setcomp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER designator comp_iter
JUMP_BACK RETURN_VALUE RETURN_LAST
comp_iter ::= comp_if
comp_iter ::= comp_ifnot
comp_iter ::= comp_for
@@ -131,11 +139,11 @@ class Parser(GenericASTBuilder):
def p_genexpr(self, args):
'''
expr ::= genexpr
genexpr ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= genexpr_func
genexpr_func ::= LOAD_FAST FOR_ITER designator comp_iter JUMP_BACK
'''
@@ -145,7 +153,7 @@ class Parser(GenericASTBuilder):
expr ::= dictcomp
dictcomp ::= LOAD_DICTCOMP MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
stmt ::= dictcomp_func
dictcomp_func ::= BUILD_MAP LOAD_FAST FOR_ITER designator
comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST
@@ -177,7 +185,7 @@ class Parser(GenericASTBuilder):
inplace_op ::= INPLACE_RSHIFT
inplace_op ::= INPLACE_AND
inplace_op ::= INPLACE_XOR
inplace_op ::= INPLACE_OR
inplace_op ::= INPLACE_OR
'''
def p_assign(self, args):
@@ -197,11 +205,11 @@ class Parser(GenericASTBuilder):
stmt ::= print_items_stmt
stmt ::= print_nl
stmt ::= print_items_nl_stmt
print_items_stmt ::= expr PRINT_ITEM print_items_opt
print_items_nl_stmt ::= expr PRINT_ITEM print_items_opt PRINT_NEWLINE_CONT
print_items_opt ::= print_items
print_items_opt ::=
print_items_opt ::=
print_items ::= print_items print_item
print_items ::= print_item
print_item ::= expr PRINT_ITEM_CONT
@@ -222,7 +230,7 @@ class Parser(GenericASTBuilder):
'''
def p_import20(self, args):
'''
'''
stmt ::= importstmt
stmt ::= importfrom
stmt ::= importstar
@@ -234,20 +242,20 @@ class Parser(GenericASTBuilder):
import_as ::= IMPORT_NAME load_attrs designator
import_as ::= IMPORT_FROM designator
importstmt ::= LOAD_CONST LOAD_CONST import_as
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR
importstmt ::= LOAD_CONST LOAD_CONST import_as
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist2 POP_TOP
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT IMPORT_STAR
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT IMPORT_STAR
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT importlist2 POP_TOP
importmultiple ::= LOAD_CONST LOAD_CONST import_as imports_cont
imports_cont ::= imports_cont import_cont
imports_cont ::= import_cont
import_cont ::= LOAD_CONST LOAD_CONST import_as_cont
import_as_cont ::= IMPORT_NAME_CONT designator
import_as_cont ::= IMPORT_NAME_CONT load_attrs designator
import_as_cont ::= IMPORT_FROM designator
load_attrs ::= LOAD_ATTR
load_attrs ::= load_attrs LOAD_ATTR
'''
@@ -259,11 +267,11 @@ class Parser(GenericASTBuilder):
sstmt ::= stmt
sstmt ::= ifelsestmtr
sstmt ::= return_stmt RETURN_LAST
stmts_opt ::= stmts
stmts_opt ::= passstmt
passstmt ::=
passstmt ::=
_stmts ::= _stmts stmt
_stmts ::= stmt
@@ -271,7 +279,7 @@ class Parser(GenericASTBuilder):
c_stmts ::= _stmts lastc_stmt
c_stmts ::= lastc_stmt
c_stmts ::= continue_stmts
lastc_stmt ::= iflaststmt
lastc_stmt ::= whileelselaststmt
lastc_stmt ::= forelselaststmt
@@ -281,28 +289,28 @@ class Parser(GenericASTBuilder):
c_stmts_opt ::= c_stmts
c_stmts_opt ::= passstmt
l_stmts ::= _stmts
l_stmts ::= return_stmts
l_stmts ::= continue_stmts
l_stmts ::= _stmts lastl_stmt
l_stmts ::= lastl_stmt
lastl_stmt ::= iflaststmtl
lastl_stmt ::= ifelsestmtl
lastl_stmt ::= forelselaststmtl
lastl_stmt ::= tryelsestmtl
l_stmts_opt ::= l_stmts
l_stmts_opt ::= passstmt
suite_stmts ::= _stmts
suite_stmts ::= return_stmts
suite_stmts ::= continue_stmts
suite_stmts_opt ::= suite_stmts
suite_stmts_opt ::= passstmt
else_suite ::= suite_stmts
else_suitel ::= l_stmts
else_suitec ::= c_stmts
@@ -324,7 +332,7 @@ class Parser(GenericASTBuilder):
store_subscr ::= expr expr STORE_SUBSCR
designator ::= unpack
designator ::= unpack_list
stmt ::= classdef
stmt ::= call_stmt
call_stmt ::= expr POP_TOP
@@ -333,21 +341,21 @@ class Parser(GenericASTBuilder):
return_stmt ::= ret_expr RETURN_VALUE
return_stmts ::= return_stmt
return_stmts ::= _stmts return_stmt
return_if_stmts ::= return_if_stmt
return_if_stmts ::= _stmts return_if_stmt
return_if_stmt ::= ret_expr RETURN_END_IF
stmt ::= break_stmt
break_stmt ::= BREAK_LOOP
stmt ::= continue_stmt
continue_stmt ::= CONTINUE
continue_stmt ::= CONTINUE_LOOP
continue_stmts ::= _stmts lastl_stmt continue_stmt
continue_stmts ::= lastl_stmt continue_stmt
continue_stmts ::= continue_stmt
stmt ::= raise_stmt0
stmt ::= raise_stmt1
stmt ::= raise_stmt2
@@ -357,16 +365,16 @@ class Parser(GenericASTBuilder):
raise_stmt1 ::= expr RAISE_VARARGS_1
raise_stmt2 ::= expr expr RAISE_VARARGS_2
raise_stmt3 ::= expr expr expr RAISE_VARARGS_3
stmt ::= exec_stmt
exec_stmt ::= expr exprlist DUP_TOP EXEC_STMT
exec_stmt ::= expr exprlist EXEC_STMT
stmt ::= assert
stmt ::= assert2
stmt ::= ifstmt
stmt ::= ifelsestmt
stmt ::= whilestmt
stmt ::= whilenotstmt
stmt ::= while1stmt
@@ -379,7 +387,7 @@ class Parser(GenericASTBuilder):
stmt ::= tryfinallystmt
stmt ::= withstmt
stmt ::= withasstmt
stmt ::= del_stmt
del_stmt ::= DELETE_FAST
del_stmt ::= DELETE_NAME
@@ -391,12 +399,12 @@ class Parser(GenericASTBuilder):
del_stmt ::= delete_subscr
delete_subscr ::= expr expr DELETE_SUBSCR
del_stmt ::= expr DELETE_ATTR
kwarg ::= LOAD_CONST expr
classdef ::= LOAD_CONST expr mkfunc
CALL_FUNCTION_0 BUILD_CLASS designator
stmt ::= classdefdeco
classdefdeco ::= classdefdeco1 designator
classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
@@ -411,11 +419,11 @@ class Parser(GenericASTBuilder):
jmp_false ::= JUMP_IF_FALSE
jmp_true ::= POP_JUMP_IF_TRUE
jmp_true ::= JUMP_IF_TRUE
assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
assert2 ::= assert_expr jmp_true LOAD_ASSERT expr RAISE_VARARGS_2
assert_expr ::= expr
assert_expr ::= assert_expr_or
assert_expr ::= assert_expr_and
@@ -423,17 +431,17 @@ class Parser(GenericASTBuilder):
assert_expr_and ::= assert_expr jmp_false expr
ifstmt ::= testexpr _ifstmts_jump
testexpr ::= testfalse
testexpr ::= testtrue
testfalse ::= expr jmp_false
testtrue ::= expr jmp_true
_ifstmts_jump ::= return_if_stmts
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite COME_FROM
@@ -443,8 +451,8 @@ class Parser(GenericASTBuilder):
ifelsestmtr ::= testexpr return_if_stmts return_stmts
ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel
trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
try_middle COME_FROM
@@ -461,12 +469,12 @@ class Parser(GenericASTBuilder):
END_FINALLY
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY COME_FROM
except_stmts ::= except_stmts except_stmt
except_stmts ::= except_stmt
except_stmt ::= except_cond1 except_suite
except_stmt ::= except_cond2 except_suite
except_stmt ::= except_cond1 except_suite
except_stmt ::= except_cond2 except_suite
except_stmt ::= except
except_suite ::= c_stmts_opt JUMP_FORWARD
@@ -474,22 +482,22 @@ class Parser(GenericASTBuilder):
except_suite ::= return_stmts
except_cond1 ::= DUP_TOP expr COMPARE_OP
jmp_false POP_TOP POP_TOP POP_TOP
jmp_false POP_TOP POP_TOP POP_TOP
except_cond2 ::= DUP_TOP expr COMPARE_OP
jmp_false POP_TOP designator POP_TOP
except ::= POP_TOP POP_TOP POP_TOP c_stmts_opt JUMP_FORWARD
except ::= POP_TOP POP_TOP POP_TOP c_stmts_opt jmp_abs
except ::= POP_TOP POP_TOP POP_TOP return_stmts
jmp_abs ::= JUMP_ABSOLUTE
jmp_abs ::= JUMP_BACK
tryfinallystmt ::= SETUP_FINALLY suite_stmts
POP_BLOCK LOAD_CONST
COME_FROM suite_stmts_opt END_FINALLY
withstmt ::= expr SETUP_WITH POP_TOP suite_stmts_opt
POP_BLOCK LOAD_CONST COME_FROM
WITH_CLEANUP END_FINALLY
@@ -527,7 +535,7 @@ class Parser(GenericASTBuilder):
for_block ::= l_stmts_opt JUMP_BACK
for_block ::= return_stmts _come_from
forstmt ::= SETUP_LOOP expr _for designator
for_block POP_BLOCK COME_FROM
@@ -577,7 +585,7 @@ class Parser(GenericASTBuilder):
expr ::= buildslice2
expr ::= buildslice3
expr ::= yield
binary_expr ::= expr expr binary_op
binary_op ::= BINARY_ADD
binary_op ::= BINARY_MULTIPLY
@@ -616,7 +624,7 @@ class Parser(GenericASTBuilder):
slice3 ::= expr expr expr DUP_TOPX_3 SLICE+3
buildslice3 ::= expr expr expr BUILD_SLICE_3
buildslice2 ::= expr expr BUILD_SLICE_2
yield ::= expr YIELD_VALUE
_mklambda ::= load_closure mklambda
@@ -627,17 +635,17 @@ class Parser(GenericASTBuilder):
and ::= expr jmp_false expr _come_from
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
and2 ::= _jump jmp_false COME_FROM expr COME_FROM
expr ::= conditional
conditional ::= expr jmp_false expr JUMP_FORWARD expr COME_FROM
conditional ::= expr jmp_false expr JUMP_ABSOLUTE expr
expr ::= conditionalnot
conditionalnot ::= expr jmp_true expr _jump expr COME_FROM
ret_expr ::= expr
ret_expr ::= ret_and
ret_expr ::= ret_or
ret_expr_or_cond ::= ret_expr
ret_expr_or_cond ::= ret_cond
ret_expr_or_cond ::= ret_cond_not
@@ -649,9 +657,9 @@ class Parser(GenericASTBuilder):
stmt ::= return_lambda
stmt ::= conditional_lambda
return_lambda ::= ret_expr RETURN_VALUE LAMBDA_MARKER
conditional_lambda ::= expr jmp_false return_if_stmt return_stmt LAMBDA_MARKER
conditional_lambda ::= expr jmp_false return_if_stmt return_stmt LAMBDA_MARKER
cmp ::= cmp_list
cmp ::= compare
@@ -704,7 +712,7 @@ class Parser(GenericASTBuilder):
def __ambiguity(self, children):
# only for debugging! to be removed hG/2000-10-15
print children
print(children)
return GenericASTBuilder.ambiguity(self, children)
def resolve(self, list):
@@ -737,9 +745,9 @@ def parse(tokens, customize):
# expr ::= expr {expr}^n CALL_FUNCTION_KW_n POP_TOP
#
global p
for k, v in customize.items():
for k, v in list(customize.items()):
# avoid adding the same rule twice to this parser
if p.customized.has_key(k):
if k in p.customized:
continue
p.customized[k] = None

View File

@@ -12,14 +12,14 @@ from array import array
from operator import itemgetter
from struct import *
from uncompyle2.opcode.opcode_25 import *
from uncompyle6.opcodes.opcode_25 import *
import disas as dis
import scanner as scan
class Scanner25(scan.Scanner):
def __init__(self):
self.Token = scan.Scanner.__init__(self, 2.5)
def disassemble(self, co, classname=None):
'''
Disassemble a code object, returning a list of 'Token'.
@@ -38,7 +38,7 @@ class Scanner25(scan.Scanner):
# linestarts contains bloc code adresse (addr,block)
self.linestarts = list(dis.findlinestarts(co))
self.prev = [0]
# class and names
if classname:
classname = '_' + classname.lstrip('_') + '__'
@@ -46,7 +46,7 @@ class Scanner25(scan.Scanner):
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 ]
@@ -82,13 +82,13 @@ class Scanner25(scan.Scanner):
while j < codelen:
self.lines.append(linetuple(prev_line_no, codelen))
j+=1
self.load_asserts = set()
for i in self.op_range(0, codelen):
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
if names[self.get_argument(i+3)] == 'AssertionError':
self.load_asserts.add(i+3)
# self.lines contains (block,addrLastInstr)
cf = self.find_jump_targets(self.code)
# contains (code, [addrRefToCode])
@@ -104,7 +104,7 @@ class Scanner25(scan.Scanner):
replace[i] = 'PRINT_NEWLINE_CONT'
last_stmt = i
i = self.next_stmt[i]
imports = self.all_instr(0, codelen, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR))
if len(imports) > 1:
last_import = imports[0]
@@ -220,10 +220,10 @@ class Scanner25(scan.Scanner):
'''
opcode = self.code[i]
opsize = self.op_size(opcode)
if i+opsize >= len(self.code):
return None
if opcode == EXTENDED_ARG:
raise NotImplementedError
# del POP_TOP
@@ -283,7 +283,7 @@ class Scanner25(scan.Scanner):
target = self.get_target(target-3)
self.restructJump(start, target)
start += self.op_size(PJIF)
# del DELETE_NAME x
# del DELETE_NAME x
start = end
while end < len(self.code):
end = self.first_instr(end, len(self.code), (DELETE_NAME,DELETE_FAST))
@@ -297,7 +297,7 @@ class Scanner25(scan.Scanner):
return toDel
# change join(for..) struct
if opcode == SETUP_LOOP:
if self.code[i+3] == LOAD_FAST and self.code[i+6] == FOR_ITER:
if self.code[i+3] == LOAD_FAST and self.code[i+6] == FOR_ITER:
end = self.first_instr(i, len(self.code), RETURN_VALUE)
end = self.first_instr(i, end, YIELD_VALUE)
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
@@ -357,7 +357,7 @@ class Scanner25(scan.Scanner):
i+=2
i+=1
return listExp
def restructCode(self, listDel, listExp):
'''
restruct linestarts and jump destination
@@ -389,7 +389,7 @@ class Scanner25(scan.Scanner):
if listDel:
for jmp in self.op_range(0, len(self.code)):
op = self.code[jmp]
if op in hasjrel+hasjabs:
if op in hasjrel+hasjabs:
offset = 0
jmpTarget = self.get_target(jmp)
for toDel in listDel:
@@ -412,7 +412,7 @@ class Scanner25(scan.Scanner):
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
jmp += 3
else: jmp += 1
def restructBytecode(self):
'''
add/change/delete bytecode for suiting bytecode 2.7
@@ -420,9 +420,9 @@ class Scanner25(scan.Scanner):
# we can't use op_range for the moment
# convert jump opcode to 2.7
self.restructRelativeJump()
listExp = self.getOpcodeToExp()
# change code structure
# change code structure
if listExp:
listExp = sorted(list(set(listExp)))
self.restructCode([], listExp)
@@ -439,7 +439,7 @@ class Scanner25(scan.Scanner):
ret = self.getOpcodeToDel(i)
if ret != None:
listDel += ret
# change code structure after deleting byte
if listDel:
listDel = sorted(list(set(listDel)))
@@ -455,7 +455,7 @@ class Scanner25(scan.Scanner):
else:
self.code.pop(x-delta)
delta += 1
def restructRelativeJump(self):
'''
change relative JUMP_IF_FALSE/TRUE to absolut jump
@@ -495,7 +495,7 @@ class Scanner25(scan.Scanner):
raise NotImplementedError
self.code[pos+2] = (target >> 8) & 0xFF
self.code[pos+1] = target & 0xFF
def build_stmt_indices(self):
code = self.code
start = 0;
@@ -513,9 +513,9 @@ class Scanner25(scan.Scanner):
}
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
@@ -532,17 +532,17 @@ class Scanner25(scan.Scanner):
match = False
break
i += self.op_size(code[i])
if match:
i = self.prev[i]
stmts.add(i)
pass_stmts.add(i)
if pass_stmts:
stmt_list = list(stmts)
stmt_list.sort()
else:
stmt_list = prelim
stmt_list = prelim
last_stmt = -1
self.next_stmt = []
slist = self.next_stmt = []
@@ -573,7 +573,7 @@ class Scanner25(scan.Scanner):
slist += [s] * (s-i)
i = s
slist += [end] * (end-len(slist))
def next_except_jump(self, start):
'''
Return the next jump that was generated by an except SomeException:
@@ -602,7 +602,7 @@ class Scanner25(scan.Scanner):
elif op in (SETUP_EXCEPT, SETUP_FINALLY):
count_SETUP_ += 1
#return self.lines[start].next
def detect_structure(self, pos, op=None):
'''
Detect type of block structures and their boundaries to fix optimizied jumps
@@ -635,7 +635,7 @@ class Scanner25(scan.Scanner):
if target != end:
self.fixed_jumps[pos] = end
(line_no, next_line_byte) = self.lines[pos]
jump_back = self.last_instr(start, end, JA,
next_line_byte, False)
@@ -645,7 +645,7 @@ class Scanner25(scan.Scanner):
jump_back = None
if not jump_back: # loop suite ends in return. wtf right?
jump_back = self.last_instr(start, end, RETURN_VALUE)
if not jump_back:
if not jump_back:
return
jump_back += 1
if code[self.prev[next_line_byte]] not in (PJIF, PJIT):
@@ -667,7 +667,7 @@ class Scanner25(scan.Scanner):
elif target < pos:
self.fixed_jumps[pos] = jump_back+4
end = jump_back+4
target = self.get_target(jump_back, JA)
if code[target] in (FOR_ITER, GET_ITER):
@@ -677,7 +677,7 @@ class Scanner25(scan.Scanner):
test = self.prev[next_line_byte]
if test == pos:
loop_type = 'while 1'
elif self.code[test] in hasjabs+hasjrel:
elif self.code[test] in hasjabs+hasjrel:
self.ignore_if.add(test)
test_target = self.get_target(test)
if test_target > (jump_back+3):
@@ -725,7 +725,7 @@ class Scanner25(scan.Scanner):
self.structs.append({'type': 'except',
'start': i,
'end': jmp})
i = jmp + 3
i = jmp + 3
## Add the try-else block
if end_else != start_else:
@@ -754,7 +754,7 @@ class Scanner25(scan.Scanner):
'start': start,
'end': pre[target]})
return
# is this an if and
if op == PJIF:
match = self.rem_or(start, self.next_stmt[pos], PJIF, target)
@@ -790,7 +790,7 @@ class Scanner25(scan.Scanner):
self.fixed_jumps[pos] = fix or match[-1]
return
elif pos < rtarget and code[target] == ROT_TWO:
self.fixed_jumps[pos] = target
self.fixed_jumps[pos] = target
return
else:
self.fixed_jumps[pos] = match[-1]
@@ -800,7 +800,7 @@ class Scanner25(scan.Scanner):
if code[pre[rtarget]] == RAISE_VARARGS:
return
self.load_asserts.remove(pos+3)
next = self.next_stmt[pos]
if pre[next] == pos:
pass
@@ -816,7 +816,7 @@ class Scanner25(scan.Scanner):
#don't add a struct for a while test, it's already taken care of
if pos in self.ignore_if:
return
if code[pre[rtarget]] == JA and pre[rtarget] in self.stmts \
and pre[rtarget] != pos and pre[pre[rtarget]] != pos \
and not (code[rtarget] == JA and code[rtarget+3] == POP_BLOCK and code[pre[pre[rtarget]]] != JA):
@@ -824,19 +824,19 @@ class Scanner25(scan.Scanner):
#does the if jump just beyond a jump op, then this is probably an if statement
if code[pre[rtarget]] in (JA, JF):
if_end = self.get_target(pre[rtarget])
#is this a loop not an if?
if (if_end < pre[rtarget]) and (code[pre[if_end]] == SETUP_LOOP):
if(if_end > start):
return
end = self.restrict_to_parent(if_end, parent)
self.structs.append({'type': 'if-then',
'start': start,
'end': pre[rtarget]})
self.not_continue.add(pre[rtarget])
if rtarget < end:
self.structs.append({'type': 'if-else',
'start': rtarget,
@@ -867,7 +867,7 @@ class Scanner25(scan.Scanner):
self.loops = [] ## All loop entry points
self.fixed_jumps = {} ## Map fixed jumps to their real destination
self.ignore_if = set()
self.build_stmt_indices()
self.build_stmt_indices()
self.not_continue = set()
self.return_end_ifs = set()
@@ -880,7 +880,7 @@ class Scanner25(scan.Scanner):
if self.op_hasArgument(op):
label = self.fixed_jumps.get(i)
oparg = self.get_argument(i)
oparg = self.get_argument(i)
if label is None:
if op in hasjrel and op != FOR_ITER:
label = i + 3 + oparg

View File

@@ -12,14 +12,14 @@ from array import array
from operator import itemgetter
from struct import *
from uncompyle2.opcode.opcode_26 import *
from uncompyle6.opcodes.opcode_26 import *
import disas as dis
import scanner as scan
class Scanner26(scan.Scanner):
def __init__(self):
self.Token = scan.Scanner.__init__(self, 2.6)
def disassemble(self, co, classname=None):
'''
Disassemble a code object, returning a list of 'Token'.
@@ -27,7 +27,7 @@ class Scanner26(scan.Scanner):
The main part of this procedure is modelled after
dis.disassemble().
'''
rv = []
customize = {}
Token = self.Token # shortcut
@@ -46,7 +46,7 @@ class Scanner26(scan.Scanner):
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 ]
@@ -60,7 +60,7 @@ class Scanner26(scan.Scanner):
self.toChange = []
self.restructBytecode()
codelen = len(self.code)
# mapping adresses of prev instru
# mapping adresses of prev instru
for i in self.op_range(0, codelen):
op = self.code[i]
self.prev.append(i)
@@ -83,13 +83,13 @@ class Scanner26(scan.Scanner):
self.lines.append(linetuple(prev_line_no, codelen))
j+=1
# self.lines contains (block,addrLastInstr)
self.load_asserts = set()
for i in self.op_range(0, codelen):
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
if names[self.get_argument(i+3)] == 'AssertionError':
self.load_asserts.add(i+3)
cf = self.find_jump_targets(self.code)
# contains (code, [addrRefToCode])
@@ -105,7 +105,7 @@ class Scanner26(scan.Scanner):
replace[i] = 'PRINT_NEWLINE_CONT'
last_stmt = i
i = self.next_stmt[i]
imports = self.all_instr(0, codelen, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR))
if len(imports) > 1:
last_import = imports[0]
@@ -248,10 +248,10 @@ class Scanner26(scan.Scanner):
if destFor == i+opsize+4:
setupLoop = self.last_instr(0, jmpabs1target, SETUP_LOOP)
standarFor = self.last_instr(setupLoop, jmpabs1target, GET_ITER)
if standarFor == None:
if standarFor == None:
self.restructJump(jmpabs1target, destFor+self.op_size(POP_BLOCK))
toDel += [setupLoop, i+opsize+1, i+opsize+4]
if len(toDel) > 0:
return toDel
return None
@@ -288,7 +288,7 @@ class Scanner26(scan.Scanner):
target = self.get_target(target-3)
self.restructJump(start, target)
start += self.op_size(PJIF)
# del DELETE_NAME x
# del DELETE_NAME x
start = end
while end < len(self.code):
end = self.first_instr(end, len(self.code), (DELETE_NAME,DELETE_FAST))
@@ -303,7 +303,7 @@ class Scanner26(scan.Scanner):
# for / while struct
if opcode == SETUP_LOOP:
# change join(for..) struct
if self.code[i+3] == LOAD_FAST and self.code[i+6] == FOR_ITER:
if self.code[i+3] == LOAD_FAST and self.code[i+6] == FOR_ITER:
end = self.first_instr(i, len(self.code), RETURN_VALUE)
end = self.first_instr(i, end, YIELD_VALUE)
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
@@ -385,7 +385,7 @@ class Scanner26(scan.Scanner):
if listDel:
for jmp in self.op_range(0, len(self.code)):
op = self.code[jmp]
if op in hasjrel+hasjabs:
if op in hasjrel+hasjabs:
offset = 0
jmpTarget = self.get_target(jmp)
for toDel in listDel:
@@ -416,9 +416,9 @@ class Scanner26(scan.Scanner):
# we can't use op_range for the moment
# convert jump opcode to 2.7
self.restructRelativeJump()
listExp = self.getOpcodeToExp()
# change code structure
# change code structure
if listExp:
listExp = sorted(list(set(listExp)))
self.restructCode([], listExp)
@@ -435,7 +435,7 @@ class Scanner26(scan.Scanner):
ret = self.getOpcodeToDel(i)
if ret != None:
listDel += ret
# change code structure after deleting byte
if listDel:
listDel = sorted(list(set(listDel)))
@@ -479,7 +479,7 @@ class Scanner26(scan.Scanner):
if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended:
i += 3
else: i += 1
def restructJump(self, pos, newTarget):
if not (self.code[pos] in hasjabs+hasjrel):
raise 'Can t change this argument. Opcode is not a jump'
@@ -491,7 +491,7 @@ class Scanner26(scan.Scanner):
raise NotImplementedError
self.code[pos+2] = (target >> 8) & 0xFF
self.code[pos+1] = target & 0xFF
def build_stmt_indices(self):
code = self.code
start = 0;
@@ -509,9 +509,9 @@ class Scanner26(scan.Scanner):
}
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
@@ -528,17 +528,17 @@ class Scanner26(scan.Scanner):
match = False
break
i += self.op_size(code[i])
if match:
i = self.prev[i]
stmts.add(i)
pass_stmts.add(i)
if pass_stmts:
stmt_list = list(stmts)
stmt_list.sort()
else:
stmt_list = prelim
stmt_list = prelim
last_stmt = -1
self.next_stmt = []
slist = self.next_stmt = []
@@ -634,7 +634,7 @@ class Scanner26(scan.Scanner):
if target != end:
self.fixed_jumps[pos] = end
(line_no, next_line_byte) = self.lines[pos]
jump_back = self.last_instr(start, end, JA,
next_line_byte, False)
@@ -644,7 +644,7 @@ class Scanner26(scan.Scanner):
jump_back = None
if not jump_back: # loop suite ends in return. wtf right?
jump_back = self.last_instr(start, end, RETURN_VALUE)
if not jump_back:
if not jump_back:
return
jump_back += 1
if code[self.prev[next_line_byte]] not in (PJIF, PJIT):
@@ -666,7 +666,7 @@ class Scanner26(scan.Scanner):
elif target < pos:
self.fixed_jumps[pos] = jump_back+4
end = jump_back+4
target = self.get_target(jump_back, JA)
if code[target] in (FOR_ITER, GET_ITER):
@@ -676,7 +676,7 @@ class Scanner26(scan.Scanner):
test = self.prev[next_line_byte]
if test == pos:
loop_type = 'while 1'
elif self.code[test] in hasjabs+hasjrel:
elif self.code[test] in hasjabs+hasjrel:
self.ignore_if.add(test)
test_target = self.get_target(test)
if test_target > (jump_back+3):
@@ -725,7 +725,7 @@ class Scanner26(scan.Scanner):
self.structs.append({'type': 'except',
'start': i,
'end': jmp})
i = jmp + 3
i = jmp + 3
## Add the try-else block
if end_else != start_else:
@@ -754,7 +754,7 @@ class Scanner26(scan.Scanner):
'start': start,
'end': pre[target]})
return
# is this an if and
if op == PJIF:
match = self.rem_or(start, self.next_stmt[pos], PJIF, target)
@@ -790,7 +790,7 @@ class Scanner26(scan.Scanner):
self.fixed_jumps[pos] = fix or match[-1]
return
elif pos < rtarget and code[target] == ROT_TWO:
self.fixed_jumps[pos] = target
self.fixed_jumps[pos] = target
return
else:
self.fixed_jumps[pos] = match[-1]
@@ -800,7 +800,7 @@ class Scanner26(scan.Scanner):
if code[pre[rtarget]] == RAISE_VARARGS:
return
self.load_asserts.remove(pos+3)
next = self.next_stmt[pos]
if pre[next] == pos:
pass
@@ -816,7 +816,7 @@ class Scanner26(scan.Scanner):
#don't add a struct for a while test, it's already taken care of
if pos in self.ignore_if:
return
if code[pre[rtarget]] == JA and pre[rtarget] in self.stmts \
and pre[rtarget] != pos and pre[pre[rtarget]] != pos \
and not (code[rtarget] == JA and code[rtarget+3] == POP_BLOCK and code[pre[pre[rtarget]]] != JA):
@@ -824,19 +824,19 @@ class Scanner26(scan.Scanner):
#does the if jump just beyond a jump op, then this is probably an if statement
if code[pre[rtarget]] in (JA, JF):
if_end = self.get_target(pre[rtarget])
#is this a loop not an if?
if (if_end < pre[rtarget]) and (code[pre[if_end]] == SETUP_LOOP):
if(if_end > start):
return
end = self.restrict_to_parent(if_end, parent)
self.structs.append({'type': 'if-then',
'start': start,
'end': pre[rtarget]})
self.not_continue.add(pre[rtarget])
if rtarget < end:
self.structs.append({'type': 'if-else',
'start': rtarget,
@@ -867,7 +867,7 @@ class Scanner26(scan.Scanner):
self.loops = [] ## All loop entry points
self.fixed_jumps = {} ## Map fixed jumps to their real destination
self.ignore_if = set()
self.build_stmt_indices()
self.build_stmt_indices()
self.not_continue = set()
self.return_end_ifs = set()
@@ -880,7 +880,7 @@ class Scanner26(scan.Scanner):
if self.op_hasArgument(op):
label = self.fixed_jumps.get(i)
oparg = self.get_argument(i)
oparg = self.get_argument(i)
if label is None:
if op in hasjrel and op != FOR_ITER:
label = i + 3 + oparg
@@ -894,4 +894,3 @@ class Scanner26(scan.Scanner):
label = self.fixed_jumps[i]
targets[label] = targets.get(label, []) + [i]
return targets

View File

@@ -11,14 +11,14 @@ from collections import namedtuple
from array import array
from operator import itemgetter
from uncompyle2.opcode.opcode_27 import *
from uncompyle6.opcodes.opcode_27 import *
import disas as dis
import scanner as scan
class Scanner27(scan.Scanner):
def __init__(self):
self.Token = scan.Scanner.__init__(self, 2.7) # check
def disassemble(self, co, classname=None):
'''
Disassemble a code object, returning a list of 'Token'.
@@ -33,7 +33,7 @@ class Scanner27(scan.Scanner):
if self.code[i] in (RETURN_VALUE, END_FINALLY):
n = i + 1
self.code = array('B', co.co_code[:n])
self.prev = [0]
# mapping adresses of instru & arg
for i in self.op_range(0, n):
@@ -42,7 +42,7 @@ class Scanner27(scan.Scanner):
if op >= HAVE_ARGUMENT:
self.prev.append(i)
self.prev.append(i)
self.lines = []
linetuple = namedtuple('linetuple', ['l_no', 'next'])
j = 0
@@ -66,7 +66,7 @@ class Scanner27(scan.Scanner):
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 ]
@@ -80,7 +80,7 @@ class Scanner27(scan.Scanner):
if self.code[i] == PJIT and self.code[i+3] == LOAD_GLOBAL:
if names[self.get_argument(i+3)] == 'AssertionError':
self.load_asserts.add(i+3)
cf = self.find_jump_targets(self.code)
# contains (code, [addrRefToCode])
last_stmt = self.next_stmt[0]
@@ -95,7 +95,7 @@ class Scanner27(scan.Scanner):
replace[i] = 'PRINT_NEWLINE_CONT'
last_stmt = i
i = self.next_stmt[i]
imports = self.all_instr(0, n, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR))
if len(imports) > 1:
last_import = imports[0]
@@ -104,7 +104,7 @@ class Scanner27(scan.Scanner):
if self.code[last_import] == IMPORT_NAME == self.code[i]:
replace[i] = 'IMPORT_NAME_CONT'
last_import = i
extended_arg = 0
for offset in self.op_range(0, n):
if offset in cf:
@@ -113,7 +113,7 @@ class Scanner27(scan.Scanner):
rv.append(Token('COME_FROM', None, repr(j),
offset="%s_%d" % (offset, k)))
k += 1
op = self.code[offset]
op_name = opname[op]
oparg = None; pattr = None
@@ -193,7 +193,7 @@ class Scanner27(scan.Scanner):
rv.append(Token(op_name, oparg, pattr, offset, linestart = offset in linestartoffsets))
else:
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
if self.showasm:
out = self.out # shortcut
for t in rv:
@@ -206,12 +206,12 @@ class Scanner27(scan.Scanner):
return 1
else:
return 3
def build_stmt_indices(self):
code = self.code
start = 0;
end = len(code)
stmt_opcodes = {
SETUP_LOOP, BREAK_LOOP, CONTINUE_LOOP,
SETUP_FINALLY, END_FINALLY, SETUP_EXCEPT, SETUP_WITH,
@@ -226,9 +226,9 @@ class Scanner27(scan.Scanner):
}
stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)]
designator_ops = {
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_FAST, STORE_NAME, STORE_GLOBAL, STORE_DEREF, STORE_ATTR,
STORE_SLICE_0, STORE_SLICE_1, STORE_SLICE_2, STORE_SLICE_3,
STORE_SUBSCR, UNPACK_SEQUENCE, JA
}
@@ -245,12 +245,12 @@ class Scanner27(scan.Scanner):
match = False
break
i += self.op_size(code[i])
if match:
i = self.prev[i]
stmts.add(i)
pass_stmts.add(i)
if pass_stmts:
stmt_list = list(stmts)
stmt_list.sort()
@@ -286,7 +286,7 @@ class Scanner27(scan.Scanner):
slist += [s] * (s-i)
i = s
slist += [end] * (end-len(slist))
def remove_mid_line_ifs(self, ifs):
filtered = []
for i in ifs:
@@ -309,7 +309,7 @@ class Scanner27(scan.Scanner):
self.ignore_if.add(except_match)
self.not_continue.add(jmp)
return jmp
count_END_FINALLY = 0
count_SETUP_ = 0
for i in self.op_range(start, len(self.code)):
@@ -367,7 +367,7 @@ class Scanner27(scan.Scanner):
jump_back = None
if not jump_back: # loop suite ends in return. wtf right?
jump_back = self.last_instr(start, end, RETURN_VALUE) + 1
if not jump_back:
if not jump_back:
return
if code[self.prev[next_line_byte]] not in (PJIF, PJIT):
loop_type = 'for'
@@ -388,7 +388,7 @@ class Scanner27(scan.Scanner):
self.fixed_jumps[pos] = jump_back+4
end = jump_back+4
target = self.get_target(jump_back, JA)
if code[target] in (FOR_ITER, GET_ITER):
loop_type = 'for'
else:
@@ -396,7 +396,7 @@ class Scanner27(scan.Scanner):
test = self.prev[next_line_byte]
if test == pos:
loop_type = 'while 1'
elif self.code[test] in hasjabs+hasjrel:
elif self.code[test] in hasjabs+hasjrel:
self.ignore_if.add(test)
test_target = self.get_target(test)
if test_target > (jump_back+3):
@@ -441,7 +441,7 @@ class Scanner27(scan.Scanner):
self.structs.append({'type': 'except',
'start': i,
'end': jmp})
i = jmp + 3
i = jmp + 3
## Add the try-else block
if end_else != start_else:
@@ -452,14 +452,14 @@ class Scanner27(scan.Scanner):
self.fixed_jumps[i] = r_end_else
else:
self.fixed_jumps[i] = i+1
elif op in (PJIF, PJIT):
start = pos+3
start = pos+3
target = self.get_target(pos, op)
rtarget = self.restrict_to_parent(target, parent)
pre = self.prev
if target != rtarget and parent['type'] == 'and/or':
self.fixed_jumps[pos] = rtarget
return
@@ -472,7 +472,7 @@ class Scanner27(scan.Scanner):
'start': start,
'end': pre[target]})
return
# is this an if and
if op == PJIF:
match = self.rem_or(start, self.next_stmt[pos], PJIF, target)
@@ -516,7 +516,7 @@ class Scanner27(scan.Scanner):
if code[pre[rtarget]] == RAISE_VARARGS:
return
self.load_asserts.remove(pos+3)
next = self.next_stmt[pos]
if pre[next] == pos:
pass
@@ -533,7 +533,7 @@ class Scanner27(scan.Scanner):
elif code[next_target] in (JA, JF) and self.get_target(next_target) == self.get_target(target):
self.fixed_jumps[pos] = pre[next]
return
#don't add a struct for a while test, it's already taken care of
if pos in self.ignore_if:
return
@@ -552,19 +552,19 @@ class Scanner27(scan.Scanner):
#does the if jump just beyond a jump op, then this is probably an if statement
if code[pre[rtarget]] in (JA, JF):
if_end = self.get_target(pre[rtarget])
#is this a loop not an if?
if (if_end < pre[rtarget]) and (code[pre[if_end]] == SETUP_LOOP):
if(if_end > start):
return
end = self.restrict_to_parent(if_end, parent)
self.structs.append({'type': 'if-then',
'start': start,
'end': pre[rtarget]})
self.not_continue.add(pre[rtarget])
if rtarget < end:
self.structs.append({'type': 'if-else',
'start': rtarget,
@@ -617,7 +617,7 @@ class Scanner27(scan.Scanner):
if op in (JUMP_IF_FALSE_OR_POP, JUMP_IF_TRUE_OR_POP):
if (oparg > i):
label = oparg
if label is not None and label != -1:
targets[label] = targets.get(label, []) + [i]
elif op == END_FINALLY and i in self.fixed_jumps:

View File

@@ -1,6 +1,7 @@
'''
from __future__ import print_function
'''
Copyright (c) 1998-2002 John Aycock
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
@@ -8,17 +9,17 @@ Copyright (c) 1998-2002 John Aycock
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''
__version__ = 'SPARK-0.7 (pre-alpha-7) uncompyle trim'
@@ -28,31 +29,31 @@ def _namelist(instance):
for c in classlist:
for b in c.__bases__:
classlist.append(b)
for name in c.__dict__.keys():
if not namedict.has_key(name):
for name in list(c.__dict__.keys()):
if name not in namedict:
namelist.append(name)
namedict[name] = 1
return namelist
#
# Extracted from GenericParser and made global so that [un]picking works.
#
class _State:
'''
Extracted from GenericParser and made global so that [un]picking works.
'''
def __init__(self, stateno, items):
self.T, self.complete, self.items = [], [], items
self.stateno = stateno
class GenericParser:
#
# An Earley parser, as per J. Earley, "An Efficient Context-Free
# Parsing Algorithm", CACM 13(2), pp. 94-102. Also J. C. Earley,
# "An Efficient Context-Free Parsing Algorithm", Ph.D. thesis,
# Carnegie-Mellon University, August 1968. New formulation of
# the parser according to J. Aycock, "Practical Earley Parsing
# and the SPARK Toolkit", Ph.D. thesis, University of Victoria,
# 2001, and J. Aycock and R. N. Horspool, "Practical Earley
# Parsing", unpublished paper, 2001.
#
'''
An Earley parser, as per J. Earley, "An Efficient Context-Free
Parsing Algorithm", CACM 13(2), pp. 94-102. Also J. C. Earley,
"An Efficient Context-Free Parsing Algorithm", Ph.D. thesis,
Carnegie-Mellon University, August 1968. New formulation of
the parser according to J. Aycock, "Practical Earley Parsing
and the SPARK Toolkit", Ph.D. thesis, University of Victoria,
2001, and J. Aycock and R. N. Horspool, "Practical Earley
Parsing", unpublished paper, 2001.
'''
def __init__(self, start):
self.rules = {}
@@ -90,7 +91,7 @@ class GenericParser:
changes = 1
while changes:
changes = 0
for k, v in self.edges.items():
for k, v in list(self.edges.items()):
if v is None:
state, sym = k
if self.states.has_key(state):
@@ -127,12 +128,12 @@ class GenericParser:
rules = doc.split()
index = []
for i in xrange(len(rules)):
for i in range(len(rules)):
if rules[i] == '::=':
index.append(i-1)
index.append(len(rules))
for i in xrange(len(index)-1):
for i in range(len(index)-1):
lhs = rules[index[i]]
rhs = rules[index[i]+2:index[i+1]]
rule = (lhs, tuple(rhs))
@@ -140,7 +141,7 @@ class GenericParser:
if _preprocess:
rule, fn = self.preprocess(rule, func)
if self.rules.has_key(lhs):
if lhs in self.rules:
self.rules[lhs].append(rule)
else:
self.rules[lhs] = [ rule ]
@@ -163,7 +164,7 @@ class GenericParser:
self.nullable = {}
tbd = []
for rulelist in self.rules.values():
for rulelist in list(self.rules.values()):
lhs = rulelist[0][0]
self.nullable[lhs] = 0
for rule in rulelist:
@@ -178,7 +179,7 @@ class GenericParser:
# grammars.
#
for sym in rhs:
if not self.rules.has_key(sym):
if sym not in self.rules:
break
else:
tbd.append(rule)
@@ -212,7 +213,7 @@ class GenericParser:
def makeNewRules(self):
worklist = []
for rulelist in self.rules.values():
for rulelist in list(self.rules.values()):
for rule in rulelist:
worklist.append((rule, 0, 1, rule))
@@ -221,7 +222,7 @@ class GenericParser:
n = len(rhs)
while i < n:
sym = rhs[i]
if not self.rules.has_key(sym) or \
if sym not in self.rules or \
not self.nullable[sym]:
candidate = 0
i = i + 1
@@ -238,7 +239,7 @@ class GenericParser:
if candidate:
lhs = self._NULLABLE+lhs
rule = (lhs, rhs)
if self.newrules.has_key(lhs):
if lhs in self.newrules:
self.newrules[lhs].append(rule)
else:
self.newrules[lhs] = [ rule ]
@@ -248,7 +249,7 @@ class GenericParser:
return None
def error(self, token):
print "Syntax error at or near `%s' token" % token
print("Syntax error at or near `%s' token" % token)
raise SystemExit
def parse(self, tokens):
@@ -274,7 +275,7 @@ class GenericParser:
else:
sets.append([])
self.makeSet(None, sets, len(tokens))
finalitem = (self.finalState(tokens), 0)
if finalitem not in sets[-2]:
if len(tokens) > 0:
@@ -292,7 +293,8 @@ class GenericParser:
#
return self._NULLABLE == sym[0:len(self._NULLABLE)]
def skip(self, (lhs, rhs), pos=0):
def skip(self, xxx_todo_changeme, pos=0):
(lhs, rhs) = xxx_todo_changeme
n = len(rhs)
while pos < n:
if not self.isnullable(rhs[pos]):
@@ -551,12 +553,12 @@ class GenericParser:
rule = self.ambiguity(self.newrules[nt])
else:
rule = self.newrules[nt][0]
#print rule
# print(rule)
rhs = rule[1]
attr = [None] * len(rhs)
for i in xrange(len(rhs)-1, -1, -1):
for i in range(len(rhs)-1, -1, -1):
attr[i] = self.deriveEpsilon(rhs[i])
return self.rule2func[self.new2old[rule]](attr)
@@ -570,12 +572,12 @@ class GenericParser:
rule = choices[0]
if len(choices) > 1:
rule = self.ambiguity(choices)
#print rule
# print(rule)
rhs = rule[1]
attr = [None] * len(rhs)
for i in xrange(len(rhs)-1, -1, -1):
for i in range(len(rhs)-1, -1, -1):
sym = rhs[i]
if not self.newrules.has_key(sym):
if sym != self._BOF:
@@ -599,24 +601,23 @@ class GenericParser:
# appears in >1 method. Also undefined results if rules
# causing the ambiguity appear in the same method.
#
sortlist = []
name2index = {}
for i in xrange(len(rules)):
for i in range(len(rules)):
lhs, rhs = rule = rules[i]
name = self.rule2name[self.new2old[rule]]
sortlist.append((len(rhs), name))
name2index[name] = i
sortlist.sort()
list = map(lambda (a,b): b, sortlist)
list = [a_b[1] for a_b in sortlist]
return rules[name2index[self.resolve(list)]]
def resolve(self, list):
#
# Resolve ambiguity in favor of the shortest RHS.
# Since we walk the tree from the top down, this
# should effectively resolve in favor of a "shift".
#
'''
Resolve ambiguity in favor of the shortest RHS.
Since we walk the tree from the top down, this
should effectively resolve in favor of a "shift".
'''
return list[0]
#
@@ -645,28 +646,29 @@ class GenericASTBuilder(GenericParser):
if isinstance(arg, self.AST):
children.append(arg)
else:
children.append(arg)
children.append(self.terminal(arg))
return self.nonterminal(lhs, children)
def terminal(self, token): return token
def nonterminal(self, type, args):
rv = self.AST(type)
rv[:len(args)] = args
return rv
#
# GenericASTTraversal is a Visitor pattern according to Design Patterns. For
# each node it attempts to invoke the method n_<node type>, falling
# back onto the default() method if the n_* can't be found. The preorder
# traversal also looks for an exit hook named n_<node type>_exit (no default
# routine is called if it's not found). To prematurely halt traversal
# of a subtree, call the prune() method -- this only makes sense for a
# preorder traversal. Node type is determined via the typestring() method.
#
class GenericASTTraversalPruningException:
pass
class GenericASTTraversal:
'''
GenericASTTraversal is a Visitor pattern according to Design Patterns. For
each node it attempts to invoke the method n_<node type>, falling
back onto the default() method if the n_* can't be found. The preorder
traversal also looks for an exit hook named n_<node type>_exit (no default
routine is called if it's not found). To prematurely halt traversal
of a subtree, call the prune() method -- this only makes sense for a
preorder traversal. Node type is determined via the typestring() method.
'''
def __init__(self, ast):
self.ast = ast