py: yield from: Elaborate GeneratorExit (gen.close()) handling.
Handling of GeneratorExit is really peculiar - it subverts normal exception propagation rules.
This commit is contained in:
parent
cf21a4e7f4
commit
55234f4617
23
py/vm.c
23
py/vm.c
@ -645,15 +645,16 @@ yield:
|
|||||||
{
|
{
|
||||||
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
|
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
|
||||||
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
|
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
|
||||||
|
#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_jump(t); }
|
||||||
mp_vm_return_kind_t ret_kind;
|
mp_vm_return_kind_t ret_kind;
|
||||||
obj1 = POP();
|
obj1 = POP();
|
||||||
mp_obj_t t = MP_OBJ_NULL;
|
mp_obj_t t_exc = MP_OBJ_NULL;
|
||||||
if (inject_exc != MP_OBJ_NULL) {
|
if (inject_exc != MP_OBJ_NULL) {
|
||||||
t = inject_exc;
|
t_exc = inject_exc;
|
||||||
inject_exc = MP_OBJ_NULL;
|
inject_exc = MP_OBJ_NULL;
|
||||||
obj2 = mp_obj_gen_resume(TOP(), mp_const_none, t, &ret_kind);
|
ret_kind = mp_obj_gen_resume(TOP(), mp_const_none, t_exc, &obj2);
|
||||||
} else {
|
} else {
|
||||||
obj2 = mp_obj_gen_resume(TOP(), obj1, MP_OBJ_NULL, &ret_kind);
|
ret_kind = mp_obj_gen_resume(TOP(), obj1, MP_OBJ_NULL, &obj2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_kind == MP_VM_RETURN_YIELD) {
|
if (ret_kind == MP_VM_RETURN_YIELD) {
|
||||||
@ -672,19 +673,19 @@ yield:
|
|||||||
PUSH(obj2);
|
PUSH(obj2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it swallowed it, we re-raise GeneratorExit
|
// If we injected GeneratorExit downstream, then even
|
||||||
if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) {
|
// if it was swallowed, we re-raise GeneratorExit
|
||||||
nlr_jump(t);
|
GENERATOR_EXIT_IF_NEEDED(t_exc);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret_kind == MP_VM_RETURN_EXCEPTION) {
|
if (ret_kind == MP_VM_RETURN_EXCEPTION) {
|
||||||
// Pop exhausted gen
|
// Pop exhausted gen
|
||||||
sp--;
|
sp--;
|
||||||
if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
|
if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
|
||||||
printf("Generator explicitly raised StopIteration\n");
|
PUSH(mp_obj_exception_get_value(obj2));
|
||||||
PUSH(mp_const_none);
|
// If we injected GeneratorExit downstream, then even
|
||||||
|
// if it was swallowed, we re-raise GeneratorExit
|
||||||
|
GENERATOR_EXIT_IF_NEEDED(t_exc);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
nlr_jump(obj2);
|
nlr_jump(obj2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user