[Python-checkins] r62706 - in python/branches/tlee-ast-optimize: Include/Python-ast.h Lib/test/test_optimizer.py Parser/asdl_c.py Python/Python-ast.c Python/compile.c Python/optimize.c Python/peephole.c

thomas.lee python-checkins at python.org
Sun May 4 18:57:45 CEST 2008


Author: thomas.lee
Date: Sun May  4 18:57:45 2008
New Revision: 62706

Log:
Implementing very, very rough initial implementation of annotated ASTs. Got one or two extra optimizations ported from the peepholer (most notably, folding tuples of constants). Tests are somewhat incomplete, and refleaks are likely to be present.

Modified:
   python/branches/tlee-ast-optimize/Include/Python-ast.h
   python/branches/tlee-ast-optimize/Lib/test/test_optimizer.py
   python/branches/tlee-ast-optimize/Parser/asdl_c.py
   python/branches/tlee-ast-optimize/Python/Python-ast.c
   python/branches/tlee-ast-optimize/Python/compile.c
   python/branches/tlee-ast-optimize/Python/optimize.c
   python/branches/tlee-ast-optimize/Python/peephole.c

Modified: python/branches/tlee-ast-optimize/Include/Python-ast.h
==============================================================================
--- python/branches/tlee-ast-optimize/Include/Python-ast.h	(original)
+++ python/branches/tlee-ast-optimize/Include/Python-ast.h	Sun May  4 18:57:45 2008
@@ -57,6 +57,7 @@
                 } Suite;
                 
         } v;
+        PyObject* annotations;
 };
 
 enum _stmt_kind {FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3,
@@ -182,6 +183,7 @@
         } v;
         int lineno;
         int col_offset;
+        PyObject* annotations;
 };
 
 enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
@@ -295,6 +297,7 @@
         } v;
         int lineno;
         int col_offset;
+        PyObject* annotations;
 };
 
 enum _slice_kind {Ellipsis_kind=1, Slice_kind=2, ExtSlice_kind=3, Index_kind=4};
@@ -316,6 +319,7 @@
                 } Index;
                 
         } v;
+        PyObject* annotations;
 };
 
 struct _comprehension {
@@ -337,6 +341,7 @@
         } v;
         int lineno;
         int col_offset;
