[Python-checkins] r46650 - in python/trunk: Include/symtable.h Lib/test/test_generators.py Misc/NEWS Python/compile.c Python/symtable.c

georg.brandl python-checkins at python.org
Sun Jun 4 23:57:14 CEST 2006


Author: georg.brandl
Date: Sun Jun  4 23:56:52 2006
New Revision: 46650

Modified:
   python/trunk/Include/symtable.h
   python/trunk/Lib/test/test_generators.py
   python/trunk/Misc/NEWS
   python/trunk/Python/compile.c
   python/trunk/Python/symtable.c
Log:
Patch #1346214: correctly optimize away "if 0"-style stmts
(thanks to Neal for review)



Modified: python/trunk/Include/symtable.h
==============================================================================
--- python/trunk/Include/symtable.h	(original)
+++ python/trunk/Include/symtable.h	Sun Jun  4 23:56:52 2006
@@ -39,6 +39,8 @@
 	unsigned ste_generator : 1;   /* true if namespace is a generator */
 	unsigned ste_varargs : 1;     /* true if block has varargs */
 	unsigned ste_varkeywords : 1; /* true if block has varkeywords */
+	unsigned ste_returns_value : 1;  /* true if namespace uses return with
+	                                    an argument */
 	int ste_lineno;          /* first line of block */
 	int ste_opt_lineno;      /* lineno of last exec or import * */
 	int ste_tmpname;         /* counter for listcomp temp vars */

Modified: python/trunk/Lib/test/test_generators.py
==============================================================================
--- python/trunk/Lib/test/test_generators.py	(original)
+++ python/trunk/Lib/test/test_generators.py	Sun Jun  4 23:56:52 2006
@@ -733,7 +733,7 @@
 ...     yield 1
 Traceback (most recent call last):
   ..
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2)
+SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3)
 
 >>> def f():
 ...     yield 1
@@ -876,9 +876,9 @@
 ...         if 0:
 ...             return 3        # but *this* sucks (line 8)
 ...     if 0:
-...         yield 2             # because it's a generator
+...         yield 2             # because it's a generator (line 10)
 Traceback (most recent call last):
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 8)
+SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 10)
 
 This one caused a crash (see SF bug 567538):
 

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sun Jun  4 23:56:52 2006
@@ -12,6 +12,9 @@
 Core and builtins
 -----------------
 
+- Patch #1346214: Statements like "if 0: suite" are now again optimized
+  away like they were in Python 2.4.
+
 - Builtin exceptions are now full-blown new-style classes instead of
   instances pretending to be classes, which speeds up exception handling
   by about 80% in comparison to 2.5a2.

Modified: python/trunk/Python/compile.c
==============================================================================
--- python/trunk/Python/compile.c	(original)
+++ python/trunk/Python/compile.c	Sun Jun  4 23:56:52 2006
@@ -2148,7 +2148,7 @@
 compiler_if(struct compiler *c, stmt_ty s)
 {
 	basicblock *end, *next;
-
+	int constant;
 	assert(s->kind == If_kind);
 	end = compiler_new_block(c);
 	if (end == NULL)
@@ -2156,15 +2156,27 @@
 	next = compiler_new_block(c);
 	if (next == NULL)
 	    return 0;
-	VISIT(c, expr, s->v.If.test);
-	ADDOP_JREL(c, JUMP_IF_FALSE, next);
-	ADDOP(c, POP_TOP);
-	VISIT_SEQ(c, stmt, s->v.If.body);
-	ADDOP_JREL(c, JUMP_FORWARD, end);
-	compiler_use_next_block(c, next);
-	ADDOP(c, POP_TOP);
-	if (s->v.If.orelse)
-	    VISIT_SEQ(c, stmt, s->v.If.orelse);
+	
+	constant = expr_constant(s->v.If.test);
+	/* constant = 0: "if 0"
+	 * constant = 1: "if 1", "if 2", ...
+	 * constant = -1: rest */
+	if (constant == 0) {
+		if (s->v.If.orelse)
+			VISIT_SEQ(c, stmt, s->v.If.orelse);
+	} else if (constant == 1) {
+		VISIT_SEQ(c, stmt, s->v.If.body);
+	} else {
+		VISIT(c, expr, s->v.If.test);
+		ADDOP_JREL(c, JUMP_IF_FALSE, next);
+		ADDOP(c, POP_TOP);
+		VISIT_SEQ(c, stmt, s->v.If.body);
+		ADDOP_JREL(c, JUMP_FORWARD, end);
+		compiler_use_next_block(c, next);
+		ADDOP(c, POP_TOP);
+		if (s->v.If.orelse)
+	    		VISIT_SEQ(c, stmt, s->v.If.orelse);
+	}
 	compiler_use_next_block(c, end);
 	return 1;
 }
