예제 #1
0
파일: Generator.c 프로젝트: vietlq/cython
static CYTHON_INLINE
PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value)
{
    PyObject *retval;

    if (self->is_running) {
        PyErr_SetString(PyExc_ValueError,
                        "generator already executing");
        return NULL;
    }

    if (self->resume_label == 0) {
        if (value && value != Py_None) {
            PyErr_SetString(PyExc_TypeError,
                            "can't send non-None value to a "
                            "just-started generator");
            return NULL;
        }
    }

    if (self->resume_label == -1) {
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }


    if (value)
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
    else
        __Pyx_Generator_ExceptionClear(self);

    self->is_running = 1;
    retval = self->body((PyObject *) self, value);
    self->is_running = 0;

    if (retval)
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback);
    else
        __Pyx_Generator_ExceptionClear(self);

    return retval;
}
예제 #2
0
static CYTHON_INLINE
PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value) {
    PyObject *retval;

    assert(!self->is_running);

    if (unlikely(self->resume_label == 0)) {
        if (unlikely(value && value != Py_None)) {
            PyErr_SetString(PyExc_TypeError,
                            "can't send non-None value to a "
                            "just-started generator");
            return NULL;
        }
    }

    if (unlikely(self->resume_label == -1)) {
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }


    if (value) {
#if CYTHON_COMPILING_IN_PYPY
        // FIXME: what to do in PyPy?
#else
        /* Generators always return to their most recent caller, not
         * necessarily their creator. */
        if (self->exc_traceback) {
            PyThreadState *tstate = PyThreadState_GET();
            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
            PyFrameObject *f = tb->tb_frame;

            Py_XINCREF(tstate->frame);
            assert(f->f_back == NULL);
            f->f_back = tstate->frame;
        }
#endif
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
                            &self->exc_traceback);
    } else {
        __Pyx_Generator_ExceptionClear(self);
    }

    self->is_running = 1;
    retval = self->body((PyObject *) self, value);
    self->is_running = 0;

    if (retval) {
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
                            &self->exc_traceback);
#if CYTHON_COMPILING_IN_PYPY
        // FIXME: what to do in PyPy?
#else
        /* Don't keep the reference to f_back any longer than necessary.  It
         * may keep a chain of frames alive or it could create a reference
         * cycle. */
        if (self->exc_traceback) {
            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
            PyFrameObject *f = tb->tb_frame;
            Py_CLEAR(f->f_back);
        }
#endif
    } else {
        __Pyx_Generator_ExceptionClear(self);
    }

    return retval;
}