summaryrefslogtreecommitdiff
path: root/py/compile.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-01-02 10:46:51 +1100
committerDamien George <damien.p.george@gmail.com>2019-01-27 14:09:44 +1100
commitdeb67569ff66b2111cd18679a3bbdb35655cd25d (patch)
tree9029b2aa8940da8a2fa78de3c70c56836278caef /py/compile.c
parent4caf5b23588a82b2a952b0206fe87cd18a9a9050 (diff)
py/compile: Swap order of pop_block/pop_except in "except as" handler.
To make the try-finally block self contained.
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/py/compile.c b/py/compile.c
index 6db108a59..a5bdfa2af 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1582,25 +1582,32 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
compile_store_id(comp, qstr_exception_local);
}
+ // If the exception is bound to a variable <e> then the <body> of the
+ // exception handler is wrapped in a try-finally so that the name <e> can
+ // be deleted (per Python semantics) even if the <body> has an exception.
+ // In such a case the generated code for the exception handler is:
+ // try:
+ // <body>
+ // finally:
+ // <e> = None
+ // del <e>
uint l3 = 0;
if (qstr_exception_local != 0) {
l3 = comp_next_label(comp);
compile_increase_except_level(comp, l3, MP_EMIT_SETUP_BLOCK_FINALLY);
}
- compile_node(comp, pns_except->nodes[1]);
+ compile_node(comp, pns_except->nodes[1]); // the <body>
if (qstr_exception_local != 0) {
EMIT(pop_block);
- }
- EMIT(pop_except);
- if (qstr_exception_local != 0) {
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
EMIT_ARG(label_assign, l3);
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
compile_store_id(comp, qstr_exception_local);
compile_delete_id(comp, qstr_exception_local);
-
compile_decrease_except_level(comp);
}
+
+ EMIT(pop_except);
EMIT_ARG(jump, l2);
EMIT_ARG(label_assign, end_finally_label);
EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance