summaryrefslogtreecommitdiff
path: root/py/emitbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/emitbc.c')
-rw-r--r--py/emitbc.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/py/emitbc.c b/py/emitbc.c
index 05754cfab..f6bb229ba 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -666,6 +666,27 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) {
mp_emit_bc_adjust_stack_size(emit, -4);
}
+#if MICROPY_PY_ASYNC_AWAIT
+void mp_emit_bc_async_with_setup_finally(emit_t *emit, mp_uint_t label_aexit_no_exc, mp_uint_t label_finally_block, mp_uint_t label_ret_unwind_jump) {
+ // The async-with body has executed and no exception was raised, the execution fell through to this point.
+ // Stack: (..., ctx_mgr)
+
+ // Finish async-with body and prepare to enter "finally" block.
+ mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception
+ mp_emit_bc_rot_two(emit);
+ mp_emit_bc_jump(emit, label_aexit_no_exc); // jump to code to call __aexit__
+
+ // Start of "finally" block which is entered via one of: an exception propagating out, a return, an unwind jump.
+ mp_emit_bc_label_assign(emit, label_finally_block);
+
+ // Detect which case we have by the TOS being an exception or not.
+ mp_emit_bc_dup_top(emit);
+ mp_emit_bc_load_global(emit, MP_QSTR_BaseException, MP_EMIT_IDOP_GLOBAL_GLOBAL);
+ mp_emit_bc_binary_op(emit, MP_BINARY_OP_EXCEPTION_MATCH);
+ mp_emit_bc_pop_jump_if(emit, false, label_ret_unwind_jump); // if not an exception then we have return or unwind jump.
+}
+#endif
+
void mp_emit_bc_end_finally(emit_t *emit) {
emit_write_bytecode_byte(emit, -1, MP_BC_END_FINALLY);
}
@@ -862,6 +883,9 @@ const emit_method_table_t emit_bc_method_table = {
mp_emit_bc_unwind_jump,
mp_emit_bc_setup_block,
mp_emit_bc_with_cleanup,
+ #if MICROPY_PY_ASYNC_AWAIT
+ mp_emit_bc_async_with_setup_finally,
+ #endif
mp_emit_bc_end_finally,
mp_emit_bc_get_iter,
mp_emit_bc_for_iter,