From ad1a18b78ef87957a716af47e4c4f125e85565d0 Mon Sep 17 00:00:00 2001
From: Tim Peters <tim.peters@gmail.com>
Date: Sat, 23 Jun 2001 06:19:16 +0000
Subject: 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.
---
 Python/ceval.c   |  7 +++++++
 Python/compile.c | 35 ++++++++++-------------------------
 2 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/Python/ceval.c b/Python/ceval.c
index d334775..6a1ba50 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -166,6 +166,13 @@ gen_iternext(genobject *gen)
 	Py_XDECREF(f->f_back);
 	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;
 }
 
diff --git a/Python/compile.c b/Python/compile.c
index 843cf09..2ce7487 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2639,20 +2639,14 @@ com_return_stmt(struct compiling *c, node *n)
 			com_error(c, PyExc_SyntaxError,
 				  "'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) {
-			com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-			com_push(c, 1);
-		}
-		else
-			com_node(c, CHILD(n, 1));
-		com_addbyte(c, RETURN_VALUE);
+	if (NCH(n) < 2) {
+		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
+		com_push(c, 1);
 	}
+	else
+		com_node(c, CHILD(n, 1));
+	com_addbyte(c, RETURN_VALUE);
 	com_pop(c, 1);
 }
 
@@ -3711,19 +3705,10 @@ compile_funcdef(struct compiling *c, node *n)
 	c->c_infunction = 1;
 	com_node(c, CHILD(n, 4));
 	c->c_infunction = 0;
-	if (c->c_flags & CO_GENERATOR) {
-		com_addoparg(c, LOAD_CONST,
-				com_addconst(c, PyExc_StopIteration));
-		com_push(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);
-	}
+	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
-- 
cgit v0.12

