Skip to content

Commit 55234f4

Browse files
committed
py: yield from: Elaborate GeneratorExit (gen.close()) handling.
Handling of GeneratorExit is really peculiar - it subverts normal exception propagation rules.
1 parent cf21a4e commit 55234f4

1 file changed

Lines changed: 12 additions & 11 deletions

File tree

py/vm.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -645,15 +645,16 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
645645
{
646646
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
647647
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
648+
#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_jump(t); }
648649
mp_vm_return_kind_t ret_kind;
649650
obj1 = POP();
650-
mp_obj_t t = MP_OBJ_NULL;
651+
mp_obj_t t_exc = MP_OBJ_NULL;
651652
if (inject_exc != MP_OBJ_NULL) {
652-
t = inject_exc;
653+
t_exc = inject_exc;
653654
inject_exc = MP_OBJ_NULL;
654-
obj2 = mp_obj_gen_resume(TOP(), mp_const_none, t, &ret_kind);
655+
ret_kind = mp_obj_gen_resume(TOP(), mp_const_none, t_exc, &obj2);
655656
} else {
656-
obj2 = mp_obj_gen_resume(TOP(), obj1, MP_OBJ_NULL, &ret_kind);
657+
ret_kind = mp_obj_gen_resume(TOP(), obj1, MP_OBJ_NULL, &obj2);
657658
}
658659

659660
if (ret_kind == MP_VM_RETURN_YIELD) {
@@ -672,19 +673,19 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
672673
PUSH(obj2);
673674
}
674675

675-
// if it swallowed it, we re-raise GeneratorExit
676-
if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) {
677-
nlr_jump(t);
678-
}
679-
676+
// If we injected GeneratorExit downstream, then even
677+
// if it was swallowed, we re-raise GeneratorExit
678+
GENERATOR_EXIT_IF_NEEDED(t_exc);
680679
break;
681680
}
682681
if (ret_kind == MP_VM_RETURN_EXCEPTION) {
683682
// Pop exhausted gen
684683
sp--;
685684
if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
686-
printf("Generator explicitly raised StopIteration\n");
687-
PUSH(mp_const_none);
685+
PUSH(mp_obj_exception_get_value(obj2));
686+
// If we injected GeneratorExit downstream, then even
687+
// if it was swallowed, we re-raise GeneratorExit
688+
GENERATOR_EXIT_IF_NEEDED(t_exc);
688689
break;
689690
} else {
690691
nlr_jump(obj2);

0 commit comments

Comments
 (0)