summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-03-26 19:24:03 +0200
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-03-28 02:50:56 +0200
commit55234f46179ceff01a2364d018ad3ce5dd5f2dfc (patch)
treee7c9c269b7573f876e4e6a74828e8684e4353064
parentcf21a4e7f4fbd330fa65fb5431308ae712626023 (diff)
downloadmicropython-55234f46179ceff01a2364d018ad3ce5dd5f2dfc.tar.gz
micropython-55234f46179ceff01a2364d018ad3ce5dd5f2dfc.zip
py: yield from: Elaborate GeneratorExit (gen.close()) handling.
Handling of GeneratorExit is really peculiar - it subverts normal exception propagation rules.
-rw-r--r--py/vm.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/py/vm.c b/py/vm.c
index 854e747585..607f48cf79 100644
--- a/py/vm.c
+++ b/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_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;
obj1 = POP();
- mp_obj_t t = MP_OBJ_NULL;
+ mp_obj_t t_exc = MP_OBJ_NULL;
if (inject_exc != MP_OBJ_NULL) {
- t = inject_exc;
+ t_exc = inject_exc;
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 {
- 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) {
@@ -672,19 +673,19 @@ yield:
PUSH(obj2);
}
- // if it swallowed it, we re-raise GeneratorExit
- if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) {
- nlr_jump(t);
- }
-
+ // If we injected GeneratorExit downstream, then even
+ // if it was swallowed, we re-raise GeneratorExit
+ GENERATOR_EXIT_IF_NEEDED(t_exc);
break;
}
if (ret_kind == MP_VM_RETURN_EXCEPTION) {
// Pop exhausted gen
sp--;
if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
- printf("Generator explicitly raised StopIteration\n");
- PUSH(mp_const_none);
+ PUSH(mp_obj_exception_get_value(obj2));
+ // If we injected GeneratorExit downstream, then even
+ // if it was swallowed, we re-raise GeneratorExit
+ GENERATOR_EXIT_IF_NEEDED(t_exc);
break;
} else {
nlr_jump(obj2);