+        PyObject* annotations;
 };
 
 struct _arguments {

Modified: python/branches/tlee-ast-optimize/Lib/test/test_optimizer.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/test/test_optimizer.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/test/test_optimizer.py	Sun May  4 18:57:45 2008
@@ -97,7 +97,7 @@
 
         for code, expected in tests:
             ast = self.compileast(code)
-            actual = getattr(ast.body[0].value, attrmap[type(expected)])
+            actual = ast.body[0].value.annotations['const']
             self.assertEqual(expected, actual)
 
     def test_binop_fold_num_with_variable(self):
@@ -118,8 +118,8 @@
         self.assertEqual(_ast.Expr, ast.body[1].__class__)
         self.assertEqual(_ast.BinOp, ast.body[1].value.__class__)
         self.assertEqual(_ast.Name, ast.body[1].value.left.__class__)
-        self.assertEqual(_ast.Num, ast.body[1].value.right.__class__)
-        self.assertEqual(6, ast.body[1].value.right.n)
+        self.assertEqual(_ast.BinOp, ast.body[1].value.right.__class__)
+        self.assertEqual(6, ast.body[1].value.right.annotations['const'])
 
     def test_binop_failure_left_until_runtime(self):
         ast = self.compileast("5 + '3'")
@@ -134,13 +134,22 @@
         except TypeError:
             pass
 
+    def assertConstant(self, expected, code):
+        ast = self.compileast(code).body[0].value
+        if type(ast) is _ast.Str:
+            self.assertEqual(expected, ast.s)
+        elif type(ast) is _ast.Num:
+            self.assertEqual(expected, ast.n)
+        else:
+            self.assertEqual(expected, ast.annotations['const'])
+
     def test_unary_fold_num(self):
         # check unary constant folding for numeric values
-        self.assertNum(-5, "-5")
-        self.assertNum(True, "not 0")
-        self.assertNum(-3, "-+3")
-        self.assertNum(False, "not True")
-        self.assertNum(True, "not None")
+        self.assertConstant(-5, '-5')
+        self.assertConstant(True, "not 0")
+        self.assertConstant(-3, "-+3")
+        self.assertConstant(False, "not True")
+        self.assertConstant(True, "not None")
 
     def test_unary_failure_left_until_runtime(self):
         ast = self.compileast("~'bad!'")
@@ -188,6 +197,13 @@
         self.assertEqual(3, len(ast.body[0].body))
         self.assertEqual(_ast.Pass, ast.body[0].body[2].__class__)
 
+    def test_fold_tuple_of_constants(self):
+        ast = self.compileast('(1, 2, 3)')
+        self.assertEqual((1, 2, 3), ast.body[0].value.annotations['const'])
+
+        ast = self.compileast('((1, 2), 3)')
+        self.assertEqual(((1, 2), 3), ast.body[0].value.annotations['const'])
+
 def test_main():
     test_support.run_unittest(AstOptimizerTest)
 

Modified: python/branches/tlee-ast-optimize/Parser/asdl_c.py
==============================================================================
--- python/branches/tlee-ast-optimize/Parser/asdl_c.py	(original)
+++ python/branches/tlee-ast-optimize/Parser/asdl_c.py	Sun May  4 18:57:45 2008
@@ -170,6 +170,7 @@
             type = str(field.type)
             assert type in asdl.builtin_types, type
             emit("%s %s;" % (type, field.name), depth + 1);
+        emit("PyObject* annotations;", depth + 1)
         emit("};")
         emit("")
 
@@ -321,6 +322,7 @@
             emit("p->v.%s.%s = %s;" % (name, argname, argname), 1)
         for argtype, argname, opt in attrs:
             emit("p->%s = %s;" % (argname, argname), 1)
+        emit("p->annotations = NULL;", 1)
 
     def emit_body_struct(self, name, args, attrs):
         def emit(s, depth=0, reflow=1):
@@ -417,6 +419,9 @@
             args = [f.name.value for f in t.fields] + [a.name.value for a in sum.attributes]
             self.emit("*out = %s(%s);" % (t.name, self.buildArgs(args)), 2)
             self.emit("if (*out == NULL) goto failed;", 2)
+            self.emit('(*out)->annotations = PyObject_GetAttrString(obj, "annotations");', 2)
+            self.emit('if ((*out)->annotations == NULL)', 2)
+            self.emit('PyErr_Clear();', 3)
             self.emit("return 0;", 2)
             self.emit("}", 1)
         self.sumTrailer(name)
@@ -980,6 +985,9 @@
             self.emit('if (PyObject_SetAttrString(result, "%s", value) < 0)' % a.name, 1)
             self.emit('goto failed;', 2)
             self.emit('Py_DECREF(value);', 1)
+        if not is_simple(sum):
+            self.emit('if (o->annotations && PyObject_SetAttrString(result, "annotations", o->annotations) < 0)', 1)
+            self.emit('goto failed;', 2)
         self.func_end()
 
     def simpleSum(self, sum, name):

Modified: python/branches/tlee-ast-optimize/Python/Python-ast.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/Python-ast.c	(original)
+++ python/branches/tlee-ast-optimize/Python/Python-ast.c	Sun May  4 18:57:45 2008
@@ -936,6 +936,7 @@
                 return NULL;
         p->kind = Module_kind;
         p->v.Module.body = body;
+        p->annotations = NULL;
         return p;
 }
 
@@ -948,6 +949,7 @@
                 return NULL;
         p->kind = Interactive_kind;
         p->v.Interactive.body = body;
+        p->annotations = NULL;
         return p;
 }
 
@@ -965,6 +967,7 @@
                 return NULL;
         p->kind = Expression_kind;
         p->v.Expression.body = body;
+        p->annotations = NULL;
         return p;
 }
 
