SF patch #1355913, PEP 341 - Unification of try/except and try/finally

Modified since ast-arenas was implemented.
This commit is contained in:
Neal Norwitz 2005-12-17 21:33:47 +00:00
parent adb69fcdff
commit f599f424a2
5 changed files with 265 additions and 59 deletions

View File

@ -67,8 +67,7 @@ compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break try_stmt: 'try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)
['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
# NB compile.c makes sure that the default except clause is last # NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test [',' test]] except_clause: 'except' [test [',' test]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

View File

@ -0,0 +1,180 @@
from test.test_support import run_unittest
import unittest
class ExceptionTestCase(unittest.TestCase):
def test_try_except_else_finally(self):
hit_except = False
hit_else = False
hit_finally = False
try:
raise Exception, 'nyaa!'
except:
hit_except = True
else:
hit_else = True
finally:
hit_finally = True
self.assertTrue(hit_except)
self.assertTrue(hit_finally)
self.assertFalse(hit_else)
def test_try_except_else_finally_no_exception(self):
hit_except = False
hit_else = False
hit_finally = False
try:
pass
except:
hit_except = True
else:
hit_else = True
finally:
hit_finally = True
self.assertFalse(hit_except)
self.assertTrue(hit_finally)
self.assertTrue(hit_else)
def test_try_except_finally(self):
hit_except = False
hit_finally = False
try:
raise Exception, 'yarr!'
except:
hit_except = True
finally:
hit_finally = True
self.assertTrue(hit_except)
self.assertTrue(hit_finally)
def test_try_except_finally_no_exception(self):
hit_except = False
hit_finally = False
try:
pass
except:
hit_except = True
finally:
hit_finally = True
self.assertFalse(hit_except)
self.assertTrue(hit_finally)
def test_try_except(self):
hit_except = False
try:
raise Exception, 'ahoy!'
except:
hit_except = True
self.assertTrue(hit_except)
def test_try_except_no_exception(self):
hit_except = False
try:
pass
except:
hit_except = True
self.assertFalse(hit_except)
def test_try_except_else(self):
hit_except = False
hit_else = False
try:
raise Exception, 'foo!'
except:
hit_except = True
else:
hit_else = True
self.assertFalse(hit_else)
self.assertTrue(hit_except)
def test_try_except_else_no_exception(self):
hit_except = False
hit_else = False
try:
pass
except:
hit_except = True
else:
hit_else = True
self.assertFalse(hit_except)
self.assertTrue(hit_else)
def test_try_finally_no_exception(self):
hit_finally = False
try:
pass
finally:
hit_finally = True
self.assertTrue(hit_finally)
def test_nested(self):
hit_finally = False
hit_inner_except = False
hit_inner_finally = False
try:
try:
raise Exception, 'inner exception'
except:
hit_inner_except = True
finally:
hit_inner_finally = True
finally:
hit_finally = True
self.assertTrue(hit_inner_except)
self.assertTrue(hit_inner_finally)
self.assertTrue(hit_finally)
def test_nested_else(self):
hit_else = False
hit_finally = False
hit_except = False
hit_inner_except = False
hit_inner_else = False
try:
try:
pass
except:
hit_inner_except = True
else:
hit_inner_else = True
raise Exception, 'outer exception'
except:
hit_except = True
else:
hit_else = True
finally:
hit_finally = True
self.assertFalse(hit_inner_except)
self.assertTrue(hit_inner_else)
self.assertFalse(hit_else)
self.assertTrue(hit_finally)
self.assertTrue(hit_except)
def test_main():
run_unittest(ExceptionTestCase)
if __name__ == '__main__':
test_main()

View File

@ -357,6 +357,7 @@ Chris Lawrence
Christopher Lee Christopher Lee
Inyeol Lee Inyeol Lee
John J. Lee John J. Lee
Thomas Lee
Luc Lefebvre Luc Lefebvre
Kip Lehman Kip Lehman
Joerg Lehmann Joerg Lehmann

View File

@ -2597,66 +2597,78 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body)
static stmt_ty static stmt_ty
ast_for_try_stmt(struct compiling *c, const node *n) ast_for_try_stmt(struct compiling *c, const node *n)
{ {
const int nch = NCH(n);
int n_except = (nch - 3)/3;
asdl_seq *body, *orelse = NULL, *finally = NULL;
REQ(n, try_stmt); REQ(n, try_stmt);
if (TYPE(CHILD(n, 3)) == NAME) {/* must be 'finally' */ body = ast_for_suite(c, CHILD(n, 2));
/* try_stmt: 'try' ':' suite 'finally' ':' suite) */ if (body == NULL)
asdl_seq *s1, *s2; return NULL;
s1 = ast_for_suite(c, CHILD(n, 2));
if (!s1)
return NULL;
s2 = ast_for_suite(c, CHILD(n, 5));
if (!s2) {
return NULL;
}
return TryFinally(s1, s2, LINENO(n), c->c_arena);
}
else if (TYPE(CHILD(n, 3)) == except_clause) {
/* try_stmt: ('try' ':' suite (except_clause ':' suite)+
['else' ':' suite]
*/
asdl_seq *suite_seq1, *suite_seq2;
asdl_seq *handlers;
int i, has_else = 0, n_except = NCH(n) - 3;
if (TYPE(CHILD(n, NCH(n) - 3)) == NAME) {
has_else = 1;
n_except -= 3;
}
n_except /= 3;
handlers = asdl_seq_new(n_except, c->c_arena);
if (!handlers)
return NULL;
for (i = 0; i < n_except; i++) {
excepthandler_ty e = ast_for_except_clause(c,
CHILD(n, 3 + i * 3),
CHILD(n, 5 + i * 3));
if (!e) {
return NULL;
}
asdl_seq_SET(handlers, i, e);
}
suite_seq1 = ast_for_suite(c, CHILD(n, 2)); if (TYPE(CHILD(n, nch - 3)) == NAME) {
if (!suite_seq1) { if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) {
return NULL; if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) {
} /* we can assume it's an "else",
if (has_else) { because nch >= 9 for try-else-finally and
suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1)); it would otherwise have a type of except_clause */
if (!suite_seq2) { orelse = ast_for_suite(c, CHILD(n, nch - 4));
return NULL; if (orelse == NULL)
} return NULL;
} n_except--;
else }
suite_seq2 = NULL;
return TryExcept(suite_seq1, handlers, suite_seq2, LINENO(n), finally = ast_for_suite(c, CHILD(n, nch - 1));
c->c_arena); if (finally == NULL)
return NULL;
n_except--;
}
else {
/* we can assume it's an "else",
otherwise it would have a type of except_clause */
orelse = ast_for_suite(c, CHILD(n, nch - 1));
if (orelse == NULL)
return NULL;
n_except--;
}
} }
else { else if (TYPE(CHILD(n, nch - 3)) != except_clause) {
ast_error(n, "malformed 'try' statement"); ast_error(n, "malformed 'try' statement");
return NULL; return NULL;
} }
if (n_except > 0) {
int i;
stmt_ty except_st;
/* process except statements to create a try ... except */
asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena);
if (handlers == NULL)
return NULL;
for (i = 0; i < n_except; i++) {
excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3),
CHILD(n, 5 + i * 3));
if (!e)
return NULL;
asdl_seq_SET(handlers, i, e);
}
except_st = TryExcept(body, handlers, orelse, LINENO(n), c->c_arena);
if (!finally)
return except_st;
/* if a 'finally' is present too, we nest the TryExcept within a
TryFinally to emulate try ... except ... finally */
body = asdl_seq_new(1, c->c_arena);
if (body == NULL)
return NULL;
asdl_seq_SET(body, 0, except_st);
}
/* must be a try ... finally (except clauses are in body, if any exist) */
assert(finally != NULL);
return TryFinally(body, finally, LINENO(n), c->c_arena);
} }
static stmt_ty static stmt_ty

