summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index ed82b94..134d1ee 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1828,6 +1828,52 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why = WHY_RETURN;
goto fast_block_end;
+ TARGET(YIELD_FROM)
+ u = POP();
+ x = PyObject_GetIter(u);
+ Py_DECREF(u);
+ if (x == NULL)
+ break;
+ /* x is now the iterator, make the first next() call */
+ retval = (*Py_TYPE(x)->tp_iternext)(x);
+ if (!retval) {
+ /* iter may be exhausted */
+ Py_CLEAR(x);
+ if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {
+ /* some other exception */
+ break;
+ }
+ /* try to get return value from exception */
+ PyObject *et, *ev, *tb;
+ PyErr_Fetch(&et, &ev, &tb);
+ Py_XDECREF(et);
+ Py_XDECREF(tb);
+ /* u is return value */
+ u = NULL;
+ if (ev) {
+ u = PyObject_GetAttrString(ev, "value");
+ Py_DECREF(ev);
+ if (u == NULL) {
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ /* some other exception */
+ break;
+ }
+ PyErr_Clear();
+ }
+ }
+ if (u == NULL) {
+ u = Py_None;
+ Py_INCREF(u);
+ }
+ PUSH(u);
+ continue;
+ }
+ /* x is iterator, retval is value to be yielded */
+ f->f_yieldfrom = x;
+ f->f_stacktop = stack_pointer;
+ why = WHY_YIELD;
+ goto fast_yield;
+
TARGET(YIELD_VALUE)
retval = POP();
f->f_stacktop = stack_pointer;