diff options
author | Damien George <damien.p.george@gmail.com> | 2018-10-01 13:07:04 +1000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2018-10-01 13:31:11 +1000 |
commit | cc2bd63c57a72ec37d839965c6bb61cd1fa202fc (patch) | |
tree | 44acc885421554921db85273aed4d1b1de4ecbf8 /py/nativeglue.c | |
parent | 8fec6f543411dc16b42e9850af0cc3a1097162a7 (diff) | |
download | micropython-cc2bd63c57a72ec37d839965c6bb61cd1fa202fc.tar.gz micropython-cc2bd63c57a72ec37d839965c6bb61cd1fa202fc.zip |
py/emitnative: Implement yield and yield-from in native emitter.
This commit adds first class support for yield and yield-from in the native
emitter, including send and throw support, and yields enclosed in exception
handlers (which requires pulling down the NLR stack before yielding, then
rebuilding it when resuming).
This has been fully tested and is working on unix x86 and x86-64, and
stm32. Also basic tests have been done with the esp8266 port. Performance
of existing native code is unchanged.
Diffstat (limited to 'py/nativeglue.c')
-rw-r--r-- | py/nativeglue.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/py/nativeglue.c b/py/nativeglue.c index a15a2eae31..b3a50ef198 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -106,7 +106,7 @@ mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const m // wrapper that makes raise obj and raises it // END_FINALLY opcode requires that we don't raise if o==None void mp_native_raise(mp_obj_t o) { - if (o != mp_const_none) { + if (o != MP_OBJ_NULL && o != mp_const_none) { nlr_raise(mp_make_raise_obj(o)); } } @@ -137,6 +137,42 @@ STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { return mp_iternext(obj); } +STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) { + mp_vm_return_kind_t ret_kind; + nlr_buf_t nlr_buf; + mp_obj_t throw_value = *ret_value; + if (nlr_push(&nlr_buf) == 0) { + if (throw_value != MP_OBJ_NULL) { + send_value = MP_OBJ_NULL; + } + ret_kind = mp_resume(gen, send_value, throw_value, ret_value); + nlr_pop(); + } else { + ret_kind = MP_VM_RETURN_EXCEPTION; + *ret_value = nlr_buf.ret_val; + } + + if (ret_kind == MP_VM_RETURN_YIELD) { + return true; + } else if (ret_kind == MP_VM_RETURN_NORMAL) { + if (*ret_value == MP_OBJ_STOP_ITERATION) { + *ret_value = mp_const_none; + } + } else { + assert(ret_kind == MP_VM_RETURN_EXCEPTION); + if (!mp_obj_exception_match(*ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { + nlr_raise(*ret_value); + } + *ret_value = mp_obj_exception_get_value(*ret_value); + } + + if (throw_value != MP_OBJ_NULL && mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { + nlr_raise(mp_make_raise_obj(throw_value)); + } + + return false; +} + // these must correspond to the respective enum in runtime0.h void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_convert_obj_to_native, @@ -189,6 +225,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_setup_code_state, mp_small_int_floor_divide, mp_small_int_modulo, + mp_native_yield_from, }; /* |