diff options
| author | Kenny <3454741+WarriorOfWire@users.noreply.github.com> | 2020-07-21 00:01:22 -0700 |
|---|---|---|
| committer | Kenny <3454741+WarriorOfWire@users.noreply.github.com> | 2020-07-23 20:40:16 -0700 |
| commit | 51a79b1af7fa663bb078136611705c04df12970a (patch) | |
| tree | 69e15aa9c69c8383885ff899d67b584e2a060935 /py/objgenerator.c | |
| parent | 543708416bc19bc1e77d859d013c4757433ad255 (diff) | |
add coroutine behavior for generators
coroutines don't have __next__; they also call themselves coroutines.
This does not change the fact that `async def` methods are generators,
but it does make them behave more like CPython.
Diffstat (limited to 'py/objgenerator.c')
| -rw-r--r-- | py/objgenerator.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/py/objgenerator.c b/py/objgenerator.c index 6ffcfae46..57d20e3db 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -42,11 +42,13 @@ typedef struct _mp_obj_gen_wrap_t { mp_obj_base_t base; mp_obj_t *fun; + bool coroutine_generator; } mp_obj_gen_wrap_t; typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; mp_obj_dict_t *globals; + bool coroutine_generator; mp_code_state_t code_state; } mp_obj_gen_instance_t; @@ -64,6 +66,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; + o->coroutine_generator = self->coroutine_generator; o->globals = self_fun->globals; o->code_state.fun_bc = self_fun; o->code_state.ip = 0; @@ -78,10 +81,11 @@ const mp_obj_type_t mp_type_gen_wrap = { .unary_op = mp_generic_unary_op, }; -mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { +mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun, bool is_coroutine) { mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t); o->base.type = &mp_type_gen_wrap; o->fun = MP_OBJ_TO_PTR(fun); + o->coroutine_generator = is_coroutine; return MP_OBJ_FROM_PTR(o); } @@ -91,7 +95,11 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<generator object '%q' at %p>", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); + if (self->coroutine_generator) { + mp_printf(print, "<coroutine object '%q' at %p>", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); + } else { + mp_printf(print, "<generator object '%q' at %p>", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); + } } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { @@ -194,6 +202,10 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o } STATIC mp_obj_t gen_instance_iternext(mp_obj_t self_in) { + mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); + if (self->coroutine_generator) { + mp_raise_TypeError(translate("'coroutine' object is not an iterator")); + } return gen_resume_and_raise(self_in, mp_const_none, MP_OBJ_NULL); } |