@@ -977,6 +980,7 @@
                 return NULL;
         p->kind = Suite_kind;
         p->v.Suite.body = body;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1005,6 +1009,7 @@
         p->v.FunctionDef.decorator_list = decorator_list;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1028,6 +1033,7 @@
         p->v.ClassDef.decorator_list = decorator_list;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1042,6 +1048,7 @@
         p->v.Return.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1056,6 +1063,7 @@
         p->v.Delete.targets = targets;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1077,6 +1085,7 @@
         p->v.Assign.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1109,6 +1118,7 @@
         p->v.AugAssign.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1126,6 +1136,7 @@
         p->v.Print.nl = nl;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1154,6 +1165,7 @@
         p->v.For.orelse = orelse;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1176,6 +1188,7 @@
         p->v.While.orelse = orelse;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1198,6 +1211,7 @@
         p->v.If.orelse = orelse;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1220,6 +1234,7 @@
         p->v.With.body = body;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1237,6 +1252,7 @@
         p->v.Raise.tback = tback;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1254,6 +1270,7 @@
         p->v.TryExcept.orelse = orelse;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1270,6 +1287,7 @@
         p->v.TryFinally.finalbody = finalbody;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1290,6 +1308,7 @@
         p->v.Assert.msg = msg;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1304,6 +1323,7 @@
         p->v.Import.names = names;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1326,6 +1346,7 @@
         p->v.ImportFrom.level = level;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1348,6 +1369,7 @@
         p->v.Exec.locals = locals;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1362,6 +1384,7 @@
         p->v.Global.names = names;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1381,6 +1404,7 @@
         p->v.Expr.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1394,6 +1418,7 @@
         p->kind = Pass_kind;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1407,6 +1432,7 @@
         p->kind = Break_kind;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1420,6 +1446,7 @@
         p->kind = Continue_kind;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1441,6 +1468,7 @@
         p->v.BoolOp.values = values;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1473,6 +1501,7 @@
         p->v.BinOp.right = right;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1499,6 +1528,7 @@
         p->v.UnaryOp.operand = operand;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1525,6 +1555,7 @@
         p->v.Lambda.body = body;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1557,6 +1588,7 @@
         p->v.IfExp.orelse = orelse;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1573,6 +1605,7 @@
         p->v.Dict.values = values;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1594,6 +1627,7 @@
         p->v.ListComp.generators = generators;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1615,6 +1649,7 @@
         p->v.GeneratorExp.generators = generators;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1629,6 +1664,7 @@
         p->v.Yield.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1651,6 +1687,7 @@
         p->v.Compare.comparators = comparators;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1675,6 +1712,7 @@
         p->v.Call.kwargs = kwargs;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1694,6 +1732,7 @@
         p->v.Repr.value = value;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1713,6 +1752,7 @@
         p->v.Num.n = n;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1732,6 +1772,7 @@
         p->v.Str.s = s;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1764,6 +1805,7 @@
         p->v.Attribute.ctx = ctx;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1796,6 +1838,7 @@
         p->v.Subscript.ctx = ctx;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1822,6 +1865,7 @@
         p->v.Name.ctx = ctx;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1843,6 +1887,7 @@
         p->v.List.ctx = ctx;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1864,6 +1909,7 @@
         p->v.Tuple.ctx = ctx;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1875,6 +1921,7 @@
         if (!p)
                 return NULL;
         p->kind = Ellipsis_kind;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1889,6 +1936,7 @@
         p->v.Slice.lower = lower;
         p->v.Slice.upper = upper;
         p->v.Slice.step = step;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1901,6 +1949,7 @@
                 return NULL;
         p->kind = ExtSlice_kind;
         p->v.ExtSlice.dims = dims;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1918,6 +1967,7 @@
                 return NULL;
         p->kind = Index_kind;
         p->v.Index.value = value;
+        p->annotations = NULL;
         return p;
 }
 
@@ -1958,6 +2008,7 @@
         p->v.ExceptHandler.body = body;
         p->lineno = lineno;
         p->col_offset = col_offset;
+        p->annotations = NULL;
         return p;
 }
 
@@ -2064,6 +2115,9 @@
                 Py_DECREF(value);
                 break;
         }
+        if (o->annotations && PyObject_SetAttrString(result, "annotations",
+            o->annotations) < 0)
+                goto failed;
         return result;
 failed:
         Py_XDECREF(value);
@@ -2441,6 +2495,9 @@
         if (PyObject_SetAttrString(result, "col_offset", value) < 0)
                 goto failed;
         Py_DECREF(value);
+        if (o->annotations && PyObject_SetAttrString(result, "annotations",
+            o->annotations) < 0)
+                goto failed;
         return result;
 failed:
         Py_XDECREF(value);
@@ -2764,6 +2821,9 @@
         if (PyObject_SetAttrString(result, "col_offset", value) < 0)
                 goto failed;
         Py_DECREF(value);
+        if (o->annotations && PyObject_SetAttrString(result, "annotations",
+            o->annotations) < 0)
+                goto failed;
         return result;
 failed:
         Py_XDECREF(value);
@@ -2851,6 +2911,9 @@
                 Py_DECREF(value);
                 break;
         }
+        if (o->annotations && PyObject_SetAttrString(result, "annotations",
+            o->annotations) < 0)
+                goto failed;
         return result;
 failed:
         Py_XDECREF(value);