@@ -2639,10 +2651,6 @@
 		if (c->u->u_ste->ste_type != FunctionBlock)
 			return compiler_error(c, "'return' outside function");
 		if (s->v.Return.value) {
-			if (c->u->u_ste->ste_generator) {
-				return compiler_error(c,
-				    "'return' with argument inside generator");
-			}
 			VISIT(c, expr, s->v.Return.value);
 		}
 		else
@@ -3356,6 +3364,13 @@
 		return PyObject_IsTrue(e->v.Num.n);
 	case Str_kind:
 		return PyObject_IsTrue(e->v.Str.s);
+	case Name_kind:
+		/* __debug__ is not assignable, so we can optimize
+		 * it away in if and while statements */
+		if (strcmp(PyString_AS_STRING(e->v.Name.id),
+		           "__debug__") == 0)
+			   return ! Py_OptimizeFlag;
+		/* fall through */
 	default:
 		return -1;
 	}

Modified: python/trunk/Python/symtable.c
==============================================================================
--- python/trunk/Python/symtable.c	(original)
+++ python/trunk/Python/symtable.c	Sun Jun  4 23:56:52 2006
@@ -13,6 +13,8 @@
 
 #define IMPORT_STAR_WARNING "import * only allowed at module level"
 
+#define RETURN_VAL_IN_GENERATOR \
+    "'return' with argument inside generator"
 
 /* XXX(nnorwitz): change name since static? */
 static PySTEntryObject *
@@ -66,6 +68,7 @@
 		ste->ste_nested = 1;
 	ste->ste_child_free = 0;
 	ste->ste_generator = 0;
+	ste->ste_returns_value = 0;
 
 	if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0)
 	    goto fail;
@@ -944,8 +947,17 @@
 		break;
 	}
         case Return_kind:
-		if (s->v.Return.value)
+		if (s->v.Return.value) {
 			VISIT(st, expr, s->v.Return.value);
+			st->st_cur->ste_returns_value = 1;
+			if (st->st_cur->ste_generator) {
+				PyErr_SetString(PyExc_SyntaxError,
+					RETURN_VAL_IN_GENERATOR);
+			        PyErr_SyntaxLocation(st->st_filename,
+				             s->lineno);
+				return 0;
+			}
+		}
 		break;
         case Delete_kind:
 		VISIT_SEQ(st, expr, s->v.Delete.targets);
@@ -1136,6 +1148,13 @@
 		if (e->v.Yield.value)
 			VISIT(st, expr, e->v.Yield.value);
                 st->st_cur->ste_generator = 1;
+		if (st->st_cur->ste_returns_value) {
+			PyErr_SetString(PyExc_SyntaxError,
+				RETURN_VAL_IN_GENERATOR);
+		        PyErr_SyntaxLocation(st->st_filename,
+			             e->lineno);
+			return 0;
+		}
 		break;
         case Compare_kind:
 		VISIT(st, expr, e->v.Compare.left);


More information about the Python-checkins mailing list