try/else on 2.6 fixup

This commit is contained in:
rocky
2018-01-07 21:24:35 -05:00
parent 7db8001d54
commit fbda3ca695
10 changed files with 59 additions and 19 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,17 @@
# From 2.4 test_binop.py bug is missing 'else:' in 2nd try.
def test_constructor():
for bad in "0", 0.0, 0j, (), [], {}, None:
try:
raise TypeError(bad)
except TypeError:
pass
else:
assert False, "%r didn't raise TypeError" % bad
try:
raise TypeError(bad)
except TypeError:
pass
else:
assert False, "%r didn't raise TypeError" % bad
test_constructor()

View File

@@ -0,0 +1,18 @@
# From Python 2.4. test_cgi.py
# Bug was in putting try block inside the ifelse statement.
# Note: this is a self testing program - will assert on failure.
def do_test(method):
if method == "GET":
rc = 0
elif method == "POST":
rc = 1
else:
raise ValueError, "unknown method: %s" % method
try:
rc = 2
except ZeroDivisionError:
rc = 3
return rc
assert 2 == do_test("GET")

View File

@@ -47,27 +47,19 @@ case $PYVERSION in
[test_sax.py]=1 # Control flow?
[test_trace.py]=1 # Line numbers are expected to be different
[test_types.py]=1 # Control flow?
[test_zipfile64.py]=1 # Runs ok but takes 204 seconds
nn [test_zipfile64.py]=1 # Runs ok but takes 204 seconds
)
;;
2.6)
SKIP_TESTS=(
[test_binop.py]=1 # need to fix tryelse
[test_cmath.py]=1 # Control flow?
[test_codecs.py]=1 # need to fix tryelse
[test_coercion.py]=1 # Control flow?
[test_cookielib.py]=1 # Control flow?
[test_decorators.py]=1 # Syntax Error - look at
[test_enumerate.py]=1 # Control flow?
[test_file.py]=1 # Control flow?
[test_frozen.py]=1 # Control flow?
[test_ftplib.py]=1 # Control flow?
[test_funcattrs.py]=1 # Control flow?
[test_grp.py]=1 # Long test - might work Control flow?
[test_imp.py]=1
[test_int.py]=1
[test_long.py]=1
[test_pty.py]=1
[test_pwd.py]=1 # Long test - might work? Control flow?
[test_queue.py]=1 # Control flow?
[test_re.py]=1 # Probably Control flow?

View File

@@ -69,7 +69,6 @@ class Python24Parser(Python25Parser):
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
if self.version == 2.4:
self.check_reduce['nop_stmt'] = 'tokens'
self.check_reduce['try_except'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python24Parser,

View File

@@ -19,9 +19,6 @@ class Python25Parser(Python26Parser):
return_if_stmt ::= ret_expr RETURN_END_IF JUMP_BACK
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
# Python 2.6 uses ROT_TWO instead of the STORE_xxx
# withas is allowed as a "from future" in 2.5
# 2.6 and 2.7 do something slightly different
@@ -39,8 +36,6 @@ class Python25Parser(Python26Parser):
# loop. FIXME: should "come_froms" below be a single COME_FROM?
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suite come_froms
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suitel
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
# withas is allowed as a "from future" in 2.5
@@ -59,9 +54,6 @@ class Python25Parser(Python26Parser):
def customize_grammar_rules(self, tokens, customize):
# Remove grammar rules inherited from Python 2.6 or Python 2
self.remove_rules("""
# No jump to jumps in 2.4 so we have a single "COME_FROM", not "come_froms"
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY

View File

@@ -40,6 +40,8 @@ class Python26Parser(Python2Parser):
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suite come_froms
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
except_handler else_suitel
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM POP_TOP
@@ -155,10 +157,12 @@ class Python26Parser(Python2Parser):
ifstmt ::= testexpr_then _ifstmts_jump
# Semantic actions want the else to be at position 3
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
ifelsestmt ::= testexpr_then c_stmts_opt jf_cf_pop else_suite come_froms
ifelsestmt ::= testexpr_then c_stmts_opt filler else_suitel come_froms POP_TOP
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
# Semantic actions want else_suitel to be at index 3
ifelsestmtl ::= testexpr_then c_stmts_opt jb_cf_pop else_suitel
ifelsestmtc ::= testexpr_then c_stmts_opt ja_cf_pop else_suitec
@@ -307,6 +311,7 @@ class Python26Parser(Python2Parser):
super(Python26Parser, self).customize_grammar_rules(tokens, customize)
self.check_reduce['and'] = 'AST'
self.check_reduce['list_for'] = 'AST'
self.check_reduce['try_except'] = 'tokens'
def reduce_is_invalid(self, rule, ast, tokens, first, last):
invalid = super(Python26Parser,
@@ -333,6 +338,23 @@ class Python26Parser(Python2Parser):
# The JUMP_ABSOLUTE has to be to the last POP_TOP or this is invalid
ja_attr = ast[4].attr
return tokens[last].offset != ja_attr
elif rule[0] == 'try_except':
# We need to distingush try_except from try_except_else and we do that
# by checking the jump before the END_FINALLY
# If we have:
# insn
# POP_TOP
# END_FINALLY
# COME_FROM
# then insn has to be either a JUMP_FORWARD or a RETURN_VALUE
if last == len(tokens):
last -= 1
if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM':
last -= 1
return (tokens[last] == 'COME_FROM'
and tokens[last-1] == 'END_FINALLY'
and tokens[last-2] == 'POP_TOP'
and tokens[last-3].kind not in frozenset(('JUMP_FORWARD', 'RETURN_VALUE')))
return False
class Python26ParserSingle(Python2Parser, PythonParserSingle):
pass