@@ -3053,6 +3116,9 @@
         if (PyObject_SetAttrString(result, "col_offset", value) < 0)
                 goto failed;
         Py_DECREF(value);
+        if (o->annotations && PyObject_SetAttrString(result, "annotations",
+            o->annotations) < 0)
+                goto failed;
         return result;
 failed:
         Py_XDECREF(value);
@@ -3198,6 +3264,10 @@
                 }
                 *out = Module(body, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Interactive_type)) {
@@ -3230,6 +3300,10 @@
                 }
                 *out = Interactive(body, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Expression_type)) {
@@ -3249,6 +3323,10 @@
                 }
                 *out = Expression(body, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Suite_type)) {
@@ -3281,6 +3359,10 @@
                 }
                 *out = Suite(body, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
 
@@ -3411,6 +3493,10 @@
                 *out = FunctionDef(name, args, body, decorator_list, lineno,
                                    col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)ClassDef_type)) {
@@ -3509,6 +3595,10 @@
                 *out = ClassDef(name, bases, body, decorator_list, lineno,
                                 col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Return_type)) {
@@ -3527,6 +3617,10 @@
                 }
                 *out = Return(value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Delete_type)) {
@@ -3559,6 +3653,10 @@
                 }
                 *out = Delete(targets, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Assign_type)) {
@@ -3604,6 +3702,10 @@
                 }
                 *out = Assign(targets, value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)AugAssign_type)) {
@@ -3649,6 +3751,10 @@
                 }
                 *out = AugAssign(target, op, value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Print_type)) {
@@ -3706,6 +3812,10 @@
                 }
                 *out = Print(dest, values, nl, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)For_type)) {
@@ -3791,6 +3901,10 @@
                 *out = For(target, iter, body, orelse, lineno, col_offset,
                            arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)While_type)) {
@@ -3862,6 +3976,10 @@
                 }
                 *out = While(test, body, orelse, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)If_type)) {
@@ -3933,6 +4051,10 @@
                 }
                 *out = If(test, body, orelse, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)With_type)) {
@@ -3991,6 +4113,10 @@
                 *out = With(context_expr, optional_vars, body, lineno,
                             col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Raise_type)) {
@@ -4033,6 +4159,10 @@
                 }
                 *out = Raise(type, inst, tback, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)TryExcept_type)) {
@@ -4118,6 +4248,10 @@
                 *out = TryExcept(body, handlers, orelse, lineno, col_offset,
                                  arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)TryFinally_type)) {
@@ -4176,6 +4310,10 @@
                 }
                 *out = TryFinally(body, finalbody, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Assert_type)) {
@@ -4207,6 +4345,10 @@
                 }
                 *out = Assert(test, msg, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Import_type)) {
@@ -4239,6 +4381,10 @@
                 }
                 *out = Import(names, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)ImportFrom_type)) {
@@ -4297,6 +4443,10 @@
                 *out = ImportFrom(module, names, level, lineno, col_offset,
                                   arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Exec_type)) {
@@ -4340,6 +4490,10 @@
                 }
                 *out = Exec(body, globals, locals, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Global_type)) {
@@ -4372,6 +4526,10 @@
                 }
                 *out = Global(names, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Expr_type)) {
@@ -4391,24 +4549,40 @@
                 }
                 *out = Expr(value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Pass_type)) {
 
                 *out = Pass(lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Break_type)) {
 
                 *out = Break(lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Continue_type)) {
 
                 *out = Continue(lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
 
@@ -4499,6 +4673,10 @@
                 }
                 *out = BoolOp(op, values, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)BinOp_type)) {
@@ -4544,6 +4722,10 @@
                 }
                 *out = BinOp(left, op, right, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)UnaryOp_type)) {
@@ -4576,6 +4758,10 @@
                 }
                 *out = UnaryOp(op, operand, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Lambda_type)) {
@@ -4608,6 +4794,10 @@
                 }
                 *out = Lambda(args, body, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)IfExp_type)) {
@@ -4653,6 +4843,10 @@
                 }
                 *out = IfExp(test, body, orelse, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Dict_type)) {
@@ -4711,6 +4905,10 @@
                 }
                 *out = Dict(keys, values, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)ListComp_type)) {
@@ -4756,6 +4954,10 @@
                 }
                 *out = ListComp(elt, generators, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)GeneratorExp_type)) {
@@ -4801,6 +5003,10 @@
                 }
                 *out = GeneratorExp(elt, generators, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Yield_type)) {
@@ -4819,6 +5025,10 @@
                 }
                 *out = Yield(value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Compare_type)) {
@@ -4891,6 +5101,10 @@
                 *out = Compare(left, ops, comparators, lineno, col_offset,
                                arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Call_type)) {
@@ -4987,6 +5201,10 @@
                 *out = Call(func, args, keywords, starargs, kwargs, lineno,
                             col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Repr_type)) {
@@ -5006,6 +5224,10 @@
                 }
                 *out = Repr(value, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Num_type)) {
@@ -5025,6 +5247,10 @@
                 }
                 *out = Num(n, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Str_type)) {
@@ -5044,6 +5270,10 @@
                 }
                 *out = Str(s, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Attribute_type)) {
@@ -5089,6 +5319,10 @@
                 }
                 *out = Attribute(value, attr, ctx, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Subscript_type)) {
@@ -5134,6 +5368,10 @@
                 }
                 *out = Subscript(value, slice, ctx, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Name_type)) {
@@ -5166,6 +5404,10 @@
                 }
                 *out = Name(id, ctx, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)List_type)) {
@@ -5211,6 +5453,10 @@
                 }
                 *out = List(elts, ctx, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Tuple_type)) {
@@ -5256,6 +5502,10 @@
                 }
                 *out = Tuple(elts, ctx, lineno, col_offset, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
 
@@ -5319,6 +5569,10 @@
 
                 *out = Ellipsis(arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Slice_type)) {
@@ -5361,6 +5615,10 @@
                 }
                 *out = Slice(lower, upper, step, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)ExtSlice_type)) {
@@ -5393,6 +5651,10 @@
                 }
                 *out = ExtSlice(dims, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
         if (PyObject_IsInstance(obj, (PyObject*)Index_type)) {
@@ -5412,6 +5674,10 @@
                 }
                 *out = Index(value, arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
 
@@ -5746,6 +6012,10 @@
                 *out = ExceptHandler(type, name, body, lineno, col_offset,
                                      arena);
                 if (*out == NULL) goto failed;
+                (*out)->annotations = PyObject_GetAttrString(obj,
+                 "annotations");
+                if ((*out)->annotations == NULL)
+                        PyErr_Clear();
                 return 0;
         }
 

Modified: python/branches/tlee-ast-optimize/Python/compile.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/compile.c	(original)
+++ python/branches/tlee-ast-optimize/Python/compile.c	Sun May  4 18:57:45 2008
@@ -2831,6 +2831,11 @@
 			   return ! Py_OptimizeFlag;
 		/* fall through */
 	default:
+        if (e->annotations != NULL) {
+            PyObject* constant = PyDict_GetItemString(e->annotations, "const");
+            if (constant != NULL)
+                return PyObject_IsTrue(constant);
+        }
 		return -1;
 	}
 }
