[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