Commit 79d996a5 authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

py/runtime: mp_resume: Handle exceptions in Python __next__().

This includes StopIteration and thus are important to make Python-coded
iterables work with yield from/await.

Exceptions in Python send() are still not handled and left for future
consideration and optimization.
parent a392b3aa
...@@ -1191,17 +1191,31 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th ...@@ -1191,17 +1191,31 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
mp_obj_t dest[3]; // Reserve slot for send() arg mp_obj_t dest[3]; // Reserve slot for send() arg
// Python instance iterator protocol
if (send_value == mp_const_none) { if (send_value == mp_const_none) {
mp_load_method_maybe(self_in, MP_QSTR___next__, dest); mp_load_method_maybe(self_in, MP_QSTR___next__, dest);
if (dest[0] != MP_OBJ_NULL) { if (dest[0] != MP_OBJ_NULL) {
*ret_val = mp_call_method_n_kw(0, 0, dest); nlr_buf_t nlr;
return MP_VM_RETURN_YIELD; if (nlr_push(&nlr) == 0) {
*ret_val = mp_call_method_n_kw(0, 0, dest);
nlr_pop();
return MP_VM_RETURN_YIELD;
} else {
*ret_val = nlr.ret_val;
return MP_VM_RETURN_EXCEPTION;
}
} }
} }
// Either python instance generator protocol, or native object
// generator protocol.
if (send_value != MP_OBJ_NULL) { if (send_value != MP_OBJ_NULL) {
mp_load_method(self_in, MP_QSTR_send, dest); mp_load_method(self_in, MP_QSTR_send, dest);
dest[2] = send_value; dest[2] = send_value;
// TODO: This should have exception wrapping like __next__ case
// above. Not done right away to think how to optimize native
// generators better, see:
// https://github.com/micropython/micropython/issues/2628
*ret_val = mp_call_method_n_kw(1, 0, dest); *ret_val = mp_call_method_n_kw(1, 0, dest);
return MP_VM_RETURN_YIELD; return MP_VM_RETURN_YIELD;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment