Index: Python/ceval.c |
=================================================================== |
--- a/Python/ceval.c |
+++ b/Python/ceval.c |
@@ -1691,8 +1691,47 @@ PyEval_EvalFrameEx(PyFrameObject *f, int |
why = WHY_RETURN; |
goto fast_block_end; |
+ case YIELD_FROM: |
+ u = POP(); |
+ x = PyObject_GetIter(u); |
+ Py_DECREF(u); |
+ if (!x) |
+ break; |
+ /* x is now the iterator, make the first next() call */ |
+ retval = (*x->ob_type->tp_iternext)(x); |
+ if (!retval) { |
+ /* iter may be exhausted */ |
+ Py_DECREF(x); |
+ if (PyErr_ExceptionMatches(PyExc_StopIteration)) { |
+ /* try to get return value from exception */ |
+ PyObject *et, *ev, *tb; |
+ PyErr_Fetch(&et, &ev, &tb); |
+ Py_XDECREF(et); Py_XDECREF(tb); |
+ u = NULL; |
+ if (ev) { |
+ u = PyObject_GetAttrString(ev, "value"); |
+ Py_DECREF(ev); |
+ if (!u) PyErr_Clear(); |
+ } |
+ if (!u) { |
+ u = Py_None; |
+ Py_INCREF(u); |
+ } |
+ /* u is return value */ |
+ PUSH(u); |
+ continue; |
+ } |
+ /* some other exception */ |
+ x = NULL; |
+ break; |
+ } |
+ /* x is iterator, retval is value to be yielded */ |
+ f->f_yieldfrom = x; |
+ goto yield_retval; |
+ |
case YIELD_VALUE: |
retval = POP(); |
+ yield_retval: |
f->f_stacktop = stack_pointer; |
why = WHY_YIELD; |
goto fast_yield; |