@@ -2972,6 +2977,16 @@
 		c->u->u_lineno = e->lineno;
 		c->u->u_lineno_set = false;
 	}
+
+    /* if the expression is annotated with a constant value, use that instead */
+    if (e->annotations != NULL) {
+        PyObject* constant = PyDict_GetItemString(e->annotations, "const");
+        if (constant != NULL) {
+            ADDOP_O(c, LOAD_CONST, constant, consts);
+            return 1;
+        }
+    }
+
 	switch (e->kind) {
 	case BoolOp_kind:
 		return compiler_boolop(c, e);
@@ -3580,7 +3595,9 @@
 	d_lineno = i->i_lineno - a->a_lineno;
 
 	assert(d_bytecode >= 0);
-	assert(d_lineno >= 0);
+#if 0
+	 assert(d_lineno >= 0);
+#endif
 
 	if(d_bytecode == 0 && d_lineno == 0)
 		return 1;

Modified: python/branches/tlee-ast-optimize/Python/optimize.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/optimize.c	(original)
+++ python/branches/tlee-ast-optimize/Python/optimize.c	Sun May  4 18:57:45 2008
@@ -14,111 +14,51 @@
 static int optimize_slice(slice_ty* slice_ptr, PyArena* arena);
 
 /**
- * Determine the constant value of a given expression. It's assumed that
- * constants have been folded.
+ * Annotate a constant expression with its value.
  */
-static PyObject*
-_expr_constant_value(expr_ty expr)
+static int
+_annotate_constant(expr_ty expr, PyObject* v, PyArena* arena)
 {
-    if (expr->kind == Str_kind) {
-        return expr->v.Str.s;
-    }
-    else if (expr->kind == Num_kind) {
-        return expr->v.Num.n;
-    }
-    else if (expr->kind == Name_kind) {
-        const char* name = PyString_AS_STRING(expr->v.Name.id);
-        if (strcmp(name, "True") == 0)
-            return Py_True;
-        else if (strcmp(name, "False") == 0)
-            return Py_False;
-        else if (strcmp(name, "None") == 0)
-            return Py_None;
+    if (expr->annotations == NULL) {
+        expr->annotations = PyDict_New();
+        if (expr->annotations == NULL)
+            return 0;
+        if (PyArena_AddPyObject(arena, expr->annotations) == -1)
+            return 0;
     }
-    return NULL;
-}
 
-/**
- * Determine whether or not the given expression represents a constant value.
- * This makes the assumption that constants have already been folded.
- */
-static int
-_expr_is_constant(expr_ty expr)
-{
-    return _expr_constant_value(expr) != NULL;
-}
+    if (PyDict_SetItemString(expr->annotations, "const", v) == -1)
+        return 0;
 
-/*
- * builds a Name() node with a Load context from the given id.
- */
-static expr_ty
-_make_name(PyObject* id, int lineno, int col_offset, PyArena* arena)
-{
-    expr_ty expr;
-    if (id == NULL)
-        return NULL;
-    expr = Name(id, Load, lineno, col_offset, arena);
-    if (expr == NULL)
-        return NULL;
-    return expr;
+    return 1;
 }
 
 /**
- * Builds an expr from the given constant value. Constant values can be
- * any Str or Num, or any one of True/False/None.
+ * Determine the constant value of a given expression. It's assumed that
+ * constants have been folded.
  */
-static expr_ty
-_expr_from_object(PyObject* object, int lineno, int col_offset, PyArena* arena)
+static PyObject*
+_expr_constant_value(expr_ty expr)
 {
-    expr_ty expr = NULL;
-
-    if (PyString_Check(object) || PyUnicode_Check(object)) {
-        Py_INCREF(object);
-        expr = Str(object, lineno, col_offset, arena);
-    }
-    else if (PyNumber_Check(object)) {
-        Py_INCREF(object);
-        expr = Num(object, lineno, col_offset, arena);
-    }
-    else if (object == Py_None) {
-        object = PyString_FromString("None");
-        expr = _make_name(object, lineno, col_offset, arena);
-    }
-    else if (object == Py_True) {
-        object = PyString_FromString("True");
-        expr = _make_name(object, lineno, col_offset, arena);
+    PyObject* obj;
+    
+    if (expr->kind == Str_kind) {
+        return expr->v.Str.s;
     }
-    else if (object == Py_False) {
-        object = PyString_FromString("False");
-        expr = _make_name(object, lineno, col_offset, arena);
+    else if (expr->kind == Num_kind) {
+        return expr->v.Num.n;
     }
     else {
-        PyErr_Format(PyExc_TypeError, "unknown constant value");
-        return NULL;
-    }
-
-    if (expr == NULL)
-        return NULL;
+        if (expr->annotations == NULL)
+            return NULL;
 
-    if (PyArena_AddPyObject(arena, object) == -1) {
-        /* exception will be set in PyArena_AddPyObject */
-        Py_DECREF(object);
-        return NULL;
-    }
+        obj = PyDict_GetItemString(expr->annotations, "const");
 
-    /* PyArena_AddPyObject decrements the refcount for us */
-    return expr;
-}
+        if (obj == NULL)
+            PyErr_Clear();
 
-/**
- * Returns 1 if the given expression evaluates to a true value. Otherwise,
- * returns 0. This function assumes that the given expr is constant.
- */
-static int
-_expr_is_true(expr_ty expr)
-{
-    assert(_expr_is_constant(expr));
-    return PyObject_IsTrue(_expr_constant_value(expr));
+        return obj;
+    }
 }
 
 /**
@@ -181,17 +121,13 @@
 _asdl_seq_replace_with_pass(asdl_seq* seq, int n, int lineno, int col_offset, PyArena* arena)
 {
     stmt_ty pass;
-    asdl_seq* new;
 
     pass = Pass(lineno, col_offset, arena);
     if (pass == NULL)
         return NULL;
-    new = asdl_seq_new(1, arena);
-    if (new == NULL)
-        return NULL;
-    asdl_seq_SET(new, 0, pass);
-    
-    return _asdl_seq_replace(seq, n, new, arena);
+    asdl_seq_SET(seq, n, pass);
+
+    return seq;
 }
 
 /**
@@ -203,14 +139,17 @@
     int n;
     asdl_seq* seq = *seq_ptr;
     for (n = 0; n < asdl_seq_LEN(seq); n++) {
-        stmt_ty stmt = asdl_seq_GET(seq, n);
+        stmt_ty stmt;
         if (!optimize_stmt((stmt_ty*)&asdl_seq_GET(seq, n), arena))
             return 0;
 
+        stmt = asdl_seq_GET(seq, n);
+
         if (stmt->kind == If_kind) {
+            PyObject* test = _expr_constant_value(stmt->v.If.test);
             /* eliminate branches that can never be reached */
-            if (_expr_is_constant(stmt->v.If.test)) {
-                if (_expr_is_true(stmt->v.If.test))
+            if (test != NULL) {
+                if (PyObject_IsTrue(test))
                     seq = _asdl_seq_replace(seq, n, stmt->v.If.body, arena);
                 else {
                     if (stmt->v.If.orelse == NULL) {
@@ -228,7 +167,7 @@
                 *seq_ptr = seq;
             }
         }
-        else if (stmt->kind == Return_kind) {
+        else if (stmt->kind == Return_kind && n < (asdl_seq_LEN(seq) - 1)) {
             /* eliminate all nodes after a return */
             seq = _asdl_seq_replace_with_pass(seq, n + 1,
                     stmt->lineno, stmt->col_offset, arena);
@@ -458,14 +397,13 @@
             return 1;
         }
         
-        expr = _expr_from_object(res, expr->lineno, expr->col_offset, arena);
-        if (expr == NULL) {
+        if (!_annotate_constant(expr, res, arena)) {
             Py_DECREF(res);
             return 0;
         }
-        *expr_ptr = expr;
 
-        Py_DECREF(res);
+        /* XXX: is this necessary? */
+        /* Py_DECREF(res); */
     }
 
     return 1;
@@ -474,20 +412,14 @@
 static int
 optimize_unary_op(expr_ty* expr_ptr, PyArena* arena)
 {
+    PyObject* operand;
     expr_ty expr = *expr_ptr;
     if (!optimize_expr(&expr->v.UnaryOp.operand, arena))
         return 0;
-    if (_expr_is_constant(expr->v.UnaryOp.operand)) {
-        PyObject* operand;
-        PyObject* res;
 
-        operand = _expr_constant_value(expr->v.UnaryOp.operand);
-        if (operand == NULL) {
-            /* XXX this should never happen ... */
-            PyErr_Format(PyExc_ValueError, "unknown constant type: %d",
-                    expr->v.UnaryOp.operand->kind);
-            return 0;
-        }
+    operand = _expr_constant_value(expr->v.UnaryOp.operand);
+    if (operand != NULL) {
+        PyObject* res;
 
         switch (expr->v.UnaryOp.op) {
             case Invert:
@@ -533,14 +465,13 @@
             return 1;
         }
 
-        expr = _expr_from_object(res, expr->lineno, expr->col_offset, arena);
-        if (!expr) {
+        if (!_annotate_constant(expr, res, arena)) {
             Py_DECREF(res);
             return 0;
         }
-        *expr_ptr = expr;
 
-        Py_DECREF(res);
+        /* XXX: is this necessary? */
+        /* Py_DECREF(res); */
     }
     return 1;
 }
@@ -747,6 +678,50 @@
     return 1;
 }
 
+static PyObject*
+_make_constant_tuple(asdl_seq* values, PyArena* arena)
+{
+    expr_ty expr;
+    int i;
+    PyObject* tuple;
+    
+    tuple = PyTuple_New(asdl_seq_LEN(values));
+    if (tuple == NULL)
+        return NULL;
+
+    if (PyArena_AddPyObject(arena, tuple) == -1) {
+        Py_DECREF(tuple);
+        return NULL;
+    }
+
+    /* don't *think* we need to add the constant values to the arena */
+    for (i = 0; i < asdl_seq_LEN(values); i++) {
+        PyObject* value;
+        expr = (expr_ty)asdl_seq_GET(values, i);
+        value = _expr_constant_value(expr);
+        Py_INCREF(value);
+        if (PyTuple_SetItem(tuple, i, value) == -1)
+            return NULL;
+    }
+
+    return tuple;
+}
+
+static int
+_is_constant_seq(asdl_seq* values)
+{
+    expr_ty expr;
+    int i;
+
+    for (i = 0; i < asdl_seq_LEN(values); i++) {
+        expr = (expr_ty)asdl_seq_GET(values, i);
+        if (_expr_constant_value(expr) == NULL)
+            return 0;
+    }
+
+    return 1;
+}
+
 static int
 optimize_expr(expr_ty* expr_ptr, PyArena* arena)
 {
@@ -810,21 +785,56 @@
             }
         case List_kind:
             {
+                /* TODO: optimize lists used in "in"/"not in" as per original
+                 *       peephole optimization code */
                 return optimize_expr_seq(&expr->v.List.elts, arena);
             }
         case Tuple_kind:
             {
-                return optimize_expr_seq(&expr->v.Tuple.elts, arena);
+                if (!optimize_expr_seq(&expr->v.Tuple.elts, arena))
+                    return 0;
+                
+                if (_is_constant_seq(expr->v.Tuple.elts)) {
+                    PyObject* value = _make_constant_tuple(expr->v.Tuple.elts,
+                                                            arena);
+                    if (value == NULL)
+                        return 0;
+                    if (!_annotate_constant(expr, value, arena))
+                        return 0;
+                }
+
+                return 1;
             }
         case Num_kind:
         case Str_kind:
+            {
+                return 1;
+            }
         case Name_kind:
             {
+                PyObject* v;
+                const char* id;
+                
+                id = PyString_AS_STRING(expr->v.Name.id);
+                v  = NULL;
+
+                if (strcmp(id, "None") == 0)
+                    v = Py_None;
+                else if (strcmp(id, "True") == 0)
+                    v = Py_True;
+                else if (strcmp(id, "False") == 0)
+                    v = Py_False;
+
+                if (v != NULL) {
+                    if (!_annotate_constant(expr, v, arena))
+                        return 0;
+                }
+
                 return 1;
             }
         default:
             PyErr_Format(PyExc_ValueError, "unknown expr_ty kind: %d",
-                    expr->kind);
+                            expr->kind);
             return 0;
     }
 }
@@ -925,6 +935,16 @@
         return 0;
     if (!optimize_expr(&stmt->v.For.iter, arena))
         return 0;
+    if (stmt->v.For.iter->kind == List_kind) {
+        if (_is_constant_seq(stmt->v.For.iter->v.List.elts)) {
+            PyObject* constant = _make_constant_tuple(
+                    stmt->v.For.iter->v.List.elts, arena);
+            if (constant == NULL)
+                return 0;
+            if (!_annotate_constant(stmt->v.For.iter, constant, arena))
+                return 0;
+        }
+    }
     if (!optimize_stmt_seq(&stmt->v.For.body, arena))
         return 0;
     if (!optimize_stmt_seq(&stmt->v.For.orelse, arena))
@@ -1204,6 +1224,8 @@
 int
 PyAST_Optimize(mod_ty* mod_ptr, PyArena* arena)
 {
-    return optimize_mod(mod_ptr, arena);
+    int res;
+    res = optimize_mod(mod_ptr, arena);
+    return res;
 }
 

Modified: python/branches/tlee-ast-optimize/Python/peephole.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/peephole.c	(original)
+++ python/branches/tlee-ast-optimize/Python/peephole.c	Sun May  4 18:57:45 2008
@@ -201,34 +201,11 @@
 				codestr[i+3] = NOP;
 				break;
 
-				/* Replace LOAD_GLOBAL/LOAD_NAME None
-                                   with LOAD_CONST None */
-			case LOAD_NAME:
-			case LOAD_GLOBAL:
-				j = GETARG(codestr, i);
-				name = PyString_AsString(PyTuple_GET_ITEM(names, j));
-				if (name == NULL  ||  strcmp(name, "None") != 0)
-					continue;
-				for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) {
-					if (PyList_GET_ITEM(consts, j) == Py_None)
-						break;
-				}
-				if (j == PyList_GET_SIZE(consts)) {
-					if (PyList_Append(consts, Py_None) == -1)
-					        goto exitUnchanged;                                        
-				}
-				assert(PyList_GET_ITEM(consts, j) == Py_None);
-				codestr[i] = LOAD_CONST;
-				SETARG(codestr, i, j);
-				cumlc = lastlc + 1;
-				break;
-
 				/* Try to fold tuples of constants (includes a case for lists
 				   which are only used for "in" and "not in" tests).
 				   Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
 				   Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
 				   Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
-			case BUILD_TUPLE:
 			case BUILD_LIST:
 				j = GETARG(codestr, i);
 				h = i - 3 * j;


More information about the Python-checkins mailing list