Commit 43af12b0 authored by Benjamin Peterson's avatar Benjamin Peterson

unify TryExcept and TryFinally (closes #12199)

parent f7d08e85
...@@ -66,10 +66,9 @@ struct _mod { ...@@ -66,10 +66,9 @@ struct _mod {
enum _stmt_kind {FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3, enum _stmt_kind {FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3,
Delete_kind=4, Assign_kind=5, AugAssign_kind=6, For_kind=7, Delete_kind=4, Assign_kind=5, AugAssign_kind=6, For_kind=7,
While_kind=8, If_kind=9, With_kind=10, Raise_kind=11, While_kind=8, If_kind=9, With_kind=10, Raise_kind=11,
TryExcept_kind=12, TryFinally_kind=13, Assert_kind=14, Try_kind=12, Assert_kind=13, Import_kind=14,
Import_kind=15, ImportFrom_kind=16, Global_kind=17, ImportFrom_kind=15, Global_kind=16, Nonlocal_kind=17,
Nonlocal_kind=18, Expr_kind=19, Pass_kind=20, Break_kind=21, Expr_kind=18, Pass_kind=19, Break_kind=20, Continue_kind=21};
Continue_kind=22};
struct _stmt { struct _stmt {
enum _stmt_kind kind; enum _stmt_kind kind;
union { union {
...@@ -143,12 +142,8 @@ struct _stmt { ...@@ -143,12 +142,8 @@ struct _stmt {
asdl_seq *body; asdl_seq *body;
asdl_seq *handlers; asdl_seq *handlers;
asdl_seq *orelse; asdl_seq *orelse;
} TryExcept;
struct {
asdl_seq *body;
asdl_seq *finalbody; asdl_seq *finalbody;
} TryFinally; } Try;
struct { struct {
expr_ty test; expr_ty test;
...@@ -433,12 +428,10 @@ stmt_ty _Py_With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, ...@@ -433,12 +428,10 @@ stmt_ty _Py_With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset,
#define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4) #define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4)
stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset,
PyArena *arena); PyArena *arena);
#define TryExcept(a0, a1, a2, a3, a4, a5) _Py_TryExcept(a0, a1, a2, a3, a4, a5) #define Try(a0, a1, a2, a3, a4, a5, a6) _Py_Try(a0, a1, a2, a3, a4, a5, a6)
stmt_ty _Py_TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, stmt_ty _Py_Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse,
int lineno, int col_offset, PyArena *arena); asdl_seq * finalbody, int lineno, int col_offset, PyArena
#define TryFinally(a0, a1, a2, a3, a4) _Py_TryFinally(a0, a1, a2, a3, a4) *arena);
stmt_ty _Py_TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, int
col_offset, PyArena *arena);
#define Assert(a0, a1, a2, a3, a4) _Py_Assert(a0, a1, a2, a3, a4) #define Assert(a0, a1, a2, a3, a4) _Py_Assert(a0, a1, a2, a3, a4)
stmt_ty _Py_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, stmt_ty _Py_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset,
PyArena *arena); PyArena *arena);
......
...@@ -347,8 +347,8 @@ exec_results = [ ...@@ -347,8 +347,8 @@ exec_results = [
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]),
('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]), ('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]),
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]), ('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]),
('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [])]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]),
('Module', [('TryFinally', (1, 0), [('Pass', (2, 2))], [('Pass', (4, 2))])]), ('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
('Module', [('Import', (1, 0), [('alias', 'sys', None)])]), ('Module', [('Import', (1, 0), [('alias', 'sys', None)])]),
('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]), ('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]),
......
...@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1? ...@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #12199: The TryExcept and TryFinally and AST nodes have been unified
into a Try node.
- Issue #9670: Increase the default stack size for secondary threads on - Issue #9670: Increase the default stack size for secondary threads on
Mac OS X and FreeBSD to reduce the chances of a crash instead of a Mac OS X and FreeBSD to reduce the chances of a crash instead of a
"maximum recursion depth" RuntimeError exception. "maximum recursion depth" RuntimeError exception.
......
...@@ -31,8 +31,7 @@ module Python ...@@ -31,8 +31,7 @@ module Python
| With(withitem* items, stmt* body) | With(withitem* items, stmt* body)
| Raise(expr? exc, expr? cause) | Raise(expr? exc, expr? cause)
| TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| TryFinally(stmt* body, stmt* finalbody)
| Assert(expr test, expr? msg) | Assert(expr test, expr? msg)
| Import(alias* names) | Import(alias* names)
......
This diff is collapsed.
...@@ -2893,7 +2893,7 @@ ast_for_try_stmt(struct compiling *c, const node *n) ...@@ -2893,7 +2893,7 @@ ast_for_try_stmt(struct compiling *c, const node *n)
{ {
const int nch = NCH(n); const int nch = NCH(n);
int n_except = (nch - 3)/3; int n_except = (nch - 3)/3;
asdl_seq *body, *orelse = NULL, *finally = NULL; asdl_seq *body, *handlers = NULL, *orelse = NULL, *finally = NULL;
REQ(n, try_stmt); REQ(n, try_stmt);
...@@ -2934,9 +2934,8 @@ ast_for_try_stmt(struct compiling *c, const node *n) ...@@ -2934,9 +2934,8 @@ ast_for_try_stmt(struct compiling *c, const node *n)
if (n_except > 0) { if (n_except > 0) {
int i; int i;
stmt_ty except_st;
/* process except statements to create a try ... except */ /* process except statements to create a try ... except */
asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena); handlers = asdl_seq_new(n_except, c->c_arena);
if (handlers == NULL) if (handlers == NULL)
return NULL; return NULL;
...@@ -2947,23 +2946,10 @@ ast_for_try_stmt(struct compiling *c, const node *n) ...@@ -2947,23 +2946,10 @@ ast_for_try_stmt(struct compiling *c, const node *n)
return NULL; return NULL;
asdl_seq_SET(handlers, i, e); asdl_seq_SET(handlers, i, e);
} }
except_st = TryExcept(body, handlers, orelse, LINENO(n),
n->n_col_offset, 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 || asdl_seq_LEN(handlers));
assert(finally != NULL); return Try(body, handlers, orelse, finally, LINENO(n), n->n_col_offset, c->c_arena);
return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena);
} }
/* with_item: test ['as' expr] */ /* with_item: test ['as' expr] */
......
...@@ -185,6 +185,7 @@ static int compiler_call_helper(struct compiler *c, int n, ...@@ -185,6 +185,7 @@ static int compiler_call_helper(struct compiler *c, int n,
asdl_seq *keywords, asdl_seq *keywords,
expr_ty starargs, expr_ty starargs,
expr_ty kwargs); expr_ty kwargs);
static int compiler_try_except(struct compiler *, stmt_ty);
static PyCodeObject *assemble(struct compiler *, int addNone); static PyCodeObject *assemble(struct compiler *, int addNone);
static PyObject *__doc__; static PyObject *__doc__;
...@@ -1898,7 +1899,13 @@ compiler_try_finally(struct compiler *c, stmt_ty s) ...@@ -1898,7 +1899,13 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
compiler_use_next_block(c, body); compiler_use_next_block(c, body);
if (!compiler_push_fblock(c, FINALLY_TRY, body)) if (!compiler_push_fblock(c, FINALLY_TRY, body))
return 0; return 0;
VISIT_SEQ(c, stmt, s->v.TryFinally.body); if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) {
if (!compiler_try_except(c, s))
return 0;
}
else {
VISIT_SEQ(c, stmt, s->v.Try.body);
}
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
compiler_pop_fblock(c, FINALLY_TRY, body); compiler_pop_fblock(c, FINALLY_TRY, body);
...@@ -1906,7 +1913,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) ...@@ -1906,7 +1913,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
if (!compiler_push_fblock(c, FINALLY_END, end)) if (!compiler_push_fblock(c, FINALLY_END, end))
return 0; return 0;
VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); VISIT_SEQ(c, stmt, s->v.Try.finalbody);
ADDOP(c, END_FINALLY); ADDOP(c, END_FINALLY);
compiler_pop_fblock(c, FINALLY_END, end); compiler_pop_fblock(c, FINALLY_END, end);
...@@ -1960,15 +1967,15 @@ compiler_try_except(struct compiler *c, stmt_ty s) ...@@ -1960,15 +1967,15 @@ compiler_try_except(struct compiler *c, stmt_ty s)
compiler_use_next_block(c, body); compiler_use_next_block(c, body);
if (!compiler_push_fblock(c, EXCEPT, body)) if (!compiler_push_fblock(c, EXCEPT, body))
return 0; return 0;
VISIT_SEQ(c, stmt, s->v.TryExcept.body); VISIT_SEQ(c, stmt, s->v.Try.body);
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
compiler_pop_fblock(c, EXCEPT, body); compiler_pop_fblock(c, EXCEPT, body);
ADDOP_JREL(c, JUMP_FORWARD, orelse); ADDOP_JREL(c, JUMP_FORWARD, orelse);
n = asdl_seq_LEN(s->v.TryExcept.handlers); n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
s->v.TryExcept.handlers, i); s->v.Try.handlers, i);
if (!handler->v.ExceptHandler.type && i < n-1) if (!handler->v.ExceptHandler.type && i < n-1)
return compiler_error(c, "default 'except:' must be last"); return compiler_error(c, "default 'except:' must be last");
c->u->u_lineno_set = 0; c->u->u_lineno_set = 0;
...@@ -2055,11 +2062,20 @@ compiler_try_except(struct compiler *c, stmt_ty s) ...@@ -2055,11 +2062,20 @@ compiler_try_except(struct compiler *c, stmt_ty s)
} }
ADDOP(c, END_FINALLY); ADDOP(c, END_FINALLY);
compiler_use_next_block(c, orelse); compiler_use_next_block(c, orelse);
VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); VISIT_SEQ(c, stmt, s->v.Try.orelse);
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
return 1; return 1;
} }
static int
compiler_try(struct compiler *c, stmt_ty s) {
if (s->v.Try.finalbody && asdl_seq_LEN(s->v.Try.finalbody))
return compiler_try_finally(c, s);
else
return compiler_try_except(c, s);
}
static int static int
compiler_import_as(struct compiler *c, identifier name, identifier asname) compiler_import_as(struct compiler *c, identifier name, identifier asname)
{ {
...@@ -2307,10 +2323,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) ...@@ -2307,10 +2323,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
} }
ADDOP_I(c, RAISE_VARARGS, n); ADDOP_I(c, RAISE_VARARGS, n);
break; break;
case TryExcept_kind: case Try_kind:
return compiler_try_except(c, s); return compiler_try(c, s);
case TryFinally_kind:
return compiler_try_finally(c, s);
case Assert_kind: case Assert_kind:
return compiler_assert(c, s); return compiler_assert(c, s);
case Import_kind: case Import_kind:
......
...@@ -1211,14 +1211,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) ...@@ -1211,14 +1211,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
} }
} }
break; break;
case TryExcept_kind: case Try_kind:
VISIT_SEQ(st, stmt, s->v.TryExcept.body); VISIT_SEQ(st, stmt, s->v.Try.body);
VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); VISIT_SEQ(st, stmt, s->v.Try.orelse);
VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); VISIT_SEQ(st, excepthandler, s->v.Try.handlers);
break; VISIT_SEQ(st, stmt, s->v.Try.finalbody);
case TryFinally_kind:
VISIT_SEQ(st, stmt, s->v.TryFinally.body);
VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody);
break; break;
case Assert_kind: case Assert_kind:
VISIT(st, expr, s->v.Assert.test); VISIT(st, expr, s->v.Assert.test);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment