summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2008-06-11 15:59:43 (GMT)
committerBenjamin Peterson <benjamin@python.org>2008-06-11 15:59:43 (GMT)
commiteec3d7137929611b98dd593cd2f122cd91b723b2 (patch)
tree42721419d4fe3f53961ecfd7c1dea3224188ae40 /Python/compile.c
parente8465f2b413174084fcc2dc4cd7a53122c62ce4b (diff)
downloadcpython-eec3d7137929611b98dd593cd2f122cd91b723b2.zip
cpython-eec3d7137929611b98dd593cd2f122cd91b723b2.tar.gz
cpython-eec3d7137929611b98dd593cd2f122cd91b723b2.tar.bz2
#3021: Antoine Pitrou's Lexical exception handlers
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/Python/compile.c b/Python/compile.c
index c8a4f85..6017b2c 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -760,6 +760,8 @@ opcode_stack_effect(int opcode, int oparg)
case POP_BLOCK:
return 0;
+ case POP_EXCEPT:
+ return 0; /* -3 except if bad bytecode */
case END_FINALLY:
return -1; /* or -2 or -3 if exception occurred */
@@ -818,7 +820,8 @@ opcode_stack_effect(int opcode, int oparg)
return 0;
case SETUP_EXCEPT:
case SETUP_FINALLY:
- return 3; /* actually pushed by an exception */
+ return 6; /* can push 3 values for the new exception
+ + 3 others for the previous exception state */
case LOAD_FAST:
return 1;
@@ -2031,6 +2034,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
/* second # body */
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
ADDOP(c, POP_BLOCK);
+ ADDOP(c, POP_EXCEPT);
compiler_pop_fblock(c, FINALLY_TRY, cleanup_body);
/* finally: */
@@ -2050,9 +2054,20 @@ compiler_try_except(struct compiler *c, stmt_ty s)
compiler_pop_fblock(c, FINALLY_END, cleanup_end);
}
else {
+ basicblock *cleanup_body;
+
+ cleanup_body = compiler_new_block(c);
+ if(!cleanup_body)
+ return 0;
+
+ ADDOP(c, POP_TOP);
ADDOP(c, POP_TOP);
- ADDOP(c, POP_TOP);
+ compiler_use_next_block(c, cleanup_body);
+ if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body))
+ return 0;
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
+ ADDOP(c, POP_EXCEPT);
+ compiler_pop_fblock(c, FINALLY_TRY, cleanup_body);
}
ADDOP_JREL(c, JUMP_FORWARD, end);
compiler_use_next_block(c, except);
@@ -3109,7 +3124,7 @@ compiler_with(struct compiler *c, stmt_ty s)
{
static identifier enter_attr, exit_attr;
basicblock *block, *finally;
- identifier tmpvalue = NULL;
+ identifier tmpvalue = NULL, tmpexit = NULL;
assert(s->kind == With_kind);
@@ -3144,6 +3159,10 @@ compiler_with(struct compiler *c, stmt_ty s)
return 0;
PyArena_AddPyObject(c->c_arena, tmpvalue);
}
+ tmpexit = compiler_new_tmpname(c);
+ if (tmpexit == NULL)
+ return 0;
+ PyArena_AddPyObject(c->c_arena, tmpexit);
/* Evaluate EXPR */
VISIT(c, expr, s->v.With.context_expr);
@@ -3151,7 +3170,8 @@ compiler_with(struct compiler *c, stmt_ty s)
/* Squirrel away context.__exit__ by stuffing it under context */
ADDOP(c, DUP_TOP);
ADDOP_O(c, LOAD_ATTR, exit_attr, names);
- ADDOP(c, ROT_TWO);
+ if (!compiler_nameop(c, tmpexit, Store))
+ return 0;
/* Call context.__enter__() */
ADDOP_O(c, LOAD_ATTR, enter_attr, names);
@@ -3198,6 +3218,9 @@ compiler_with(struct compiler *c, stmt_ty s)
/* Finally block starts; context.__exit__ is on the stack under
the exception or return information. Just issue our magic
opcode. */
+ if (!compiler_nameop(c, tmpexit, Load) ||
+ !compiler_nameop(c, tmpexit, Del))
+ return 0;
ADDOP(c, WITH_CLEANUP);
/* Finally block ends. */