summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-01-13 11:43:40 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-01-13 11:43:40 (GMT)
commit1f7ce62bd61488d5d721896a36a1b43befab88b5 (patch)
treee7c92d4429ce431c78d0b7816c93862629590223 /Python/ceval.c
parente51757f6de9db71b7ee0a6cbf7dde62e9f146804 (diff)
downloadcpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.zip
cpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.tar.gz
cpython-1f7ce62bd61488d5d721896a36a1b43befab88b5.tar.bz2
Implement PEP 380 - 'yield from' (closes #11682)
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;