Пример #1
0
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
    mp_obj_gen_instance_t *self = self_in;
    bool yield = mp_execute_byte_code_2(self->code_info, &self->ip, &self->state[self->n_state - 1], &self->sp);
    if (yield) {
        return *self->sp;
    } else {
        if (*self->sp == mp_const_none) {
            return mp_const_stop_iteration;
        } else {
            // TODO return StopIteration with value *self->sp
            return mp_const_stop_iteration;
        }
    }
}
Пример #2
0
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) {
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
    mp_obj_gen_instance_t *self = self_in;
    if (self->ip == 0) {
        *ret_val = MP_OBJ_STOP_ITERATION;
        return MP_VM_RETURN_NORMAL;
    }
    if (self->sp == self->state - 1) {
        if (send_value != mp_const_none) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator"));
        }
    } else {
        *self->sp = send_value;
    }
    mp_obj_dict_t *old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    mp_vm_return_kind_t ret_kind = mp_execute_byte_code_2(self->code_info, &self->ip,
        &self->state[self->n_state - 1], &self->sp, (mp_exc_stack_t*)(self->state + self->n_state),
        &self->exc_sp, throw_value);
    mp_globals_set(old_globals);

    switch (ret_kind) {
        case MP_VM_RETURN_NORMAL:
            // Explicitly mark generator as completed. If we don't do this,
            // subsequent next() may re-execute statements after last yield
            // again and again, leading to side effects.
            // TODO: check how return with value behaves under such conditions
            // in CPython.
            self->ip = 0;
            *ret_val = *self->sp;
            break;

        case MP_VM_RETURN_YIELD:
            *ret_val = *self->sp;
            break;

        case MP_VM_RETURN_EXCEPTION:
            self->ip = 0;
            *ret_val = self->state[self->n_state - 1];
            break;

        default:
            assert(0);
            *ret_val = mp_const_none;
            break;
    }

    return ret_kind;
}