diff --git a/Grammar/Grammar b/Grammar/Grammar index 701a1ff05a0..2f07b5edd6b 100644 --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -79,7 +79,7 @@ try_stmt: ('try' ':' suite with_stmt: 'with' test [ with_var ] ':' suite with_var: 'as' expr # NB compile.c makes sure that the default except clause is last -except_clause: 'except' [test ['as' test]] +except_clause: 'except' [test ['as' NAME]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: diff --git a/Include/Python-ast.h b/Include/Python-ast.h index a159edbdca3..2d0576c936d 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -322,7 +322,7 @@ struct _comprehension { struct _excepthandler { expr_ty type; - expr_ty name; + identifier name; asdl_seq *body; int lineno; int col_offset; @@ -448,8 +448,8 @@ slice_ty ExtSlice(asdl_seq * dims, PyArena *arena); slice_ty Index(expr_ty value, PyArena *arena); comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena); -excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int - lineno, int col_offset, PyArena *arena); +excepthandler_ty excepthandler(expr_ty type, identifier name, asdl_seq * body, + int lineno, int col_offset, PyArena *arena); arguments_ty arguments(asdl_seq * args, identifier vararg, expr_ty varargannotation, asdl_seq * kwonlyargs, identifier kwarg, expr_ty kwargannotation, asdl_seq * defaults, diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index 55d2617923e..92eff6cc684 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -825,11 +825,33 @@ class CodeGenerator: self.emit('POP_TOP') self.emit('POP_TOP') if target: - self.visit(target) + cleanup_body = self.newBlock() + cleanup_final = self.newBlock() + target_name = target[1] + + self.storeName(target_name) + self.emit('POP_TOP') + self.emit('SETUP_FINALLY', cleanup_final) + self.nextBlock(cleanup_body) + self.setups.push((TRY_FINALLY, cleanup_body)) + self.visit(body) + self.emit('POP_BLOCK') + self.setups.pop() + self.emit('LOAD_CONST', None) + self.nextBlock(cleanup_final) + self.setups.push((END_FINALLY, cleanup_final)) + + + self.emit('LOAD_CONST', None) + self.storeName(target_name) + self._implicitNameOp('DELETE', target_name) + + self.emit('END_FINALLY') + self.setups.pop() else: self.emit('POP_TOP') - self.emit('POP_TOP') - self.visit(body) + self.emit('POP_TOP') + self.visit(body) self.emit('JUMP_FORWARD', end) if expr: self.nextBlock(next) diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py index 4a8e623f06d..e111b61671e 100644 --- a/Lib/compiler/transformer.py +++ b/Lib/compiler/transformer.py @@ -988,16 +988,16 @@ class Transformer: for i in range(3, len(nodelist), 3): node = nodelist[i] if node[0] == symbol.except_clause: - # except_clause: 'except' [expr [',' expr]] */ + # except_clause: 'except' [expr ['as' NAME]] */ if len(node) > 2: - expr1 = self.com_node(node[2]) + expr = self.com_node(node[2]) if len(node) > 4: - expr2 = self.com_assign(node[4], OP_ASSIGN) + expr_name = node[4] else: - expr2 = None + expr_name = None else: - expr1 = expr2 = None - clauses.append((expr1, expr2, self.com_node(nodelist[i+2]))) + expr = expr_name = None + clauses.append((expr, expr_name, self.com_node(nodelist[i+2]))) if node[0] == token.NAME: if node[1] == 'else': diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 2c3fa9454f6..eb5a14e5b04 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -97,7 +97,7 @@ module Python version "$Revision$" -- TODO(jhylton): Figure out if there is a better way to handle -- lineno and col_offset fields, particularly when -- ast is exposed to Python. - excepthandler = (expr? type, expr? name, stmt* body, int lineno, + excepthandler = (expr? type, identifier? name, stmt* body, int lineno, int col_offset) arguments = (arg* args, identifier? vararg, expr? varargannotation, diff --git a/Python/Python-ast.c b/Python/Python-ast.c index a210c7f20f2..e1a5bcef8b2 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1836,7 +1836,7 @@ comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena) } excepthandler_ty -excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int +excepthandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int col_offset, PyArena *arena) { excepthandler_ty p; @@ -2928,7 +2928,7 @@ ast2obj_excepthandler(void* _o) if (PyObject_SetAttrString(result, "type", value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(o->name); + value = ast2obj_identifier(o->name); if (!value) goto failed; if (PyObject_SetAttrString(result, "name", value) == -1) goto failed; diff --git a/Python/ast.c b/Python/ast.c index 5ccd6f530df..41fb50e410a 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2899,11 +2899,9 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body) else if (NCH(exc) == 4) { asdl_seq *suite_seq; expr_ty expression; - expr_ty e = ast_for_expr(c, CHILD(exc, 3)); + identifier e = NEW_IDENTIFIER(CHILD(exc, 3)); if (!e) return NULL; - if (!set_context(e, Store, CHILD(exc, 3))) - return NULL; expression = ast_for_expr(c, CHILD(exc, 1)); if (!expression) return NULL; diff --git a/Python/compile.c b/Python/compile.c index 481cc858861..e3bdaf5a1e9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1956,16 +1956,13 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); if (handler->name) { basicblock *cleanup_end, *cleanup_body; - expr_context_ty orig_ctx; - - assert(handler->name->kind == Name_kind); cleanup_end = compiler_new_block(c); cleanup_body = compiler_new_block(c); if(!(cleanup_end || cleanup_body)) return 0; - VISIT(c, expr, handler->name); + compiler_nameop(c, handler->name, Store); ADDOP(c, POP_TOP); /* @@ -1998,14 +1995,10 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* name = None */ ADDOP_O(c, LOAD_CONST, Py_None, consts); - orig_ctx = handler->name->v.Name.ctx; - handler->name->v.Name.ctx = Store; - VISIT(c, expr, handler->name); + compiler_nameop(c, handler->name, Store); - /* del name */ - handler->name->v.Name.ctx = Del; - VISIT(c, expr, handler->name); - handler->name->v.Name.ctx = orig_ctx; + /* del name */ + compiler_nameop(c, handler->name, Del); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, cleanup_end); diff --git a/Python/graminit.c b/Python/graminit.c index 3f0224045e6..0c4bfb5739b 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1053,7 +1053,7 @@ static arc arcs_46_2[2] = { {0, 2}, }; static arc arcs_46_3[1] = { - {22, 4}, + {19, 4}, }; static arc arcs_46_4[1] = { {0, 4}, diff --git a/Python/symtable.c b/Python/symtable.c index 708e18cafd2..d275cb90343 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1335,7 +1335,8 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) if (eh->type) VISIT(st, expr, eh->type); if (eh->name) - VISIT(st, expr, eh->name); + if (!symtable_add_def(st, eh->name, DEF_LOCAL)) + return 0; VISIT_SEQ(st, stmt, eh->body); return 1; }