You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
@@ -159,6 +159,17 @@ class Python2Parser(PythonParser):
|
||||
except_handler ::= jmp_abs COME_FROM except_stmts
|
||||
END_FINALLY
|
||||
|
||||
# except_handler_else is intended to be used only in a
|
||||
# try_else. The disambiguation comes from reduction rule
|
||||
# checking where we make sure that the JUMP_FORWARD mismatches
|
||||
# the JUMP_FORWARD before the END_FINALLY
|
||||
except_handler_else ::= JUMP_FORWARD COME_FROM except_stmts
|
||||
END_FINALLY come_froms
|
||||
|
||||
except_handler_else ::= jmp_abs COME_FROM except_stmts
|
||||
END_FINALLY
|
||||
|
||||
|
||||
except_stmts ::= except_stmt+
|
||||
|
||||
except_stmt ::= except_cond1 except_suite
|
||||
@@ -635,6 +646,8 @@ class Python2Parser(PythonParser):
|
||||
self.addRule(rule, nop_func)
|
||||
pass
|
||||
|
||||
self.check_reduce["except_handler"] = "tokens"
|
||||
self.check_reduce["except_handler_else"] = "tokens"
|
||||
self.check_reduce["raise_stmt1"] = "tokens"
|
||||
self.check_reduce["assert_expr_and"] = "AST"
|
||||
self.check_reduce["tryelsestmt"] = "AST"
|
||||
@@ -666,6 +679,31 @@ class Python2Parser(PythonParser):
|
||||
jmp_false = ast[1]
|
||||
jump_target = jmp_false[0].attr
|
||||
return jump_target > tokens[last].off2int()
|
||||
elif lhs in ("except_handler, except_handler_else"):
|
||||
|
||||
# FIXME: expand this to other 2.x version
|
||||
if self.version != 2.7: return False
|
||||
|
||||
if tokens[first] in ("JUMP_FORWARD", "JUMP_ABSOLUTE"):
|
||||
first_jump_target = tokens[first].pattr
|
||||
last = min(last, len(tokens)-1)
|
||||
for i in range(last, first, -1):
|
||||
if tokens[i] == "END_FINALLY":
|
||||
i -= 1
|
||||
second_jump = tokens[i]
|
||||
if second_jump in ("JUMP_FORWARD", "JUMP_ABSOLUTE"):
|
||||
second_jump_target = second_jump.pattr
|
||||
equal_target = second_jump_target == first_jump_target
|
||||
if equal_target:
|
||||
return lhs != "except_handler"
|
||||
else:
|
||||
return lhs != "except_handler_else"
|
||||
pass
|
||||
else:
|
||||
return False
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
elif rule == ("ifstmt", ("testexpr", "_ifstmts_jump")):
|
||||
for i in range(last-1, last-4, -1):
|
||||
t = tokens[i]
|
||||
|
@@ -60,13 +60,13 @@ class Python27Parser(Python2Parser):
|
||||
COME_FROM_FINALLY suite_stmts_opt END_FINALLY
|
||||
|
||||
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suite COME_FROM
|
||||
except_handler_else else_suite COME_FROM
|
||||
|
||||
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suitel JUMP_BACK COME_FROM
|
||||
except_handler_else else_suitel JUMP_BACK COME_FROM
|
||||
|
||||
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suitel
|
||||
except_handler_else else_suitel
|
||||
|
||||
except_stmt ::= except_cond2 except_suite
|
||||
|
||||
@@ -216,6 +216,10 @@ class Python27Parser(Python2Parser):
|
||||
super(Python27Parser, self).customize_grammar_rules(tokens, customize)
|
||||
self.check_reduce["and"] = "AST"
|
||||
self.check_reduce["conditional"] = "AST"
|
||||
|
||||
self.check_reduce["except_handler"] = "tokens"
|
||||
self.check_reduce["except_handler_else"] = "tokens"
|
||||
|
||||
# self.check_reduce["or"] = "AST"
|
||||
self.check_reduce["raise_stmt1"] = "AST"
|
||||
self.check_reduce["iflaststmtl"] = "AST"
|
||||
|
@@ -18,6 +18,7 @@ All the crazy things we have to do to handle Python functions in Python before 3
|
||||
The saga of changes continues in 3.0 and above and in other files.
|
||||
"""
|
||||
from xdis.code import iscode, code_has_star_arg, code_has_star_star_arg
|
||||
from xdis.util import CO_GENERATOR
|
||||
from uncompyle6.scanner import Code
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
from uncompyle6 import PYTHON3
|
||||
@@ -178,7 +179,6 @@ def make_function2(self, node, is_lambda, nested=1, code_node=None):
|
||||
# docstring exists, dump it
|
||||
print_docstring(self, indent, code.co_consts[0])
|
||||
|
||||
code._tokens = None # save memory
|
||||
if not is_lambda:
|
||||
assert ast == "stmts"
|
||||
|
||||
@@ -199,5 +199,6 @@ def make_function2(self, node, is_lambda, nested=1, code_node=None):
|
||||
self.gen_source(
|
||||
ast, code.co_name, code._customize, is_lambda=is_lambda, returnNone=rn
|
||||
)
|
||||
code._tokens = None
|
||||
|
||||
code._tokens = None # save memory
|
||||
code._customize = None # save memory
|
||||
|
@@ -17,6 +17,7 @@ All the crazy things we have to do to handle Python functions in 3.0-3.5 or so.
|
||||
The saga of changes before and after is in other files.
|
||||
"""
|
||||
from xdis.code import iscode, code_has_star_arg, code_has_star_star_arg
|
||||
from xdis.util import CO_GENERATOR
|
||||
from uncompyle6.scanner import Code
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
from uncompyle6.semantics.parser_error import ParserError
|
||||
@@ -485,9 +486,8 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount])
|
||||
|
||||
# defaults are for last n parameters when not in a lambda, thus reverse
|
||||
if not is_lambda:
|
||||
paramnames.reverse()
|
||||
defparams.reverse()
|
||||
paramnames.reverse()
|
||||
defparams.reverse()
|
||||
|
||||
try:
|
||||
ast = self.build_ast(scanner_code._tokens,
|
||||
@@ -645,7 +645,6 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
# docstring exists, dump it
|
||||
print_docstring(self, self.indent, code.co_consts[0])
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
assert ast == "stmts"
|
||||
|
||||
all_globals = find_all_globals(ast, set())
|
||||
@@ -665,5 +664,21 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None):
|
||||
self.gen_source(
|
||||
ast, code.co_name, scanner_code._customize, is_lambda=is_lambda, returnNone=rn
|
||||
)
|
||||
scanner_code._tokens = None
|
||||
|
||||
# In obscure cases, a function may be a generator but the "yield"
|
||||
# was optimized away. Here, we need to put in unreachable code to
|
||||
# add in "yield" just so that the compiler will mark
|
||||
# the GENERATOR bit of the function. See for example
|
||||
# Python 3.x's test_generator.py test program.
|
||||
if code.co_flags & CO_GENERATOR:
|
||||
need_bogus_yield = True
|
||||
for token in scanner_code._tokens:
|
||||
if token in ("YIELD_VALUE", "YIELD_FROM"):
|
||||
need_bogus_yield = False
|
||||
break
|
||||
pass
|
||||
if need_bogus_yield:
|
||||
self.template_engine(("%|if False:\n%+%|yield None%-",), node)
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._customize = None # save memory
|
||||
|
@@ -17,6 +17,7 @@ All the crazy things we have to do to handle Python functions in 3.6 and above.
|
||||
The saga of changes before 3.6 is in other files.
|
||||
"""
|
||||
from xdis.code import iscode, code_has_star_arg, code_has_star_star_arg
|
||||
from xdis.util import CO_GENERATOR, CO_ASYNC_GENERATOR
|
||||
from uncompyle6.scanner import Code
|
||||
from uncompyle6.parsers.treenode import SyntaxTree
|
||||
from uncompyle6.semantics.parser_error import ParserError
|
||||
@@ -197,10 +198,8 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
paramnames = list(scanner_code.co_varnames[:argc])
|
||||
kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount])
|
||||
|
||||
# defaults are for last n parameters when not in a lambda, thus reverse
|
||||
if not is_lambda:
|
||||
paramnames.reverse()
|
||||
defparams.reverse()
|
||||
paramnames.reverse()
|
||||
defparams.reverse()
|
||||
|
||||
try:
|
||||
ast = self.build_ast(
|
||||
@@ -372,7 +371,6 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
# docstring exists, dump it
|
||||
self.println(self.traverse(node[-2]))
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
assert ast == "stmts"
|
||||
|
||||
all_globals = find_all_globals(ast, set())
|
||||
@@ -393,5 +391,20 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
ast, code.co_name, scanner_code._customize, is_lambda=is_lambda, returnNone=rn
|
||||
)
|
||||
|
||||
scanner_code._tokens = None
|
||||
# In obscure cases, a function may be a generator but the "yield"
|
||||
# was optimized away. Here, we need to put in unreachable code to
|
||||
# add in "yield" just so that the compiler will mark
|
||||
# the GENERATOR bit of the function. See for example
|
||||
# Python 3.x's test_generator.py test program.
|
||||
if code.co_flags & (CO_GENERATOR | CO_ASYNC_GENERATOR):
|
||||
need_bogus_yield = True
|
||||
for token in scanner_code._tokens:
|
||||
if token == "YIELD_VALUE":
|
||||
need_bogus_yield = False
|
||||
break
|
||||
pass
|
||||
if need_bogus_yield:
|
||||
self.template_engine(("%|if False:\n%+%|yield None%-",), node)
|
||||
|
||||
scanner_code._tokens = None # save memory
|
||||
scanner_code._customize = None # save memory
|
||||
|
Reference in New Issue
Block a user