View File

@ -841,15 +841,26 @@ static arc arcs_39_6[1] = {
static arc arcs_39_7[1] = { static arc arcs_39_7[1] = {
{22, 9}, {22, 9},
}; };
static arc arcs_39_8[3] = { static arc arcs_39_8[4] = {
{95, 4}, {95, 4},
{91, 5}, {91, 10},
{96, 5},
{0, 8}, {0, 8},
}; };
static arc arcs_39_9[1] = { static arc arcs_39_9[1] = {
{0, 9}, {0, 9},
}; };
static state states_39[10] = { static arc arcs_39_10[1] = {
{21, 11},
};
static arc arcs_39_11[1] = {
{22, 12},
};
static arc arcs_39_12[2] = {
{96, 5},
{0, 12},
};
static state states_39[13] = {
{1, arcs_39_0}, {1, arcs_39_0},
{1, arcs_39_1}, {1, arcs_39_1},
{1, arcs_39_2}, {1, arcs_39_2},
@ -858,8 +869,11 @@ static state states_39[10] = {
{1, arcs_39_5}, {1, arcs_39_5},
{1, arcs_39_6}, {1, arcs_39_6},
{1, arcs_39_7}, {1, arcs_39_7},
{3, arcs_39_8}, {4, arcs_39_8},
{1, arcs_39_9}, {1, arcs_39_9},
{1, arcs_39_10},
{1, arcs_39_11},
{2, arcs_39_12},
}; };
static arc arcs_40_0[1] = { static arc arcs_40_0[1] = {
{97, 1}, {97, 1},
@ -1754,7 +1768,7 @@ static dfa dfas[79] = {
"\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"},
{294, "for_stmt", 0, 10, states_38, {294, "for_stmt", 0, 10, states_38,
"\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
{295, "try_stmt", 0, 10, states_39, {295, "try_stmt", 0, 13, states_39,
"\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"},
{296, "except_clause", 0, 5, states_40, {296, "except_clause", 0, 5, states_40,
"\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"}, "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},