You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 16:59:52 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
BIN
test/bytecode_3.2/01_triple_compare.pyc
Normal file
BIN
test/bytecode_3.2/01_triple_compare.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.2/03_if_try_raise.pyc
Normal file
BIN
test/bytecode_3.2/03_if_try_raise.pyc
Normal file
Binary file not shown.
21
test/simple_source/bug32/03_if_try_raise.py
Normal file
21
test/simple_source/bug32/03_if_try_raise.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# From 3.2 distutils/core
|
||||||
|
# Ensure we handle funky trystmt
|
||||||
|
def setup (ok, dist, **attrs):
|
||||||
|
if ok:
|
||||||
|
try:
|
||||||
|
dist.run_commands()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise SystemExit("interrupted")
|
||||||
|
except IOError as exc:
|
||||||
|
error = exc
|
||||||
|
if dist:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise SystemExit(error)
|
||||||
|
except (RuntimeError) as msg:
|
||||||
|
if dist:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise SystemExit("error: " + str(msg))
|
||||||
|
|
||||||
|
return dist
|
@@ -477,7 +477,8 @@ class Python3Parser(PythonParser):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def custom_classfunc_rule(self, opname, token, customize,
|
def custom_classfunc_rule(self, opname, token, customize,
|
||||||
seen_LOAD_BUILD_CLASS):
|
seen_LOAD_BUILD_CLASS,
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM):
|
||||||
"""
|
"""
|
||||||
call_function ::= expr {expr}^n CALL_FUNCTION_n
|
call_function ::= expr {expr}^n CALL_FUNCTION_n
|
||||||
call_function ::= expr {expr}^n CALL_FUNCTION_VAR_n
|
call_function ::= expr {expr}^n CALL_FUNCTION_VAR_n
|
||||||
@@ -527,7 +528,7 @@ class Python3Parser(PythonParser):
|
|||||||
'expr ' * nak + token.kind)
|
'expr ' * nak + token.kind)
|
||||||
|
|
||||||
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
||||||
if self.version >= 3.5:
|
if self.version >= 3.5 and seen_GET_AWAITABLE_YIELD_FROM:
|
||||||
rule = ('async_call_function ::= expr ' +
|
rule = ('async_call_function ::= expr ' +
|
||||||
('pos_arg ' * args_pos) +
|
('pos_arg ' * args_pos) +
|
||||||
('kwarg ' * args_kw) +
|
('kwarg ' * args_kw) +
|
||||||
@@ -619,6 +620,7 @@ class Python3Parser(PythonParser):
|
|||||||
seen_LOAD_DICTCOMP = False
|
seen_LOAD_DICTCOMP = False
|
||||||
seen_LOAD_LISTCOMP = False
|
seen_LOAD_LISTCOMP = False
|
||||||
seen_LOAD_SETCOMP = False
|
seen_LOAD_SETCOMP = False
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM = False
|
||||||
|
|
||||||
# Loop over instructions adding custom grammar rules based on
|
# Loop over instructions adding custom grammar rules based on
|
||||||
# a specific instruction seen.
|
# a specific instruction seen.
|
||||||
@@ -633,9 +635,16 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
has_get_iter_call_function1 = False
|
has_get_iter_call_function1 = False
|
||||||
n = len(tokens)
|
n = len(tokens)
|
||||||
|
max_branches = 0
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
if token == 'GET_ITER' and i < n-2 and self.call_fn_name(tokens[i+1]) == 'CALL_FUNCTION_1':
|
if token == 'GET_ITER' and i < n-2 and self.call_fn_name(tokens[i+1]) == 'CALL_FUNCTION_1':
|
||||||
has_get_iter_call_function1 = True
|
has_get_iter_call_function1 = True
|
||||||
|
max_branches += 1
|
||||||
|
elif (token == 'GET_AWAITABLE' and i < n-3
|
||||||
|
and tokens[i+1] == 'LOAD_CONST' and tokens[i+2] == 'YIELD_FROM'):
|
||||||
|
max_branches += 1
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM = True
|
||||||
|
if max_branches > 2:
|
||||||
break
|
break
|
||||||
|
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
@@ -726,7 +735,9 @@ class Python3Parser(PythonParser):
|
|||||||
elif (opname in ('CALL_FUNCTION', 'CALL_FUNCTION_VAR',
|
elif (opname in ('CALL_FUNCTION', 'CALL_FUNCTION_VAR',
|
||||||
'CALL_FUNCTION_VAR_KW', 'CALL_FUNCTION_EX_KW')
|
'CALL_FUNCTION_VAR_KW', 'CALL_FUNCTION_EX_KW')
|
||||||
or opname.startswith('CALL_FUNCTION_KW')):
|
or opname.startswith('CALL_FUNCTION_KW')):
|
||||||
self.custom_classfunc_rule(opname, token, customize, seen_LOAD_BUILD_CLASS)
|
self.custom_classfunc_rule(opname, token, customize,
|
||||||
|
seen_LOAD_BUILD_CLASS,
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM)
|
||||||
elif opname_base == 'CALL_METHOD':
|
elif opname_base == 'CALL_METHOD':
|
||||||
# PyPy only - DRY with parse2
|
# PyPy only - DRY with parse2
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ class Python32Parser(Python3Parser):
|
|||||||
def p_32to35(self, args):
|
def p_32to35(self, args):
|
||||||
"""
|
"""
|
||||||
conditional ::= expr jmp_false expr jump_forward_else expr COME_FROM
|
conditional ::= expr jmp_false expr jump_forward_else expr COME_FROM
|
||||||
|
cmp_list2 ::= expr COMPARE_OP RETURN_VALUE
|
||||||
|
|
||||||
# Store locals is only in Python 3.0 to 3.3
|
# Store locals is only in Python 3.0 to 3.3
|
||||||
stmt ::= store_locals
|
stmt ::= store_locals
|
||||||
@@ -18,9 +19,22 @@ class Python32Parser(Python3Parser):
|
|||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP return_stmts COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP return_stmts COME_FROM_LOOP
|
||||||
|
|
||||||
|
# Python 3.5+ has jump optimization to remove the redundant
|
||||||
|
# jump_excepts. But in 3.3 we need them added
|
||||||
|
|
||||||
|
trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||||
|
try_middle
|
||||||
|
jump_excepts come_from_except_clauses
|
||||||
|
|
||||||
try_middle ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
|
try_middle ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
|
||||||
END_FINALLY
|
END_FINALLY
|
||||||
|
|
||||||
|
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||||
|
try_middle else_suite
|
||||||
|
jump_excepts come_from_except_clauses
|
||||||
|
|
||||||
|
jump_excepts ::= jump_except+
|
||||||
|
|
||||||
# Python 3.2+ has more loop optimization that removes
|
# Python 3.2+ has more loop optimization that removes
|
||||||
# JUMP_FORWARD in some cases, and hence we also don't
|
# JUMP_FORWARD in some cases, and hence we also don't
|
||||||
# see COME_FROM
|
# see COME_FROM
|
||||||
|
@@ -14,8 +14,6 @@ class Python33Parser(Python32Parser):
|
|||||||
expr ::= yield_from
|
expr ::= yield_from
|
||||||
yield_from ::= expr expr YIELD_FROM
|
yield_from ::= expr expr YIELD_FROM
|
||||||
|
|
||||||
cmp_list2 ::= expr COMPARE_OP RETURN_VALUE
|
|
||||||
|
|
||||||
# We do the grammar hackery below for semantics
|
# We do the grammar hackery below for semantics
|
||||||
# actions that want c_stmts_opt at index 1
|
# actions that want c_stmts_opt at index 1
|
||||||
|
|
||||||
@@ -25,20 +23,16 @@ class Python33Parser(Python32Parser):
|
|||||||
# Python 3.5+ has jump optimization to remove the redundant
|
# Python 3.5+ has jump optimization to remove the redundant
|
||||||
# jump_excepts. But in 3.3 we need them added
|
# jump_excepts. But in 3.3 we need them added
|
||||||
|
|
||||||
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
|
||||||
try_middle else_suite
|
|
||||||
jump_excepts come_from_except_clauses
|
|
||||||
|
|
||||||
trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||||
try_middle
|
try_middle
|
||||||
jump_excepts come_from_except_clauses
|
jump_excepts come_from_except_clauses
|
||||||
|
|
||||||
jump_excepts ::= jump_except+
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def add_custom_rules(self, tokens, customize):
|
def add_custom_rules(self, tokens, customize):
|
||||||
self.remove_rules("""
|
self.remove_rules("""
|
||||||
|
# 3.3+ adds POP_BLOCKS
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts JUMP_ABSOLUTE JUMP_BACK COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts JUMP_ABSOLUTE JUMP_BACK COME_FROM_LOOP
|
||||||
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP COME_FROM_LOOP
|
||||||
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP COME_FROM_LOOP
|
whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP COME_FROM_LOOP
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK
|
||||||
|
@@ -140,6 +140,10 @@ class Python35Parser(Python34Parser):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def add_custom_rules(self, tokens, customize):
|
def add_custom_rules(self, tokens, customize):
|
||||||
|
self.remove_rules("""
|
||||||
|
# FIXME: should this be in 3.3?
|
||||||
|
whileTruestmt ::= SETUP_LOOP return_stmts COME_FROM_LOOP
|
||||||
|
""")
|
||||||
super(Python35Parser, self).add_custom_rules(tokens, customize)
|
super(Python35Parser, self).add_custom_rules(tokens, customize)
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
opname = token.kind
|
opname = token.kind
|
||||||
|
@@ -97,7 +97,9 @@ class Python36Parser(Python35Parser):
|
|||||||
""" % (fstring_expr_or_str_n, fstring_expr_or_str_n, "fstring_expr_or_str " * v)
|
""" % (fstring_expr_or_str_n, fstring_expr_or_str_n, "fstring_expr_or_str " * v)
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
|
|
||||||
def custom_classfunc_rule(self, opname, token, customize, seen_LOAD_BUILD_CLASS):
|
def custom_classfunc_rule(self, opname, token, customize,
|
||||||
|
seen_LOAD_BUILD_CLASS,
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM):
|
||||||
if opname.startswith('CALL_FUNCTION_KW'):
|
if opname.startswith('CALL_FUNCTION_KW'):
|
||||||
values = 'expr ' * token.attr
|
values = 'expr ' * token.attr
|
||||||
rule = 'call_function ::= expr kwargs_only_36 {token.kind}'.format(**locals())
|
rule = 'call_function ::= expr kwargs_only_36 {token.kind}'.format(**locals())
|
||||||
@@ -106,7 +108,9 @@ class Python36Parser(Python35Parser):
|
|||||||
self.add_unique_rule(rule, token.kind, token.attr, customize)
|
self.add_unique_rule(rule, token.kind, token.attr, customize)
|
||||||
else:
|
else:
|
||||||
super(Python36Parser, self).custom_classfunc_rule(opname, token,
|
super(Python36Parser, self).custom_classfunc_rule(opname, token,
|
||||||
customize, seen_LOAD_BUILD_CLASS)
|
customize,
|
||||||
|
seen_LOAD_BUILD_CLASS,
|
||||||
|
seen_GET_AWAITABLE_YIELD_FROM)
|
||||||
|
|
||||||
|
|
||||||
class Python36ParserSingle(Python36Parser, PythonParserSingle):
|
class Python36ParserSingle(Python36Parser, PythonParserSingle):
|
||||||
|
Reference in New Issue
Block a user