Commit 06248c87 authored by Tim Peters's avatar Tim Peters

Change the semantics of "return" in generators, as discussed on the

Iterators list and Python-Dev; e.g., these all pass now:

def g1():
    try:
        return
    except:
        yield 1
assert list(g1()) == []

def g2():
    try:
        return
    finally:
        yield 1
assert list(g2()) == [1]

def g3():
    for i in range(3):
        yield None
    yield None
assert list(g3()) == [None] * 4

compile.c:  compile_funcdef and com_return_stmt:  Just van Rossum's patch
to compile the same code for "return" regardless of function type (this
goes back to the previous scheme of returning Py_None).

ceval.c:  gen_iternext:  take a return (but not a yield) of Py_None as
meaning the generator is exhausted.
parent e4354a3d
...@@ -166,6 +166,13 @@ gen_iternext(genobject *gen) ...@@ -166,6 +166,13 @@ gen_iternext(genobject *gen)
Py_XDECREF(f->f_back); Py_XDECREF(f->f_back);
f->f_back = NULL; f->f_back = NULL;
/* If the generator just returned (as opposed to yielding), signal
* that the generator is exhausted. */
if (result == Py_None && f->f_stacktop == NULL) {
Py_DECREF(result);
result = NULL;
}
return result; return result;
} }
......
...@@ -2639,20 +2639,14 @@ com_return_stmt(struct compiling *c, node *n) ...@@ -2639,20 +2639,14 @@ com_return_stmt(struct compiling *c, node *n)
com_error(c, PyExc_SyntaxError, com_error(c, PyExc_SyntaxError,
"'return' with argument inside generator"); "'return' with argument inside generator");
} }
com_addoparg(c, LOAD_CONST,
com_addconst(c, PyExc_StopIteration));
com_push(c, 1);
com_addoparg(c, RAISE_VARARGS, 1);
} }
else { if (NCH(n) < 2) {
if (NCH(n) < 2) { com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); com_push(c, 1);
com_push(c, 1);
}
else
com_node(c, CHILD(n, 1));
com_addbyte(c, RETURN_VALUE);
} }
else
com_node(c, CHILD(n, 1));
com_addbyte(c, RETURN_VALUE);
com_pop(c, 1); com_pop(c, 1);
} }
...@@ -3711,19 +3705,10 @@ compile_funcdef(struct compiling *c, node *n) ...@@ -3711,19 +3705,10 @@ compile_funcdef(struct compiling *c, node *n)
c->c_infunction = 1; c->c_infunction = 1;
com_node(c, CHILD(n, 4)); com_node(c, CHILD(n, 4));
c->c_infunction = 0; c->c_infunction = 0;
if (c->c_flags & CO_GENERATOR) { com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_addoparg(c, LOAD_CONST, com_push(c, 1);
com_addconst(c, PyExc_StopIteration)); com_addbyte(c, RETURN_VALUE);
com_push(c, 1); com_pop(c, 1);
com_addoparg(c, RAISE_VARARGS, 1);
com_pop(c, 1);
}
else {
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
com_addbyte(c, RETURN_VALUE);
com_pop(c, 1);
}
} }
static void static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment