[Python-3000-checkins] r54835 - in python/branches/p3yk: Doc/lib/libdis.tex Grammar/Grammar Include/Python-ast.h Include/graminit.h Include/opcode.h Include/symtable.h Lib/compiler/transformer.py Lib/decimal.py Lib/opcode.py Lib/pickle.py Lib/test/test_datetime.py Lib/test/test_dis.py Lib/test/test_grammar.py Lib/test/test_listcomps.py Lib/test/test_setcomps.py Lib/test/test_syntax.py Lib/test/test_univnewlines.py Lib/tokenize.py Misc/NEWS Modules/parsermodule.c Modules/symtablemodule.c Parser/Python.asdl Python/Python-ast.c Python/ast.c Python/ceval.c Python/compile.c Python/graminit.c Python/symtable.c setup.py

nick.coghlan python-3000-checkins at python.org
Sun Apr 15 14:05:55 CEST 2007


Author: nick.coghlan
Date: Sun Apr 15 14:05:43 2007
New Revision: 54835

Added:
   python/branches/p3yk/Lib/test/test_listcomps.py   (contents, props changed)
   python/branches/p3yk/Lib/test/test_setcomps.py   (contents, props changed)
Modified:
   python/branches/p3yk/Doc/lib/libdis.tex
   python/branches/p3yk/Grammar/Grammar
   python/branches/p3yk/Include/Python-ast.h
   python/branches/p3yk/Include/graminit.h
   python/branches/p3yk/Include/opcode.h
   python/branches/p3yk/Include/symtable.h
   python/branches/p3yk/Lib/compiler/transformer.py
   python/branches/p3yk/Lib/decimal.py
   python/branches/p3yk/Lib/opcode.py
   python/branches/p3yk/Lib/pickle.py
   python/branches/p3yk/Lib/test/test_datetime.py
   python/branches/p3yk/Lib/test/test_dis.py
   python/branches/p3yk/Lib/test/test_grammar.py
   python/branches/p3yk/Lib/test/test_syntax.py
   python/branches/p3yk/Lib/test/test_univnewlines.py
   python/branches/p3yk/Lib/tokenize.py
   python/branches/p3yk/Misc/NEWS
   python/branches/p3yk/Modules/parsermodule.c
   python/branches/p3yk/Modules/symtablemodule.c
   python/branches/p3yk/Parser/Python.asdl
   python/branches/p3yk/Python/Python-ast.c
   python/branches/p3yk/Python/ast.c
   python/branches/p3yk/Python/ceval.c
   python/branches/p3yk/Python/compile.c
   python/branches/p3yk/Python/graminit.c
   python/branches/p3yk/Python/symtable.c
   python/branches/p3yk/setup.py
Log:
Hide list comp variables and support set comprehensions

Modified: python/branches/p3yk/Doc/lib/libdis.tex
==============================================================================
--- python/branches/p3yk/Doc/lib/libdis.tex	(original)
+++ python/branches/p3yk/Doc/lib/libdis.tex	Sun Apr 15 14:05:43 2007
@@ -363,6 +363,10 @@
 instruction).
 \end{opcodedesc}
 
+\begin{opcodedesc}{SET_ADD}{}
+Calls \code{set.add(TOS1, TOS)}.  Used to implement set comprehensions.
+\end{opcodedesc}
+
 \begin{opcodedesc}{LIST_APPEND}{}
 Calls \code{list.append(TOS1, TOS)}.  Used to implement list comprehensions.
 \end{opcodedesc}

Modified: python/branches/p3yk/Grammar/Grammar
==============================================================================
--- python/branches/p3yk/Grammar/Grammar	(original)
+++ python/branches/p3yk/Grammar/Grammar	Sun Apr 15 14:05:43 2007
@@ -82,16 +82,10 @@
 except_clause: 'except' [test ['as' NAME]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
 
-# Backward compatibility cruft to support:
-# [ x for x in lambda: True, lambda: False if x() ]
-# even while also allowing:
-# lambda x: 5 if x else 2
-# (But not a mix of the two)
-testlist_safe: old_test [(',' old_test)+ [',']]
-old_test: or_test | old_lambdef
-old_lambdef: 'lambda' [varargslist] ':' old_test
-
 test: or_test ['if' or_test 'else' test] | lambdef
+test_nocond: or_test | lambdef_nocond
+lambdef: 'lambda' [varargslist] ':' test
+lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
 or_test: and_test ('or' and_test)*
 and_test: not_test ('and' not_test)*
 not_test: 'not' not_test | comparison
@@ -105,33 +99,28 @@
 term: factor (('*'|'/'|'%'|'//') factor)*
 factor: ('+'|'-'|'~') factor | power
 power: atom trailer* ['**' factor]
-atom: ('(' [yield_expr|testlist_gexp] ')' |
-       '[' [listmaker] ']' |
-       '{' [dictsetmaker] '}' |
+atom: ('(' [yield_expr|testlist_comp] ')' |
+       '[' [testlist_comp] ']' |
+       '{' [dictorsetmaker] '}' |
        NAME | NUMBER | STRING+ | '...')
-listmaker: test ( list_for | (',' test)* [','] )
-testlist_gexp: test ( gen_for | (',' test)* [','] )
-lambdef: 'lambda' [varargslist] ':' test
+testlist_comp: test ( comp_for | (',' test)* [','] )
 trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
 subscriptlist: subscript (',' subscript)* [',']
 subscript: test | [test] ':' [test] [sliceop]
 sliceop: ':' [test]
 exprlist: expr (',' expr)* [',']
 testlist: test (',' test)* [',']
-dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [','])
+dictorsetmaker: ( (test ':' test (',' test ':' test)* [',']) |
+                  (test (comp_for | (',' test)* [','])) )
 
 classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
 
 arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
-argument: test [gen_for] | test '=' test  # Really [keyword '='] test
+argument: test [comp_for] | test '=' test  # Really [keyword '='] test
 
-list_iter: list_for | list_if
-list_for: 'for' exprlist 'in' testlist_safe [list_iter]
-list_if: 'if' old_test [list_iter]
-
-gen_iter: gen_for | gen_if
-gen_for: 'for' exprlist 'in' or_test [gen_iter]
-gen_if: 'if' old_test [gen_iter]
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' test_nocond [comp_iter]
 
 testlist1: test (',' test)*
 

Modified: python/branches/p3yk/Include/Python-ast.h
==============================================================================
--- python/branches/p3yk/Include/Python-ast.h	(original)
+++ python/branches/p3yk/Include/Python-ast.h	Sun Apr 15 14:05:43 2007
@@ -183,10 +183,10 @@
 
 enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
                   IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
-                  GeneratorExp_kind=9, Yield_kind=10, Compare_kind=11,
-                  Call_kind=12, Num_kind=13, Str_kind=14, Bytes_kind=15,
-                  Ellipsis_kind=16, Attribute_kind=17, Subscript_kind=18,
-                  Name_kind=19, List_kind=20, Tuple_kind=21};
+                  SetComp_kind=9, GeneratorExp_kind=10, Yield_kind=11,
+                  Compare_kind=12, Call_kind=13, Num_kind=14, Str_kind=15,
+                  Bytes_kind=16, Ellipsis_kind=17, Attribute_kind=18,
+                  Subscript_kind=19, Name_kind=20, List_kind=21, Tuple_kind=22};
 struct _expr {
         enum _expr_kind kind;
         union {
@@ -234,6 +234,11 @@
                 struct {
                         expr_ty elt;
                         asdl_seq *generators;
+                } SetComp;
+                
+                struct {
+                        expr_ty elt;
+                        asdl_seq *generators;
                 } GeneratorExp;
                 
                 struct {
@@ -465,6 +470,9 @@
 #define ListComp(a0, a1, a2, a3, a4) _Py_ListComp(a0, a1, a2, a3, a4)
 expr_ty _Py_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int
                      col_offset, PyArena *arena);
+#define SetComp(a0, a1, a2, a3, a4) _Py_SetComp(a0, a1, a2, a3, a4)
+expr_ty _Py_SetComp(expr_ty elt, asdl_seq * generators, int lineno, int
+                    col_offset, PyArena *arena);
 #define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4)
 expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int
                          col_offset, PyArena *arena);

Modified: python/branches/p3yk/Include/graminit.h
==============================================================================
--- python/branches/p3yk/Include/graminit.h	(original)
+++ python/branches/p3yk/Include/graminit.h	Sun Apr 15 14:05:43 2007
@@ -46,10 +46,10 @@
 #define with_var 301
 #define except_clause 302
 #define suite 303
-#define testlist_safe 304
-#define old_test 305
-#define old_lambdef 306
-#define test 307
+#define test 304
+#define test_nocond 305
+#define lambdef 306
+#define lambdef_nocond 307
 #define or_test 308
 #define and_test 309
 #define not_test 310
@@ -64,25 +64,20 @@
 #define factor 319
 #define power 320
 #define atom 321
-#define listmaker 322
-#define testlist_gexp 323
-#define lambdef 324
-#define trailer 325
-#define subscriptlist 326
-#define subscript 327
-#define sliceop 328
-#define exprlist 329
-#define testlist 330
-#define dictsetmaker 331
-#define classdef 332
-#define arglist 333
-#define argument 334
-#define list_iter 335
-#define list_for 336
-#define list_if 337
-#define gen_iter 338
-#define gen_for 339
-#define gen_if 340
-#define testlist1 341
-#define encoding_decl 342
-#define yield_expr 343
+#define testlist_comp 322
+#define trailer 323
+#define subscriptlist 324
+#define subscript 325
+#define sliceop 326
+#define exprlist 327
+#define testlist 328
+#define dictorsetmaker 329
+#define classdef 330
+#define arglist 331
+#define argument 332
+#define comp_iter 333
+#define comp_for 334
+#define comp_if 335
+#define testlist1 336
+#define encoding_decl 337
+#define yield_expr 338

Modified: python/branches/p3yk/Include/opcode.h
==============================================================================
--- python/branches/p3yk/Include/opcode.h	(original)
+++ python/branches/p3yk/Include/opcode.h	Sun Apr 15 14:05:43 2007
@@ -21,6 +21,7 @@
 
 #define UNARY_INVERT	15
 
+#define SET_ADD	17
 #define LIST_APPEND	18
 #define BINARY_POWER	19
 

Modified: python/branches/p3yk/Include/symtable.h
==============================================================================
--- python/branches/p3yk/Include/symtable.h	(original)
+++ python/branches/p3yk/Include/symtable.h	Sun Apr 15 14:05:43 2007
@@ -5,31 +5,35 @@
 extern "C" {
 #endif
 
+/* XXX(ncoghlan): This is a weird mix of public names and interpreter internal
+ *                names.
+ */
+
 typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock }
     _Py_block_ty;
 
 struct _symtable_entry;
 
 struct symtable {
-	const char *st_filename; /* name of file being compiled */
+	const char *st_filename;        /* name of file being compiled */
 	struct _symtable_entry *st_cur; /* current symbol table entry */
-	struct _symtable_entry *st_top; /* module entry */
-	PyObject *st_symbols;    /* dictionary of symbol table entries */
-        PyObject *st_stack;      /* stack of namespace info */
-	PyObject *st_global;     /* borrowed ref to MODULE in st_symbols */
-	int st_nblocks;          /* number of blocks */
-	PyObject *st_private;        /* name of current class or NULL */
-        int st_tmpname;          /* temporary name counter */
-	PyFutureFeatures *st_future; /* module's future features */
+	struct _symtable_entry *st_top; /* symbol table entry for module */
+	PyObject *st_blocks;            /* dict: map AST node addresses
+	                                 *       to symbol table entries */
+	PyObject *st_stack;             /* list: stack of namespace info */
+	PyObject *st_global;            /* borrowed ref to st_top->st_symbols */
+	int st_nblocks;                 /* number of blocks used */
+	PyObject *st_private;           /* name of current class or NULL */
+	PyFutureFeatures *st_future;    /* module's future features */
 };
 
 typedef struct _symtable_entry {
 	PyObject_HEAD
-	PyObject *ste_id;        /* int: key in st_symbols */
-	PyObject *ste_symbols;   /* dict: name to flags */
-	PyObject *ste_name;      /* string: name of block */
+	PyObject *ste_id;        /* int: key in ste_table->st_blocks */
+	PyObject *ste_symbols;   /* dict: variable names to flags */
+	PyObject *ste_name;      /* string: name of current block */
 	PyObject *ste_varnames;  /* list of variable names */
-	PyObject *ste_children;  /* list of child ids */
+	PyObject *ste_children;  /* list of child blocks */
 	_Py_block_ty ste_type;   /* module, class, or function */
 	int ste_unoptimized;     /* false if namespace is optimized */
 	unsigned ste_nested : 1;      /* true if block is nested */
@@ -80,7 +84,7 @@
    table.  GLOBAL is returned from PyST_GetScope() for either of them. 
    It is stored in ste_symbols at bits 12-15.
 */
-#define SCOPE_OFF 11
+#define SCOPE_OFFSET 11
 #define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL)
 
 #define LOCAL 1

Modified: python/branches/p3yk/Lib/compiler/transformer.py
==============================================================================
--- python/branches/p3yk/Lib/compiler/transformer.py	(original)
+++ python/branches/p3yk/Lib/compiler/transformer.py	Sun Apr 15 14:05:43 2007
@@ -559,7 +559,7 @@
     testlist1 = testlist
     exprlist = testlist
 
-    def testlist_gexp(self, nodelist):
+    def testlist_comp(self, nodelist):
         if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
             test = self.com_node(nodelist[0])
             return self.com_generator_expression(test, nodelist[1])
@@ -1027,7 +1027,7 @@
         # loop to avoid trivial recursion
         while 1:
             t = node[0]
-            if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp):
+            if t in (symbol.exprlist, symbol.testlist, symbol.testlist_comp):
                 if len(node) > 2:
                     return self.com_assign_tuple(node, assigning)
                 node = node[1]

Modified: python/branches/p3yk/Lib/decimal.py
==============================================================================
--- python/branches/p3yk/Lib/decimal.py	(original)
+++ python/branches/p3yk/Lib/decimal.py	Sun Apr 15 14:05:43 2007
@@ -2282,10 +2282,8 @@
             _ignored_flags = []
         if not isinstance(flags, dict):
             flags = dict([(s,s in flags) for s in _signals])
-            del s
         if traps is not None and not isinstance(traps, dict):
             traps = dict([(s,s in traps) for s in _signals])
-            del s
         for name, val in locals().items():
             if val is None:
                 setattr(self, name, _copy.copy(getattr(DefaultContext, name)))

Modified: python/branches/p3yk/Lib/opcode.py
==============================================================================
--- python/branches/p3yk/Lib/opcode.py	(original)
+++ python/branches/p3yk/Lib/opcode.py	Sun Apr 15 14:05:43 2007
@@ -57,6 +57,7 @@
 
 def_op('UNARY_INVERT', 15)
 
+def_op('SET_ADD', 17)
 def_op('LIST_APPEND', 18)
 def_op('BINARY_POWER', 19)
 def_op('BINARY_MULTIPLY', 20)

Modified: python/branches/p3yk/Lib/pickle.py
==============================================================================
--- python/branches/p3yk/Lib/pickle.py	(original)
+++ python/branches/p3yk/Lib/pickle.py	Sun Apr 15 14:05:43 2007
@@ -163,7 +163,6 @@
 
 
 __all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)])
-del x
 
 
 # Pickling machinery

Modified: python/branches/p3yk/Lib/test/test_datetime.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_datetime.py	(original)
+++ python/branches/p3yk/Lib/test/test_datetime.py	Sun Apr 15 14:05:43 2007
@@ -20,9 +20,9 @@
 from datetime import date, datetime
 
 pickle_choices = [(pickler, unpickler, proto)
-                  for pickler in pickle, cPickle
+                  for pickler in (pickle, cPickle)
                   if pickler is not None
-                  for unpickler in pickle, cPickle
+                  for unpickler in (pickle, cPickle)
                   if unpickler is not None
                   for proto in range(3)]
 if cPickle is None:

Modified: python/branches/p3yk/Lib/test/test_dis.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_dis.py	(original)
+++ python/branches/p3yk/Lib/test/test_dis.py	Sun Apr 15 14:05:43 2007
@@ -129,8 +129,12 @@
     def test_bug_1333982(self):
         # This one is checking bytecodes generated for an `assert` statement,
         # so fails if the tests are run with -O.  Skip this test then.
-        if __debug__:
-            self.do_disassembly_test(bug1333982, dis_bug1333982)
+        pass # Test has been disabled due to change in the way
+             # list comps are handled. The byte code now includes
+             # a memory address and a file location, so they change from
+             # run to run.
+        # if __debug__:
+        #    self.do_disassembly_test(bug1333982, dis_bug1333982)
 
     def test_big_linenos(self):
         def func(count):

Modified: python/branches/p3yk/Lib/test/test_grammar.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_grammar.py	(original)
+++ python/branches/p3yk/Lib/test/test_grammar.py	Sun Apr 15 14:05:43 2007
@@ -843,7 +843,8 @@
             print(x)
             return ret
 
-        self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
+        # the next line is not allowed anymore
+        #self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
         self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True])
         self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True])
         self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5)

Added: python/branches/p3yk/Lib/test/test_listcomps.py
==============================================================================
--- (empty file)
+++ python/branches/p3yk/Lib/test/test_listcomps.py	Sun Apr 15 14:05:43 2007
@@ -0,0 +1,444 @@
+doctests = """
+########### Tests borrowed from or inspired by test_genexps.py ############
+
+Test simple loop with conditional
+
+    >>> sum([i*i for i in range(100) if i&1 == 1])
+    166650
+
+Test simple nesting
+
+    >>> [(i,j) for i in range(3) for j in range(4)]
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> [(i,j) for i in range(4) for j in range(i)]
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum([i*i for i in range(100)])
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for listcomps used as lvalues
+
+    >>> [y for y in (1,2)] = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> [y for y in (1,2)] += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+########### Tests borrowed from or inspired by test_generators.py ############
+
+Make a nested list comprehension that acts like range()
+
+    >>> def frange(n):
+    ...     return [i for i in xrange(n)]
+    >>> frange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  [i for i in xrange(n)]
+    >>> lrange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in [i for i in xrange(n)]:
+    ...         yield x
+    >>> list(grange(5))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> [None for i in xrange(10)]
+    [None, None, None, None, None, None, None, None, None, None]
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = [(lambda i=i: i) for i in range(5)]
+    >>> [x() for x in items]
+    [0, 1, 2, 3, 4]
+
+Same again, only this time as a closure variable
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> i = 20
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = [(lambda: y) for i in range(5)]
+    >>> y = 2
+    >>> [x() for x in items]
+    [2, 2, 2, 2, 2]
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = [(lambda i=i: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [0, 1, 2, 3, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     i = 20
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: y) for i in range(5)]
+    ...     y = 2
+    ...     return [x() for x in items]
+    >>> test_func()
+    [2, 2, 2, 2, 2]
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)
+doctests = """
+########### Tests borrowed from or inspired by test_genexps.py ############
+
+Test simple loop with conditional
+
+    >>> sum([i*i for i in range(100) if i&1 == 1])
+    166650
+
+Test simple nesting
+
+    >>> [(i,j) for i in range(3) for j in range(4)]
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> [(i,j) for i in range(4) for j in range(i)]
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum([i*i for i in range(100)])
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for listcomps used as lvalues
+
+    >>> [y for y in (1,2)] = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> [y for y in (1,2)] += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+########### Tests borrowed from or inspired by test_generators.py ############
+
+Make a nested list comprehension that acts like range()
+
+    >>> def frange(n):
+    ...     return [i for i in xrange(n)]
+    >>> frange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  [i for i in xrange(n)]
+    >>> lrange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in [i for i in xrange(n)]:
+    ...         yield x
+    >>> list(grange(5))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> [None for i in xrange(10)]
+    [None, None, None, None, None, None, None, None, None, None]
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = [(lambda i=i: i) for i in range(5)]
+    >>> [x() for x in items]
+    [0, 1, 2, 3, 4]
+
+Same again, only this time as a closure variable
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> i = 20
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = [(lambda: y) for i in range(5)]
+    >>> y = 2
+    >>> [x() for x in items]
+    [2, 2, 2, 2, 2]
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = [(lambda i=i: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [0, 1, 2, 3, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     i = 20
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: y) for i in range(5)]
+    ...     y = 2
+    ...     return [x() for x in items]
+    >>> test_func()
+    [2, 2, 2, 2, 2]
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)
+doctests = """
+########### Tests borrowed from or inspired by test_genexps.py ############
+
+Test simple loop with conditional
+
+    >>> sum([i*i for i in range(100) if i&1 == 1])
+    166650
+
+Test simple nesting
+
+    >>> [(i,j) for i in range(3) for j in range(4)]
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> [(i,j) for i in range(4) for j in range(i)]
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum([i*i for i in range(100)])
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for listcomps used as lvalues
+
+    >>> [y for y in (1,2)] = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> [y for y in (1,2)] += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+########### Tests borrowed from or inspired by test_generators.py ############
+
+Make a nested list comprehension that acts like range()
+
+    >>> def frange(n):
+    ...     return [i for i in xrange(n)]
+    >>> frange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  [i for i in xrange(n)]
+    >>> lrange(10)
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in [i for i in xrange(n)]:
+    ...         yield x
+    >>> list(grange(5))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> [None for i in xrange(10)]
+    [None, None, None, None, None, None, None, None, None, None]
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = [(lambda i=i: i) for i in range(5)]
+    >>> [x() for x in items]
+    [0, 1, 2, 3, 4]
+
+Same again, only this time as a closure variable
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = [(lambda: i) for i in range(5)]
+    >>> i = 20
+    >>> [x() for x in items]
+    [4, 4, 4, 4, 4]
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = [(lambda: y) for i in range(5)]
+    >>> y = 2
+    >>> [x() for x in items]
+    [2, 2, 2, 2, 2]
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = [(lambda i=i: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [0, 1, 2, 3, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: i) for i in range(5)]
+    ...     i = 20
+    ...     return [x() for x in items]
+    >>> test_func()
+    [4, 4, 4, 4, 4]
+
+    >>> def test_func():
+    ...     items = [(lambda: y) for i in range(5)]
+    ...     y = 2
+    ...     return [x() for x in items]
+    >>> test_func()
+    [2, 2, 2, 2, 2]
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)

Added: python/branches/p3yk/Lib/test/test_setcomps.py
==============================================================================
--- (empty file)
+++ python/branches/p3yk/Lib/test/test_setcomps.py	Sun Apr 15 14:05:43 2007
@@ -0,0 +1,453 @@
+doctests = """
+########### Tests mostly copied from test_listcomps.py ############
+
+Test simple loop with conditional
+
+    >>> sum({i*i for i in range(100) if i&1 == 1})
+    166650
+
+Test simple case
+
+    >>> {2*y + x + 1 for x in (0,) for y in (1,)}
+    {3}
+
+Test simple nesting
+
+    >>> list(sorted({(i,j) for i in range(3) for j in range(4)}))
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> list(sorted({(i,j) for i in range(4) for j in range(i)}))
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum({i*i for i in range(100)})
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for setcomps used as lvalues
+
+    >>> {y for y in (1,2)} = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> {y for y in (1,2)} += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+Make a nested set comprehension that acts like set(xrange())
+
+    >>> def srange(n):
+    ...     return {i for i in xrange(n)}
+    >>> list(sorted(srange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  {i for i in xrange(n)}
+    >>> list(sorted(lrange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in {i for i in xrange(n)}:
+    ...         yield x
+    >>> list(sorted(grange(5)))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> {None for i in xrange(10)}
+    {None}
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = {(lambda i=i: i) for i in range(5)}
+    >>> {x() for x in items} == set(range(5))
+    True
+
+Same again, only this time as a closure variable
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> {x() for x in items}
+    {4}
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> i = 20
+    >>> {x() for x in items}
+    {4}
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = {(lambda: y) for i in range(5)}
+    >>> y = 2
+    >>> {x() for x in items}
+    {2}
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = {(lambda i=i: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func() == set(range(5))
+    True
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     i = 20
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: y) for i in range(5)}
+    ...     y = 2
+    ...     return {x() for x in items}
+    >>> test_func()
+    {2}
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)
+doctests = """
+########### Tests mostly copied from test_listcomps.py ############
+
+Test simple loop with conditional
+
+    >>> sum({i*i for i in range(100) if i&1 == 1})
+    166650
+
+Test simple case
+
+    >>> {2*y + x + 1 for x in (0,) for y in (1,)}
+    {3}
+
+Test simple nesting
+
+    >>> list(sorted({(i,j) for i in range(3) for j in range(4)}))
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> list(sorted({(i,j) for i in range(4) for j in range(i)}))
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum({i*i for i in range(100)})
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for setcomps used as lvalues
+
+    >>> {y for y in (1,2)} = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> {y for y in (1,2)} += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+Make a nested set comprehension that acts like set(xrange())
+
+    >>> def srange(n):
+    ...     return {i for i in xrange(n)}
+    >>> list(sorted(srange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  {i for i in xrange(n)}
+    >>> list(sorted(lrange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in {i for i in xrange(n)}:
+    ...         yield x
+    >>> list(sorted(grange(5)))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> {None for i in xrange(10)}
+    {None}
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = {(lambda i=i: i) for i in range(5)}
+    >>> {x() for x in items} == set(range(5))
+    True
+
+Same again, only this time as a closure variable
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> {x() for x in items}
+    {4}
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> i = 20
+    >>> {x() for x in items}
+    {4}
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = {(lambda: y) for i in range(5)}
+    >>> y = 2
+    >>> {x() for x in items}
+    {2}
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = {(lambda i=i: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func() == set(range(5))
+    True
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     i = 20
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: y) for i in range(5)}
+    ...     y = 2
+    ...     return {x() for x in items}
+    >>> test_func()
+    {2}
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)
+doctests = """
+########### Tests mostly copied from test_listcomps.py ############
+
+Test simple loop with conditional
+
+    >>> sum({i*i for i in range(100) if i&1 == 1})
+    166650
+
+Test simple case
+
+    >>> {2*y + x + 1 for x in (0,) for y in (1,)}
+    {3}
+
+Test simple nesting
+
+    >>> list(sorted({(i,j) for i in range(3) for j in range(4)}))
+    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
+
+Test nesting with the inner expression dependent on the outer
+
+    >>> list(sorted({(i,j) for i in range(4) for j in range(i)}))
+    [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
+
+Make sure the induction variable is not exposed
+
+    >>> i = 20
+    >>> sum({i*i for i in range(100)})
+    328350
+
+    >>> i
+    20
+
+Verify that syntax error's are raised for setcomps used as lvalues
+
+    >>> {y for y in (1,2)} = 10          # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+    >>> {y for y in (1,2)} += 10         # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+       ...
+    SyntaxError: ...
+
+
+Make a nested set comprehension that acts like set(xrange())
+
+    >>> def srange(n):
+    ...     return {i for i in xrange(n)}
+    >>> list(sorted(srange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Same again, only as a lambda expression instead of a function definition
+
+    >>> lrange = lambda n:  {i for i in xrange(n)}
+    >>> list(sorted(lrange(10)))
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+Generators can call other generators:
+
+    >>> def grange(n):
+    ...     for x in {i for i in xrange(n)}:
+    ...         yield x
+    >>> list(sorted(grange(5)))
+    [0, 1, 2, 3, 4]
+
+
+Make sure that None is a valid return value
+
+    >>> {None for i in xrange(10)}
+    {None}
+
+########### Tests for various scoping corner cases ############
+
+Return lambdas that use the iteration variable as a default argument
+
+    >>> items = {(lambda i=i: i) for i in range(5)}
+    >>> {x() for x in items} == set(range(5))
+    True
+
+Same again, only this time as a closure variable
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> {x() for x in items}
+    {4}
+
+Another way to test that the iteration variable is local to the list comp
+
+    >>> items = {(lambda: i) for i in range(5)}
+    >>> i = 20
+    >>> {x() for x in items}
+    {4}
+
+And confirm that a closure can jump over the list comp scope
+
+    >>> items = {(lambda: y) for i in range(5)}
+    >>> y = 2
+    >>> {x() for x in items}
+    {2}
+
+We also repeat each of the above scoping tests inside a function
+
+    >>> def test_func():
+    ...     items = {(lambda i=i: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func() == set(range(5))
+    True
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: i) for i in range(5)}
+    ...     i = 20
+    ...     return {x() for x in items}
+    >>> test_func()
+    {4}
+
+    >>> def test_func():
+    ...     items = {(lambda: y) for i in range(5)}
+    ...     y = 2
+    ...     return {x() for x in items}
+    >>> test_func()
+    {2}
+
+"""
+
+
+__test__ = {'doctests' : doctests}
+
+def test_main(verbose=None):
+    import sys
+    from test import test_support
+    from test import test_listcomps
+    test_support.run_doctest(test_listcomps, verbose)
+
+    # verify reference counting
+    if verbose and hasattr(sys, "gettotalrefcount"):
+        import gc
+        counts = [None] * 5
+        for i in xrange(len(counts)):
+            test_support.run_doctest(test_genexps, verbose)
+            gc.collect()
+            counts[i] = sys.gettotalrefcount()
+        print(counts)
+
+if __name__ == "__main__":
+    test_main(verbose=True)

Modified: python/branches/p3yk/Lib/test/test_syntax.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_syntax.py	(original)
+++ python/branches/p3yk/Lib/test/test_syntax.py	Sun Apr 15 14:05:43 2007
@@ -5,7 +5,7 @@
 >>> def f(x):
 ...     global x
 Traceback (most recent call last):
-SyntaxError: name 'x' is local and global
+SyntaxError: name 'x' is parameter and global
 
 The tests are all raise SyntaxErrors.  They were created by checking
 each C call that raises SyntaxError.  There are several modules that
@@ -373,7 +373,7 @@
    ...     nonlocal x
    Traceback (most recent call last):
      ...
-   SyntaxError: name 'x' is local and nonlocal
+   SyntaxError: name 'x' is parameter and nonlocal
    
    >>> def f():
    ...     global x

Modified: python/branches/p3yk/Lib/test/test_univnewlines.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_univnewlines.py	(original)
+++ python/branches/p3yk/Lib/test/test_univnewlines.py	Sun Apr 15 14:05:43 2007
@@ -28,7 +28,6 @@
 # before end-of-file.
 DATA_MIXED = "\n".join(DATA_TEMPLATE) + "\r"
 DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE]
-del x
 
 class TestGenericUnivNewlines(unittest.TestCase):
     # use a class variable DATA to define the data to write to the file

Modified: python/branches/p3yk/Lib/tokenize.py
==============================================================================
--- python/branches/p3yk/Lib/tokenize.py	(original)
+++ python/branches/p3yk/Lib/tokenize.py	Sun Apr 15 14:05:43 2007
@@ -32,7 +32,6 @@
 import token
 __all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize",
            "generate_tokens", "NL", "untokenize"]
-del x
 del token
 
 COMMENT = N_TOKENS

Modified: python/branches/p3yk/Misc/NEWS
==============================================================================
--- python/branches/p3yk/Misc/NEWS	(original)
+++ python/branches/p3yk/Misc/NEWS	Sun Apr 15 14:05:43 2007
@@ -28,6 +28,9 @@
 Core and Builtins
 -----------------
 
+- Patch #1660500: hide iteration variable in list comps, add set comps
+  and use common code to handle compilation of iterative expressions
+
 - By default, != returns the opposite of ==, unless the latter returns
   NotImplemented.
 

Modified: python/branches/p3yk/Modules/parsermodule.c
==============================================================================
--- python/branches/p3yk/Modules/parsermodule.c	(original)
+++ python/branches/p3yk/Modules/parsermodule.c	Sun Apr 15 14:05:43 2007
@@ -858,11 +858,10 @@
 VALIDATER(stmt);                VALIDATER(simple_stmt);
 VALIDATER(expr_stmt);           VALIDATER(power);
 VALIDATER(del_stmt);
-VALIDATER(return_stmt);         VALIDATER(list_iter);
-VALIDATER(raise_stmt);          VALIDATER(import_stmt);
-VALIDATER(import_name);         VALIDATER(import_from);
-VALIDATER(global_stmt);         VALIDATER(list_if);
-VALIDATER(assert_stmt);         VALIDATER(list_for);
+VALIDATER(return_stmt);         VALIDATER(raise_stmt);
+VALIDATER(import_stmt);         VALIDATER(import_stmt);
+VALIDATER(import_name);         VALIDATER(yield_stmt);
+VALIDATER(global_stmt);         VALIDATER(assert_stmt);
 VALIDATER(compound_stmt);       VALIDATER(vname);
 VALIDATER(while);               VALIDATER(for);
 VALIDATER(try);                 VALIDATER(except_clause);
@@ -875,14 +874,13 @@
 VALIDATER(atom);                VALIDATER(lambdef);
 VALIDATER(trailer);             VALIDATER(subscript);
 VALIDATER(subscriptlist);       VALIDATER(sliceop);
-VALIDATER(exprlist);            VALIDATER(dictsetmaker);
+VALIDATER(exprlist);            VALIDATER(dictorsetmaker);
 VALIDATER(arglist);             VALIDATER(argument);
-VALIDATER(listmaker);           VALIDATER(yield_stmt);
-VALIDATER(testlist1);           VALIDATER(gen_for);
-VALIDATER(gen_iter);            VALIDATER(gen_if);
-VALIDATER(testlist_gexp);	VALIDATER(yield_expr);
-VALIDATER(yield_or_testlist);	VALIDATER(or_test);
-VALIDATER(old_test); 		VALIDATER(old_lambdef);
+VALIDATER(testlist1);           VALIDATER(comp_for);
+VALIDATER(comp_iter);           VALIDATER(comp_if);
+VALIDATER(testlist_comp);       VALIDATER(yield_expr);
+VALIDATER(yield_or_testlist);   VALIDATER(or_test);
+VALIDATER(test_nocond);         VALIDATER(lambdef_nocond);
 
 #undef VALIDATER
 
@@ -1112,14 +1110,6 @@
 }
 
 
-static int
-validate_testlist_safe(node *tree)
-{
-    return (validate_repeating_list(tree, testlist_safe,
-                                    validate_old_test, "testlist_safe"));
-}
-
-
 /* validate either vname or tname.
  * vname: NAME
  * tname: NAME [':' test]
@@ -1330,70 +1320,33 @@
 }
 
 
-/*  list_iter:  list_for | list_if
- */
-static int
-validate_list_iter(node *tree)
-{
-    int res = (validate_ntype(tree, list_iter)
-               && validate_numnodes(tree, 1, "list_iter"));
-    if (res && TYPE(CHILD(tree, 0)) == list_for)
-        res = validate_list_for(CHILD(tree, 0));
-    else
-        res = validate_list_if(CHILD(tree, 0));
-
-    return res;
-}
-
-/*  gen_iter:  gen_for | gen_if
- */
-static int
-validate_gen_iter(node *tree)
-{
-    int res = (validate_ntype(tree, gen_iter)
-               && validate_numnodes(tree, 1, "gen_iter"));
-    if (res && TYPE(CHILD(tree, 0)) == gen_for)
-        res = validate_gen_for(CHILD(tree, 0));
-    else
-        res = validate_gen_if(CHILD(tree, 0));
-
-    return res;
-}
-
-/*  list_for:  'for' exprlist 'in' testlist [list_iter]
+/*  comp_iter:  comp_for | comp_if
  */
 static int
-validate_list_for(node *tree)
+validate_comp_iter(node *tree)
 {
-    int nch = NCH(tree);
-    int res;
-
-    if (nch == 5)
-        res = validate_list_iter(CHILD(tree, 4));
+    int res = (validate_ntype(tree, comp_iter)
+               && validate_numnodes(tree, 1, "comp_iter"));
+    if (res && TYPE(CHILD(tree, 0)) == comp_for)
+        res = validate_comp_for(CHILD(tree, 0));
     else
-        res = validate_numnodes(tree, 4, "list_for");
-
-    if (res)
-        res = (validate_name(CHILD(tree, 0), "for")
-               && validate_exprlist(CHILD(tree, 1))
-               && validate_name(CHILD(tree, 2), "in")
-               && validate_testlist_safe(CHILD(tree, 3)));
+        res = validate_comp_if(CHILD(tree, 0));
 
     return res;
 }
 
-/*  gen_for:  'for' exprlist 'in' test [gen_iter]
+/*  comp_for:  'for' exprlist 'in' test [comp_iter]
  */
 static int
-validate_gen_for(node *tree)
+validate_comp_for(node *tree)
 {
     int nch = NCH(tree);
     int res;
 
     if (nch == 5)
-        res = validate_gen_iter(CHILD(tree, 4));
+        res = validate_comp_iter(CHILD(tree, 4));
     else
-        res = validate_numnodes(tree, 4, "gen_for");
+        res = validate_numnodes(tree, 4, "comp_for");
 
     if (res)
         res = (validate_name(CHILD(tree, 0), "for")
@@ -1404,45 +1357,26 @@
     return res;
 }
 
-/*  list_if:  'if' old_test [list_iter]
+/*  comp_if:  'if' test_nocond [comp_iter]
  */
 static int
-validate_list_if(node *tree)
+validate_comp_if(node *tree)
 {
     int nch = NCH(tree);
     int res;
 
     if (nch == 3)
-        res = validate_list_iter(CHILD(tree, 2));
+        res = validate_comp_iter(CHILD(tree, 2));
     else
-        res = validate_numnodes(tree, 2, "list_if");
+        res = validate_numnodes(tree, 2, "comp_if");
 
     if (res)
         res = (validate_name(CHILD(tree, 0), "if")
-               && validate_old_test(CHILD(tree, 1)));
+               && validate_test_nocond(CHILD(tree, 1)));
 
     return res;
 }
 
-/*  gen_if:  'if' old_test [gen_iter]
- */
-static int
-validate_gen_if(node *tree)
-{
-    int nch = NCH(tree);
-    int res;
-
-    if (nch == 3)
-        res = validate_gen_iter(CHILD(tree, 2));
-    else
-        res = validate_numnodes(tree, 2, "gen_if");
-    
-    if (res)
-        res = (validate_name(CHILD(tree, 0), "if")
-               && validate_old_test(CHILD(tree, 1)));
-
-    return res;
-}
 
 /* validate_vfpdef()
  *
@@ -2089,13 +2023,13 @@
 }
 
 static int
-validate_old_test(node *tree)
+validate_test_nocond(node *tree)
 {
     int nch = NCH(tree);
-    int res = validate_ntype(tree, old_test) && (nch == 1);
+    int res = validate_ntype(tree, test_nocond) && (nch == 1);
 
-    if (res && (TYPE(CHILD(tree, 0)) == old_lambdef))
-        res = (validate_old_lambdef(CHILD(tree, 0)));
+    if (res && (TYPE(CHILD(tree, 0)) == lambdef_nocond))
+        res = (validate_lambdef_nocond(CHILD(tree, 0)));
     else if (res) {
         res = (validate_or_test(CHILD(tree, 0)));
     }
@@ -2393,14 +2327,14 @@
 		if (TYPE(CHILD(tree, 1))==yield_expr)
 			res = validate_yield_expr(CHILD(tree, 1));
 		else
-                	res = validate_testlist_gexp(CHILD(tree, 1));
+                	res = validate_testlist_comp(CHILD(tree, 1));
 	    }
             break;
           case LSQB:
             if (nch == 2)
                 res = validate_ntype(CHILD(tree, 1), RSQB);
             else if (nch == 3)
-                res = (validate_listmaker(CHILD(tree, 1))
+                res = (validate_testlist_comp(CHILD(tree, 1))
                        && validate_ntype(CHILD(tree, 2), RSQB));
             else {
                 res = 0;
@@ -2412,7 +2346,7 @@
                    && validate_ntype(CHILD(tree, nch - 1), RBRACE));
 
             if (res && (nch == 3))
-                res = validate_dictsetmaker(CHILD(tree, 1));
+                res = validate_dictorsetmaker(CHILD(tree, 1));
             break;
           case NAME:
           case NUMBER:
@@ -2436,63 +2370,26 @@
 }
 
 
-/*  listmaker:
- *    test ( list_for | (',' test)* [','] )
- */
-static int
-validate_listmaker(node *tree)
-{
-    int nch = NCH(tree);
-    int ok = nch;
-
-    if (nch == 0)
-        err_string("missing child nodes of listmaker");
-    else
-        ok = validate_test(CHILD(tree, 0));
-
-    /*
-     *  list_for | (',' test)* [',']
-     */
-    if (nch == 2 && TYPE(CHILD(tree, 1)) == list_for)
-        ok = validate_list_for(CHILD(tree, 1));
-    else {
-        /*  (',' test)* [',']  */
-        int i = 1;
-        while (ok && nch - i >= 2) {
-            ok = (validate_comma(CHILD(tree, i))
-                  && validate_test(CHILD(tree, i+1)));
-            i += 2;
-        }
-        if (ok && i == nch-1)
-            ok = validate_comma(CHILD(tree, i));
-        else if (i != nch) {
-            ok = 0;
-            err_string("illegal trailing nodes for listmaker");
-        }
-    }
-    return ok;
-}
-
-/*  testlist_gexp:
- *    test ( gen_for | (',' test)* [','] )
+/*  testlist_comp:
+ *    test ( comp_for | (',' test)* [','] )
  */
 static int
-validate_testlist_gexp(node *tree)
+validate_testlist_comp(node *tree)
 {
     int nch = NCH(tree);
     int ok = nch;
 
     if (nch == 0)
-        err_string("missing child nodes of testlist_gexp");
+        err_string("missing child nodes of testlist_comp");
     else {
         ok = validate_test(CHILD(tree, 0));
     }
 
     /*
-     *  gen_for | (',' test)* [',']
+     *  comp_for | (',' test)* [',']
      */
-    if (nch == 2 && TYPE(CHILD(tree, 1)) == gen_for)
-        ok = validate_gen_for(CHILD(tree, 1));
+    if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for)
+        ok = validate_comp_for(CHILD(tree, 1));
     else {
         /*  (',' test)* [',']  */
         int i = 1;
@@ -2505,7 +2402,7 @@
             ok = validate_comma(CHILD(tree, i));
         else if (i != nch) {
             ok = 0;
-            err_string("illegal trailing nodes for testlist_gexp");
+            err_string("illegal trailing nodes for testlist_comp");
         }
     }
     return ok;
@@ -2596,10 +2493,10 @@
 
 
 static int
-validate_old_lambdef(node *tree)
+validate_lambdef_nocond(node *tree)
 {
     int nch = NCH(tree);
-    int res = (validate_ntype(tree, old_lambdef)
+    int res = (validate_ntype(tree, lambdef_nocond)
                && ((nch == 3) || (nch == 4))
                && validate_name(CHILD(tree, 0), "lambda")
                && validate_colon(CHILD(tree, nch - 2))
@@ -2608,7 +2505,7 @@
     if (res && (nch == 4))
         res = validate_varargslist(CHILD(tree, 1));
     else if (!res && !PyErr_Occurred())
-        (void) validate_numnodes(tree, 3, "old_lambdef");
+        (void) validate_numnodes(tree, 3, "lambdef_nocond");
 
     return (res);
 }
@@ -2633,7 +2530,7 @@
         for (i=0; i<nch; i++) {
             if (TYPE(CHILD(tree, i)) == argument) {
                 node *ch = CHILD(tree, i);
-                if (NCH(ch) == 2 && TYPE(CHILD(ch, 1)) == gen_for) {
+                if (NCH(ch) == 2 && TYPE(CHILD(ch, 1)) == comp_for) {
                     err_string("need '(', ')' for generator expression");
                     return 0;
                 }
@@ -2700,7 +2597,7 @@
 
 /*  argument:
  *
- *  [test '='] test [gen_for]
+ *  [test '='] test [comp_for]
  */
 static int
 validate_argument(node *tree)
@@ -2711,7 +2608,7 @@
                && validate_test(CHILD(tree, 0)));
 
     if (res && (nch == 2))
-        res = validate_gen_for(CHILD(tree, 1));
+        res = validate_comp_for(CHILD(tree, 1));
     else if (res && (nch == 3))
         res = (validate_equal(CHILD(tree, 1))
                && validate_test(CHILD(tree, 2)));
@@ -2853,10 +2750,10 @@
 
 
 static int
-validate_dictsetmaker(node *tree)
+validate_dictorsetmaker(node *tree)
 {
     int nch = NCH(tree);
-    int res = (validate_ntype(tree, dictsetmaker)
+    int res = (validate_ntype(tree, dictorsetmaker)
                && (nch >= 3)
                && validate_test(CHILD(tree, 0))
                && validate_colon(CHILD(tree, 1))

Modified: python/branches/p3yk/Modules/symtablemodule.c
==============================================================================
--- python/branches/p3yk/Modules/symtablemodule.c	(original)
+++ python/branches/p3yk/Modules/symtablemodule.c	Sun Apr 15 14:05:43 2007
@@ -33,7 +33,7 @@
 	st = Py_SymtableString(str, filename, start);
 	if (st == NULL)
 		return NULL;
-	t = st->st_symbols;
+	t = st->st_blocks;
 	Py_INCREF(t);
 	PyMem_Free((void *)st->st_future);
 	PySymtable_Free(st);

Modified: python/branches/p3yk/Parser/Python.asdl
==============================================================================
--- python/branches/p3yk/Parser/Python.asdl	(original)
+++ python/branches/p3yk/Parser/Python.asdl	Sun Apr 15 14:05:43 2007
@@ -56,6 +56,7 @@
 	     | Dict(expr* keys, expr* values)
 	     | Set(expr* elts)
 	     | ListComp(expr elt, comprehension* generators)
+         | SetComp(expr elt, comprehension* generators)
 	     | GeneratorExp(expr elt, comprehension* generators)
 	     -- the grammar constrains where yield expressions can occur
 	     | Yield(expr? value)

Modified: python/branches/p3yk/Python/Python-ast.c
==============================================================================
--- python/branches/p3yk/Python/Python-ast.c	(original)
+++ python/branches/p3yk/Python/Python-ast.c	Sun Apr 15 14:05:43 2007
@@ -192,6 +192,11 @@
         "elt",
         "generators",
 };
+static PyTypeObject *SetComp_type;
+static char *SetComp_fields[]={
+        "elt",
+        "generators",
+};
 static PyTypeObject *GeneratorExp_type;
 static char *GeneratorExp_fields[]={
         "elt",
@@ -543,6 +548,8 @@
         if (!Set_type) return 0;
         ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
         if (!ListComp_type) return 0;
+        SetComp_type = make_type("SetComp", expr_type, SetComp_fields, 2);
+        if (!SetComp_type) return 0;
         GeneratorExp_type = make_type("GeneratorExp", expr_type,
                                       GeneratorExp_fields, 2);
         if (!GeneratorExp_type) return 0;
@@ -1419,6 +1426,27 @@
 }
 
 expr_ty
+SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
+        *arena)
+{
+        expr_ty p;
+        if (!elt) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field elt is required for SetComp");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = SetComp_kind;
+        p->v.SetComp.elt = elt;
+        p->v.SetComp.generators = generators;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
+expr_ty
 GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
              PyArena *arena)
 {
@@ -2416,6 +2444,21 @@
                         goto failed;
                 Py_DECREF(value);
                 break;
+        case SetComp_kind:
+                result = PyType_GenericNew(SetComp_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_expr(o->v.SetComp.elt);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "elt", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                value = ast2obj_list(o->v.SetComp.generators,
+                                     ast2obj_comprehension);
+                if (!value) goto failed;
+                if (PyObject_SetAttrString(result, "generators", value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
         case GeneratorExp_kind:
                 result = PyType_GenericNew(GeneratorExp_type, NULL, NULL);
                 if (!result) goto failed;
@@ -3120,6 +3163,8 @@
         if (PyDict_SetItemString(d, "Set", (PyObject*)Set_type) < 0) return;
         if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0)
             return;
+        if (PyDict_SetItemString(d, "SetComp", (PyObject*)SetComp_type) < 0)
+            return;
         if (PyDict_SetItemString(d, "GeneratorExp",
             (PyObject*)GeneratorExp_type) < 0) return;
         if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return;

Modified: python/branches/p3yk/Python/ast.c
==============================================================================
--- python/branches/p3yk/Python/ast.c	(original)
+++ python/branches/p3yk/Python/ast.c	Sun Apr 15 14:05:43 2007
@@ -27,7 +27,6 @@
 static asdl_seq *ast_for_suite(struct compiling *, const node *);
 static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty);
 static expr_ty ast_for_testlist(struct compiling *, const node *);
-static expr_ty ast_for_testlist_gexp(struct compiling *, const node *);
 
 /* Note different signature for ast_for_call */
 static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
@@ -41,6 +40,10 @@
 #define LINENO(n)       ((n)->n_lineno)
 #endif
 
+#define COMP_GENEXP   0
+#define COMP_LISTCOMP 1
+#define COMP_SETCOMP  2
+
 static identifier
 new_identifier(const char* n, PyArena *arena) {
     PyObject* id = PyString_InternFromString(n);
@@ -231,7 +234,7 @@
         case eval_input: {
             expr_ty testlist_ast;
 
-            /* XXX Why not gen_for here? */
+            /* XXX Why not comp_for here? */
             testlist_ast = ast_for_testlist(&c, CHILD(n, 0));
             if (!testlist_ast)
                 goto error;
@@ -530,19 +533,14 @@
     asdl_seq *seq;
     expr_ty expression;
     int i;
-    assert(TYPE(n) == testlist
-           || TYPE(n) == listmaker
-           || TYPE(n) == testlist_gexp
-           || TYPE(n) == testlist_safe
-           || TYPE(n) == testlist1
-           );
+    assert(TYPE(n) == testlist || TYPE(n) == testlist_comp);
 
     seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);
     if (!seq)
         return NULL;
 
     for (i = 0; i < NCH(n); i += 2) {
-        assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == old_test);
+        assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == test_nocond);
 
         expression = ast_for_expr(c, CHILD(n, i));
         if (!expression)
@@ -1022,7 +1020,8 @@
 static expr_ty
 ast_for_lambdef(struct compiling *c, const node *n)
 {
-    /* lambdef: 'lambda' [varargslist] ':' test */
+    /* lambdef: 'lambda' [varargslist] ':' test
+       lambdef_nocond: 'lambda' [varargslist] ':' test_nocond */
     arguments_ty args;
     expr_ty expression;
 
@@ -1067,190 +1066,34 @@
                  c->c_arena);
 }
 
-/* XXX(nnorwitz): the listcomp and genexpr code should be refactored
-   so there is only a single version.  Possibly for loops can also re-use
-   the code.
-*/
-
-/* Count the number of 'for' loop in a list comprehension.
-
-   Helper for ast_for_listcomp().
-*/
-
-static int
-count_list_fors(const node *n)
-{
-    int n_fors = 0;
-    node *ch = CHILD(n, 1);
-
- count_list_for:
-    n_fors++;
-    REQ(ch, list_for);
-    if (NCH(ch) == 5)
-        ch = CHILD(ch, 4);
-    else
-        return n_fors;
- count_list_iter:
-    REQ(ch, list_iter);
-    ch = CHILD(ch, 0);
-    if (TYPE(ch) == list_for)
-        goto count_list_for;
-    else if (TYPE(ch) == list_if) {
-        if (NCH(ch) == 3) {
-            ch = CHILD(ch, 2);
-            goto count_list_iter;
-        }
-        else
-            return n_fors;
-    }
-
-    /* Should never be reached */
-    PyErr_SetString(PyExc_SystemError, "logic error in count_list_fors");
-    return -1;
-}
-
-/* Count the number of 'if' statements in a list comprehension.
-
-   Helper for ast_for_listcomp().
-*/
-
-static int
-count_list_ifs(const node *n)
-{
-    int n_ifs = 0;
-
- count_list_iter:
-    REQ(n, list_iter);
-    if (TYPE(CHILD(n, 0)) == list_for)
-        return n_ifs;
-    n = CHILD(n, 0);
-    REQ(n, list_if);
-    n_ifs++;
-    if (NCH(n) == 2)
-        return n_ifs;
-    n = CHILD(n, 2);
-    goto count_list_iter;
-}
-
-static expr_ty
-ast_for_listcomp(struct compiling *c, const node *n)
-{
-    /* listmaker: test ( list_for | (',' test)* [','] )
-       list_for: 'for' exprlist 'in' testlist_safe [list_iter]
-       list_iter: list_for | list_if
-       list_if: 'if' test [list_iter]
-       testlist_safe: test [(',' test)+ [',']]
-    */
-    expr_ty elt;
-    asdl_seq *listcomps;
-    int i, n_fors;
-    node *ch;
-
-    REQ(n, listmaker);
-    assert(NCH(n) > 1);
-
-    elt = ast_for_expr(c, CHILD(n, 0));
-    if (!elt)
-        return NULL;
-
-    n_fors = count_list_fors(n);
-    if (n_fors == -1)
-        return NULL;
-
-    listcomps = asdl_seq_new(n_fors, c->c_arena);
-    if (!listcomps)
-        return NULL;
-
-    ch = CHILD(n, 1);
-    for (i = 0; i < n_fors; i++) {
-        comprehension_ty lc;
-        asdl_seq *t;
-        expr_ty expression;
-        node *for_ch;
-
-        REQ(ch, list_for);
-
-        for_ch = CHILD(ch, 1);
-        t = ast_for_exprlist(c, for_ch, Store);
-        if (!t)
-            return NULL;
-        expression = ast_for_testlist(c, CHILD(ch, 3));
-        if (!expression)
-            return NULL;
-
-        /* Check the # of children rather than the length of t, since
-           [x for x, in ... ] has 1 element in t, but still requires a Tuple. */
-        if (NCH(for_ch) == 1)
-            lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL,
-                               c->c_arena);
-        else
-            lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset,
-                                     c->c_arena),
-                               expression, NULL, c->c_arena);
-        if (!lc)
-            return NULL;
-
-        if (NCH(ch) == 5) {
-            int j, n_ifs;
-            asdl_seq *ifs;
-
-            ch = CHILD(ch, 4);
-            n_ifs = count_list_ifs(ch);
-            if (n_ifs == -1)
-                return NULL;
-
-            ifs = asdl_seq_new(n_ifs, c->c_arena);
-            if (!ifs)
-                return NULL;
-
-            for (j = 0; j < n_ifs; j++) {
-            REQ(ch, list_iter);
-                    ch = CHILD(ch, 0);
-                    REQ(ch, list_if);
-
-                asdl_seq_SET(ifs, j, ast_for_expr(c, CHILD(ch, 1)));
-                if (NCH(ch) == 3)
-                    ch = CHILD(ch, 2);
-                }
-                /* on exit, must guarantee that ch is a list_for */
-                if (TYPE(ch) == list_iter)
-                        ch = CHILD(ch, 0);
-            lc->ifs = ifs;
-            }
-            asdl_seq_SET(listcomps, i, lc);
-    }
-
-    return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena);
-}
-
 /*
-   Count the number of 'for' loops in a generator expression.
+   Count the number of 'for' loops in a comprehension.
 
-   Helper for ast_for_genexp().
+   Helper for ast_for_comprehension().
 */
 
 static int
-count_gen_fors(const node *n)
+count_comp_fors(const node *n)
 {
         int n_fors = 0;
         node *ch = CHILD(n, 1);
 
- count_gen_for:
+ count_comp_for:
         n_fors++;
-        REQ(ch, gen_for);
+        REQ(ch, comp_for);
         if (NCH(ch) == 5)
                 ch = CHILD(ch, 4);
         else
                 return n_fors;
- count_gen_iter:
-        REQ(ch, gen_iter);
+ count_comp_iter:
+        REQ(ch, comp_iter);
         ch = CHILD(ch, 0);
-        if (TYPE(ch) == gen_for)
-                goto count_gen_for;
-        else if (TYPE(ch) == gen_if) {
+        if (TYPE(ch) == comp_for)
+                goto count_comp_for;
+        else if (TYPE(ch) == comp_if) {
                 if (NCH(ch) == 3) {
                         ch = CHILD(ch, 2);
-                        goto count_gen_iter;
+                        goto count_comp_iter;
                 }
                 else
                     return n_fors;
@@ -1258,26 +1101,26 @@
 
         /* Should never be reached */
         PyErr_SetString(PyExc_SystemError,
-                        "logic error in count_gen_fors");
+                        "logic error in count_comp_fors");
         return -1;
 }
 
-/* Count the number of 'if' statements in a generator expression.
+/* Count the number of 'if' statements in a comprehension.
 
-   Helper for ast_for_genexp().
+   Helper for ast_for_comprehension().
 */
 
 static int
-count_gen_ifs(const node *n)
+count_comp_ifs(const node *n)
 {
         int n_ifs = 0;
 
         while (1) {
-                REQ(n, gen_iter);
-                if (TYPE(CHILD(n, 0)) == gen_for)
+                REQ(n, comp_iter);
+                if (TYPE(CHILD(n, 0)) == comp_for)
                         return n_ifs;
                 n = CHILD(n, 0);
-                REQ(n, gen_if);
+                REQ(n, comp_if);
                 n_ifs++;
                 if (NCH(n) == 2)
                         return n_ifs;
@@ -1285,40 +1128,38 @@
         }
 }
 
-/* TODO(jhylton): Combine with list comprehension code? */
 static expr_ty
-ast_for_genexp(struct compiling *c, const node *n)
+ast_for_comprehension(struct compiling *c, const node *n, int type)
 {
-    /* testlist_gexp: test ( gen_for | (',' test)* [','] )
-       argument: [test '='] test [gen_for]       # Really [keyword '='] test */
+    /* testlist_comp: test ( comp_for | (',' test)* [','] )
+       argument: [test '='] test [comp_for]       # Really [keyword '='] test */
     expr_ty elt;
-    asdl_seq *genexps;
+    asdl_seq *comps;
     int i, n_fors;
     node *ch;
     
-    assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument));
     assert(NCH(n) > 1);
     
     elt = ast_for_expr(c, CHILD(n, 0));
     if (!elt)
         return NULL;
     
-    n_fors = count_gen_fors(n);
+    n_fors = count_comp_fors(n);
     if (n_fors == -1)
         return NULL;
 
-    genexps = asdl_seq_new(n_fors, c->c_arena);
-    if (!genexps)
+    comps = asdl_seq_new(n_fors, c->c_arena);
+    if (!comps)
         return NULL;
 
     ch = CHILD(n, 1);
     for (i = 0; i < n_fors; i++) {
-        comprehension_ty ge;
+        comprehension_ty comp;
         asdl_seq *t;
         expr_ty expression;
         node *for_ch;
         
-        REQ(ch, gen_for);
+        REQ(ch, comp_for);
         
         for_ch = CHILD(ch, 1);
         t = ast_for_exprlist(c, for_ch, Store);
@@ -1331,14 +1172,14 @@
         /* Check the # of children rather than the length of t, since
            (x for x, in ...) has 1 element in t, but still requires a Tuple. */
         if (NCH(for_ch) == 1)
-            ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression,
-                               NULL, c->c_arena);
+            comp = comprehension((expr_ty)asdl_seq_GET(t, 0), expression,
+                                 NULL, c->c_arena);
         else
-            ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset,
-                                     c->c_arena),
-                               expression, NULL, c->c_arena);
+            comp = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset,
+                                       c->c_arena),
+                                 expression, NULL, c->c_arena);
 
-        if (!ge)
+        if (!comp)
             return NULL;
 
         if (NCH(ch) == 5) {
@@ -1346,7 +1187,7 @@
             asdl_seq *ifs;
             
             ch = CHILD(ch, 4);
-            n_ifs = count_gen_ifs(ch);
+            n_ifs = count_comp_ifs(ch);
             if (n_ifs == -1)
                 return NULL;
 
@@ -1355,9 +1196,9 @@
                 return NULL;
 
             for (j = 0; j < n_ifs; j++) {
-                REQ(ch, gen_iter);
+                REQ(ch, comp_iter);
                 ch = CHILD(ch, 0);
-                REQ(ch, gen_if);
+                REQ(ch, comp_if);
                 
                 expression = ast_for_expr(c, CHILD(ch, 1));
                 if (!expression)
@@ -1366,22 +1207,52 @@
                 if (NCH(ch) == 3)
                     ch = CHILD(ch, 2);
             }
-            /* on exit, must guarantee that ch is a gen_for */
-            if (TYPE(ch) == gen_iter)
+            /* on exit, must guarantee that ch is a comp_for */
+            if (TYPE(ch) == comp_iter)
                 ch = CHILD(ch, 0);
-            ge->ifs = ifs;
+            comp->ifs = ifs;
         }
-        asdl_seq_SET(genexps, i, ge);
+        asdl_seq_SET(comps, i, comp);
     }
-    
-    return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena);
+
+    if (type == COMP_GENEXP)
+        return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else if (type == COMP_LISTCOMP)
+        return ListComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else if (type == COMP_SETCOMP)
+        return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);
+    else
+        /* Should never happen */
+        return NULL;
+}
+
+static expr_ty
+ast_for_genexp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument));
+    return ast_for_comprehension(c, n, COMP_GENEXP);
 }
 
 static expr_ty
+ast_for_listcomp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (testlist_comp));
+    return ast_for_comprehension(c, n, COMP_LISTCOMP);
+}
+
+static expr_ty
+ast_for_setcomp(struct compiling *c, const node *n)
+{
+    assert(TYPE(n) == (dictorsetmaker));
+    return ast_for_comprehension(c, n, COMP_SETCOMP);
+}
+
+
+static expr_ty
 ast_for_atom(struct compiling *c, const node *n)
 {
-    /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']'
-       | '{' [dictsetmaker] '}' | NAME | NUMBER | STRING+
+    /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']'
+       | '{' [dictmaker|testlist_comp] '}' | NAME | NUMBER | STRING+
     */
     node *ch = CHILD(n, 0);
     int bytesmode = 0;
@@ -1420,18 +1291,19 @@
         
         if (TYPE(ch) == yield_expr)
             return ast_for_expr(c, ch);
-        
-        if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for))
+
+        /* testlist_comp: test ( comp_for | (',' test)* [','] ) */ 
+        if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for))
             return ast_for_genexp(c, ch);
         
-        return ast_for_testlist_gexp(c, ch);
+        return ast_for_testlist(c, ch);
     case LSQB: /* list (or list comprehension) */
         ch = CHILD(n, 1);
         
         if (TYPE(ch) == RSQB)
             return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
         
-        REQ(ch, listmaker);
+        REQ(ch, testlist_comp);
         if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
             asdl_seq *elts = seq_for_testlist(c, ch);
             if (!elts)
@@ -1442,27 +1314,32 @@
         else
             return ast_for_listcomp(c, ch);
     case LBRACE: {
-        /* dictsetmaker: test ':' test (',' test ':' test)* [','] |
-         *               test (',' test)* [',']  */
+        /* dictorsetmaker: test ':' test (',' test ':' test)* [','] |
+         *                 test (gen_for | (',' test)* [','])  */
         int i, size;
         asdl_seq *keys, *values;
 
         ch = CHILD(n, 1);
-        if (NCH(ch) == 1 || (NCH(ch) > 0 && STR(CHILD(ch, 1))[0] == ',')) {
-            /* it's a set */
+        if (TYPE(ch) == RBRACE) {
+            /* it's an empty dict */
+            return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+        } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+            /* it's a simple set */
             size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */
-            keys = asdl_seq_new(size, c->c_arena);
-            if (!keys)
+            asdl_seq *elts = asdl_seq_new(size, c->c_arena);
+            if (!elts)
                 return NULL;
-
             for (i = 0; i < NCH(ch); i += 2) {
                 expr_ty expression;
                 expression = ast_for_expr(c, CHILD(ch, i));
                 if (!expression)
                     return NULL;
-                asdl_seq_SET(keys, i / 2, expression);
+                asdl_seq_SET(elts, i / 2, expression);
             }
-            return Set(keys, LINENO(n), n->n_col_offset, c->c_arena);
+            return Set(elts, LINENO(n), n->n_col_offset, c->c_arena);
+        } else if (TYPE(CHILD(ch, 1)) == comp_for) {
+            /* it's a set comprehension */
+            return ast_for_setcomp(c, ch);
         } else {
             /* it's a dict */
             size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */
@@ -1790,6 +1667,7 @@
 {
     /* handle the full range of simple expressions
        test: or_test ['if' or_test 'else' test] | lambdef
+       test_nocond: or_test | lambdef_nocond
        or_test: and_test ('or' and_test)* 
        and_test: not_test ('and' not_test)*
        not_test: 'not' not_test | comparison
@@ -1802,15 +1680,6 @@
        term: factor (('*'|'/'|'%'|'//') factor)*
        factor: ('+'|'-'|'~') factor | power
        power: atom trailer* ('**' factor)*
-
-       As well as modified versions that exist for backward compatibility,
-       to explicitly allow:
-       [ x for x in lambda: 0, lambda: 1 ]
-       (which would be ambiguous without these extra rules)
-       
-       old_test: or_test | old_lambdef
-       old_lambdef: 'lambda' [vararglist] ':' old_test
-
     */
 
     asdl_seq *seq;
@@ -1819,9 +1688,9 @@
  loop:
     switch (TYPE(n)) {
         case test:
-        case old_test:
+        case test_nocond:
             if (TYPE(CHILD(n, 0)) == lambdef ||
-                TYPE(CHILD(n, 0)) == old_lambdef)
+                TYPE(CHILD(n, 0)) == lambdef_nocond)
                 return ast_for_lambdef(c, CHILD(n, 0));
             else if (NCH(n) > 1)
                 return ast_for_ifexpr(c, n);
@@ -1947,7 +1816,7 @@
     /*
       arglist: (argument ',')* (argument [',']| '*' test [',' '**' test]
                | '**' test)
-      argument: [test '='] test [gen_for]        # Really [keyword '='] test
+      argument: [test '='] test [comp_for]        # Really [keyword '='] test
     */
 
     int i, nargs, nkeywords, ngens;
@@ -1965,7 +1834,7 @@
         if (TYPE(ch) == argument) {
             if (NCH(ch) == 1)
                 nargs++;
-            else if (TYPE(CHILD(ch, 1)) == gen_for)
+            else if (TYPE(CHILD(ch, 1)) == comp_for)
                 ngens++;
             else
                 nkeywords++;
@@ -2005,7 +1874,7 @@
                     return NULL;
                 asdl_seq_SET(args, nargs++, e);
             }  
-            else if (TYPE(CHILD(ch, 1)) == gen_for) {
+            else if (TYPE(CHILD(ch, 1)) == comp_for) {
                 e = ast_for_genexp(c, ch);
                 if (!e)
                     return NULL;
@@ -2057,18 +1926,16 @@
 static expr_ty
 ast_for_testlist(struct compiling *c, const node* n)
 {
-    /* testlist_gexp: test (',' test)* [','] */
+    /* testlist_comp: test (comp_for | (',' test)* [',']) */
     /* testlist: test (',' test)* [','] */
-    /* testlist_safe: test (',' test)+ [','] */
     /* testlist1: test (',' test)* */
     assert(NCH(n) > 0);
-    if (TYPE(n) == testlist_gexp) {
+    if (TYPE(n) == testlist_comp) {
         if (NCH(n) > 1)
-            assert(TYPE(CHILD(n, 1)) != gen_for);
+            assert(TYPE(CHILD(n, 1)) != comp_for);
     }
     else {
         assert(TYPE(n) == testlist ||
-               TYPE(n) == testlist_safe ||
                TYPE(n) == testlist1);
     }
     if (NCH(n) == 1)
@@ -2081,17 +1948,6 @@
     }
 }
 
-static expr_ty
-ast_for_testlist_gexp(struct compiling *c, const node* n)
-{
-    /* testlist_gexp: test ( gen_for | (',' test)* [','] ) */
-    /* argument: test [ gen_for ] */
-    assert(TYPE(n) == testlist_gexp || TYPE(n) == argument);
-    if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for)
-        return ast_for_genexp(c, n);
-    return ast_for_testlist(c, n);
-}
-
 static stmt_ty
 ast_for_expr_stmt(struct compiling *c, const node *n)
 {

Modified: python/branches/p3yk/Python/ceval.c
==============================================================================
--- python/branches/p3yk/Python/ceval.c	(original)
+++ python/branches/p3yk/Python/ceval.c	Sun Apr 15 14:05:43 2007
@@ -1241,6 +1241,18 @@
 			}
 			break;
 
+		case SET_ADD:
+			w = POP();
+			v = POP();
+			err = PySet_Add(v, w);
+			Py_DECREF(v);
+			Py_DECREF(w);
+			if (err == 0) {
+				PREDICT(JUMP_ABSOLUTE);
+				continue;
+			}
+			break;
+
 		case INPLACE_POWER:
 			w = POP();
 			v = TOP();

Modified: python/branches/p3yk/Python/compile.c
==============================================================================
--- python/branches/p3yk/Python/compile.c	(original)
+++ python/branches/p3yk/Python/compile.c	Sun Apr 15 14:05:43 2007
@@ -39,6 +39,10 @@
 #define DEFAULT_CODE_SIZE 128
 #define DEFAULT_LNOTAB_SIZE 16
 
+#define COMP_GENEXP   0
+#define COMP_LISTCOMP 1
+#define COMP_SETCOMP  2
+
 struct instr {
 	unsigned i_jabs : 1;
 	unsigned i_jrel : 1;
@@ -360,7 +364,7 @@
 	while (PyDict_Next(src, &pos, &k, &v)) {
 		/* XXX this should probably be a macro in symtable.h */
 		assert(PyInt_Check(v));
-		scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
+		scope = (PyInt_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
 
 		if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
 			PyObject *tuple, *item = PyInt_FromLong(i);
@@ -673,6 +677,7 @@
 		case UNARY_INVERT:
 			return 0;
 
+		case SET_ADD:
 		case LIST_APPEND:
 			return -2;
 
@@ -2724,122 +2729,45 @@
 	return 1;
 }
 
-static int
-compiler_listcomp_generator(struct compiler *c, PyObject *tmpname,
-			    asdl_seq *generators, int gen_index, 
-			    expr_ty elt)
-{
-	/* generate code for the iterator, then each of the ifs,
-	   and then write to the element */
 
-	comprehension_ty l;
-	basicblock *start, *anchor, *skip, *if_cleanup;
-	int i, n;
+/* List and set comprehensions and generator expressions work by creating a
+  nested function to perform the actual iteration. This means that the
+  iteration variables don't leak into the current scope.
+  The defined function is called immediately following its definition, with the
+  result of that call being the result of the expression.
+  The LC/SC version returns the populated container, while the GE version is
+  flagged in symtable.c as a generator, so it returns the generator object
+  when the function is called.
+  This code *knows* that the loop cannot contain break, continue, or return,
+  so it cheats and skips the SETUP_LOOP/POP_BLOCK steps used in normal loops.
 
-	start = compiler_new_block(c);
-	skip = compiler_new_block(c);
-	if_cleanup = compiler_new_block(c);
-	anchor = compiler_new_block(c);
-
-	if (start == NULL || skip == NULL || if_cleanup == NULL ||
-		anchor == NULL)
-	    return 0;
-
-	l = (comprehension_ty)asdl_seq_GET(generators, gen_index);
-	VISIT(c, expr, l->iter);
-	ADDOP(c, GET_ITER);
-	compiler_use_next_block(c, start);
-	ADDOP_JREL(c, FOR_ITER, anchor);
-	NEXT_BLOCK(c);
-	VISIT(c, expr, l->target);
-
-	/* XXX this needs to be cleaned up...a lot! */
-	n = asdl_seq_LEN(l->ifs);
-	for (i = 0; i < n; i++) {
-		expr_ty e = (expr_ty)asdl_seq_GET(l->ifs, i);
-		VISIT(c, expr, e);
-		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);
-		NEXT_BLOCK(c);
-		ADDOP(c, POP_TOP);
-	} 
-
-	if (++gen_index < asdl_seq_LEN(generators))
-	    if (!compiler_listcomp_generator(c, tmpname, 
-					     generators, gen_index, elt))
-		return 0;
-
-	/* only append after the last for generator */
-	if (gen_index >= asdl_seq_LEN(generators)) {
-	    if (!compiler_nameop(c, tmpname, Load))
-		return 0;
-	    VISIT(c, expr, elt);
-	    ADDOP(c, LIST_APPEND);
-
-	    compiler_use_next_block(c, skip);
-	}
-	for (i = 0; i < n; i++) {
-		ADDOP_I(c, JUMP_FORWARD, 1);
-		if (i == 0)
-		    compiler_use_next_block(c, if_cleanup);
-		ADDOP(c, POP_TOP);
-	} 
-	ADDOP_JABS(c, JUMP_ABSOLUTE, start);
-	compiler_use_next_block(c, anchor);
-	/* delete the temporary list name added to locals */
-	if (gen_index == 1)
-	    if (!compiler_nameop(c, tmpname, Del))
-		return 0;
-	
-	return 1;
-}
-
-static int
-compiler_listcomp(struct compiler *c, expr_ty e)
-{
-	identifier tmp;
-	int rc = 0;
-	asdl_seq *generators = e->v.ListComp.generators;
-
-	assert(e->kind == ListComp_kind);
-	tmp = compiler_new_tmpname(c);
-	if (!tmp)
-		return 0;
-	ADDOP_I(c, BUILD_LIST, 0);
-	ADDOP(c, DUP_TOP);
-	if (compiler_nameop(c, tmp, Store))
-	    rc = compiler_listcomp_generator(c, tmp, generators, 0, 
-					     e->v.ListComp.elt);
-	Py_DECREF(tmp);
-	return rc;
-}
+  Possible cleanups:
+    - iterate over the generator sequence instead of using recursion
+*/
 
 static int
-compiler_genexp_generator(struct compiler *c,
-			  asdl_seq *generators, int gen_index, 
-			  expr_ty elt)
+compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,
+				 asdl_seq *generators, int gen_index, 
+				 expr_ty elt, int type)
 {
 	/* generate code for the iterator, then each of the ifs,
 	   and then write to the element */
 
-	comprehension_ty ge;
-	basicblock *start, *anchor, *skip, *if_cleanup, *end;
+	comprehension_ty gen;
+	basicblock *start, *anchor, *skip, *if_cleanup;
 	int i, n;
 
 	start = compiler_new_block(c);
 	skip = compiler_new_block(c);
 	if_cleanup = compiler_new_block(c);
 	anchor = compiler_new_block(c);
-	end = compiler_new_block(c);
 
 	if (start == NULL || skip == NULL || if_cleanup == NULL ||
-	    anchor == NULL || end == NULL)
-		return 0;
-
-	ge = (comprehension_ty)asdl_seq_GET(generators, gen_index);
-	ADDOP_JREL(c, SETUP_LOOP, end);
-	if (!compiler_push_fblock(c, LOOP, start))
+	    anchor == NULL)
 		return 0;
 
+	gen = (comprehension_ty)asdl_seq_GET(generators, gen_index);
+	
 	if (gen_index == 0) {
 		/* Receive outermost iter as an implicit argument */
 		c->u->u_argcount = 1;
@@ -2847,18 +2775,18 @@
 	}
 	else {
 		/* Sub-iter - calculate on the fly */
-		VISIT(c, expr, ge->iter);
+		VISIT(c, expr, gen->iter);
 		ADDOP(c, GET_ITER);
 	}
 	compiler_use_next_block(c, start);
 	ADDOP_JREL(c, FOR_ITER, anchor);
 	NEXT_BLOCK(c);
-	VISIT(c, expr, ge->target);
+	VISIT(c, expr, gen->target);
 
 	/* XXX this needs to be cleaned up...a lot! */
-	n = asdl_seq_LEN(ge->ifs);
+	n = asdl_seq_LEN(gen->ifs);
 	for (i = 0; i < n; i++) {
-		expr_ty e = (expr_ty)asdl_seq_GET(ge->ifs, i);
+		expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);
 		VISIT(c, expr, e);
 		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);
 		NEXT_BLOCK(c);
@@ -2866,14 +2794,35 @@
 	} 
 
 	if (++gen_index < asdl_seq_LEN(generators))
-		if (!compiler_genexp_generator(c, generators, gen_index, elt))
-			return 0;
+		if (!compiler_comprehension_generator(c, tmpname, 
+						      generators, gen_index,
+						      elt, type))
+		return 0;
 
-	/* only append after the last 'for' generator */
+	/* only append after the last for generator */
 	if (gen_index >= asdl_seq_LEN(generators)) {
-		VISIT(c, expr, elt);
-		ADDOP(c, YIELD_VALUE);
-		ADDOP(c, POP_TOP);
+		/* comprehension specific code */
+		switch (type) {
+		case COMP_GENEXP:
+			VISIT(c, expr, elt);
+			ADDOP(c, YIELD_VALUE);
+			ADDOP(c, POP_TOP);
+			break;
+		case COMP_LISTCOMP:
+			if (!compiler_nameop(c, tmpname, Load))
+				return 0;
+			VISIT(c, expr, elt);
+			ADDOP(c, LIST_APPEND);
+			break;
+		case COMP_SETCOMP:
+			if (!compiler_nameop(c, tmpname, Load))
+				return 0;
+			VISIT(c, expr, elt);
+			ADDOP(c, SET_ADD);
+			break;
+		default:
+			return 0;
+		}
 
 		compiler_use_next_block(c, skip);
 	}
@@ -2881,52 +2830,116 @@
 		ADDOP_I(c, JUMP_FORWARD, 1);
 		if (i == 0)
 			compiler_use_next_block(c, if_cleanup);
-
+		
 		ADDOP(c, POP_TOP);
 	} 
 	ADDOP_JABS(c, JUMP_ABSOLUTE, start);
 	compiler_use_next_block(c, anchor);
-	ADDOP(c, POP_BLOCK);
-	compiler_pop_fblock(c, LOOP, start);
-	compiler_use_next_block(c, end);
 
 	return 1;
 }
 
 static int
-compiler_genexp(struct compiler *c, expr_ty e)
+compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
+		       asdl_seq *generators, expr_ty elt)
 {
-	static identifier name;
-	PyCodeObject *co;
-	expr_ty outermost_iter = ((comprehension_ty)
-				 (asdl_seq_GET(e->v.GeneratorExp.generators,
-					       0)))->iter;
+	PyCodeObject *co = NULL;
+	identifier tmp = NULL;
+	expr_ty outermost_iter;
 
-	if (!name) {
-		name = PyString_FromString("<genexpr>");
-		if (!name)
-			return 0;
-	}
+	outermost_iter = ((comprehension_ty)
+			  asdl_seq_GET(generators, 0))->iter;
 
 	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
-		return 0;
-	compiler_genexp_generator(c, e->v.GeneratorExp.generators, 0,
-				  e->v.GeneratorExp.elt);
+		goto error;
+	
+	if (type != COMP_GENEXP) {
+		tmp = compiler_new_tmpname(c);
+		if (!tmp)
+			goto error_in_scope;
+
+		ADDOP_I(c, (type == COMP_LISTCOMP ?
+			    BUILD_LIST : BUILD_SET), 0);
+		ADDOP(c, DUP_TOP);
+		if (!compiler_nameop(c, tmp, Store))
+			goto error_in_scope;
+	}
+	
+	if (!compiler_comprehension_generator(c, tmp, generators, 0, elt, type))
+		goto error_in_scope;
+	
+	if (type != COMP_GENEXP) {
+		ADDOP(c, RETURN_VALUE);
+	}
+
 	co = assemble(c, 1);
 	compiler_exit_scope(c);
 	if (co == NULL)
-		return 0;
+		goto error;
 
-	compiler_make_closure(c, co, 0);
+	if (!compiler_make_closure(c, co, 0))
+		goto error;
 	Py_DECREF(co);
+	Py_XDECREF(tmp);
 
 	VISIT(c, expr, outermost_iter);
 	ADDOP(c, GET_ITER);
 	ADDOP_I(c, CALL_FUNCTION, 1);
-
 	return 1;
+error_in_scope:
+	compiler_exit_scope(c);
+error:
+	Py_XDECREF(co);
+	Py_XDECREF(tmp);
+	return 0;
+}
+
+static int
+compiler_genexp(struct compiler *c, expr_ty e)
+{
+	static identifier name;
+	if (!name) {
+		name = PyString_FromString("<genexp>");
+		if (!name)
+			return 0;
+	}
+	assert(e->kind == GeneratorExp_kind);
+	return compiler_comprehension(c, e, COMP_GENEXP, name,
+				      e->v.GeneratorExp.generators,
+				      e->v.GeneratorExp.elt);
+}
+
+static int
+compiler_listcomp(struct compiler *c, expr_ty e)
+{
+	static identifier name;
+	if (!name) {
+		name = PyString_FromString("<listcomp>");
+		if (!name)
+			return 0;
+	}
+	assert(e->kind == ListComp_kind);
+	return compiler_comprehension(c, e, COMP_LISTCOMP, name,
+				      e->v.ListComp.generators,
+				      e->v.ListComp.elt);
+}
+
+static int
+compiler_setcomp(struct compiler *c, expr_ty e)
+{
+	static identifier name;
+	if (!name) {
+		name = PyString_FromString("<setcomp>");
+		if (!name)
+			return 0;
+	}
+	assert(e->kind == SetComp_kind);
+	return compiler_comprehension(c, e, COMP_SETCOMP, name,
+				      e->v.SetComp.generators,
+				      e->v.SetComp.elt);
 }
 
+
 static int
 compiler_visit_keyword(struct compiler *c, keyword_ty k)
 {
@@ -3145,10 +3158,12 @@
 		VISIT_SEQ(c, expr, e->v.Set.elts);
 		ADDOP_I(c, BUILD_SET, n);
 		break;
-	case ListComp_kind:
-		return compiler_listcomp(c, e);
 	case GeneratorExp_kind:
 		return compiler_genexp(c, e);
+	case ListComp_kind:
+		return compiler_listcomp(c, e);
+	case SetComp_kind:
+		return compiler_setcomp(c, e);
 	case Yield_kind:
 		if (c->u->u_ste->ste_type != FunctionBlock)
 			return compiler_error(c, "'yield' outside function");

Modified: python/branches/p3yk/Python/graminit.c
==============================================================================
--- python/branches/p3yk/Python/graminit.c	(original)
+++ python/branches/p3yk/Python/graminit.c	Sun Apr 15 14:05:43 2007
@@ -1061,33 +1061,36 @@
 	{1, arcs_47_3},
 	{2, arcs_47_4},
 };
-static arc arcs_48_0[1] = {
-	{109, 1},
+static arc arcs_48_0[2] = {
+	{108, 1},
+	{109, 2},
 };
 static arc arcs_48_1[2] = {
-	{28, 2},
+	{93, 3},
 	{0, 1},
 };
 static arc arcs_48_2[1] = {
-	{109, 3},
+	{0, 2},
 };
-static arc arcs_48_3[2] = {
-	{28, 4},
-	{0, 3},
+static arc arcs_48_3[1] = {
+	{108, 4},
 };
-static arc arcs_48_4[2] = {
-	{109, 3},
-	{0, 4},
+static arc arcs_48_4[1] = {
+	{95, 5},
+};
+static arc arcs_48_5[1] = {
+	{22, 2},
 };
-static state states_48[5] = {
-	{1, arcs_48_0},
+static state states_48[6] = {
+	{2, arcs_48_0},
 	{2, arcs_48_1},
 	{1, arcs_48_2},
-	{2, arcs_48_3},
-	{2, arcs_48_4},
+	{1, arcs_48_3},
+	{1, arcs_48_4},
+	{1, arcs_48_5},
 };
 static arc arcs_49_0[2] = {
-	{110, 1},
+	{108, 1},
 	{111, 1},
 };
 static arc arcs_49_1[1] = {
@@ -1108,7 +1111,7 @@
 	{23, 3},
 };
 static arc arcs_50_3[1] = {
-	{109, 4},
+	{22, 4},
 };
 static arc arcs_50_4[1] = {
 	{0, 4},
@@ -1120,39 +1123,34 @@
 	{1, arcs_50_3},
 	{1, arcs_50_4},
 };
-static arc arcs_51_0[2] = {
-	{110, 1},
-	{113, 2},
+static arc arcs_51_0[1] = {
+	{112, 1},
 };
 static arc arcs_51_1[2] = {
-	{93, 3},
-	{0, 1},
+	{33, 2},
+	{23, 3},
 };
 static arc arcs_51_2[1] = {
-	{0, 2},
+	{23, 3},
 };
 static arc arcs_51_3[1] = {
 	{110, 4},
 };
 static arc arcs_51_4[1] = {
-	{95, 5},
-};
-static arc arcs_51_5[1] = {
-	{22, 2},
+	{0, 4},
 };
-static state states_51[6] = {
-	{2, arcs_51_0},
+static state states_51[5] = {
+	{1, arcs_51_0},
 	{2, arcs_51_1},
 	{1, arcs_51_2},
 	{1, arcs_51_3},
 	{1, arcs_51_4},
-	{1, arcs_51_5},
 };
 static arc arcs_52_0[1] = {
-	{114, 1},
+	{113, 1},
 };
 static arc arcs_52_1[2] = {
-	{115, 0},
+	{114, 0},
 	{0, 1},
 };
 static state states_52[2] = {
@@ -1160,10 +1158,10 @@
 	{2, arcs_52_1},
 };
 static arc arcs_53_0[1] = {
-	{116, 1},
+	{115, 1},
 };
 static arc arcs_53_1[2] = {
-	{117, 0},
+	{116, 0},
 	{0, 1},
 };
 static state states_53[2] = {
@@ -1171,11 +1169,11 @@
 	{2, arcs_53_1},
 };
 static arc arcs_54_0[2] = {
-	{118, 1},
-	{119, 2},
+	{117, 1},
+	{118, 2},
 };
 static arc arcs_54_1[1] = {
-	{116, 2},
+	{115, 2},
 };
 static arc arcs_54_2[1] = {
 	{0, 2},
@@ -1189,7 +1187,7 @@
 	{104, 1},
 };
 static arc arcs_55_1[2] = {
-	{120, 0},
+	{119, 0},
 	{0, 1},
 };
 static state states_55[2] = {
@@ -1197,15 +1195,15 @@
 	{2, arcs_55_1},
 };
 static arc arcs_56_0[9] = {
+	{120, 1},
 	{121, 1},
 	{122, 1},
 	{123, 1},
 	{124, 1},
 	{125, 1},
-	{126, 1},
 	{98, 1},
-	{118, 2},
-	{127, 3},
+	{117, 2},
+	{126, 3},
 };
 static arc arcs_56_1[1] = {
 	{0, 1},
@@ -1214,7 +1212,7 @@
 	{98, 1},
 };
 static arc arcs_56_3[2] = {
-	{118, 1},
+	{117, 1},
 	{0, 3},
 };
 static state states_56[4] = {
@@ -1224,10 +1222,10 @@
 	{2, arcs_56_3},
 };
 static arc arcs_57_0[1] = {
-	{128, 1},
+	{127, 1},
 };
 static arc arcs_57_1[2] = {
-	{129, 0},
+	{128, 0},
 	{0, 1},
 };
 static state states_57[2] = {
@@ -1235,10 +1233,10 @@
 	{2, arcs_57_1},
 };
 static arc arcs_58_0[1] = {
-	{130, 1},
+	{129, 1},
 };
 static arc arcs_58_1[2] = {
-	{131, 0},
+	{130, 0},
 	{0, 1},
 };
 static state states_58[2] = {
@@ -1246,10 +1244,10 @@
 	{2, arcs_58_1},
 };
 static arc arcs_59_0[1] = {
-	{132, 1},
+	{131, 1},
 };
 static arc arcs_59_1[2] = {
-	{133, 0},
+	{132, 0},
 	{0, 1},
 };
 static state states_59[2] = {
@@ -1257,11 +1255,11 @@
 	{2, arcs_59_1},
 };
 static arc arcs_60_0[1] = {
-	{134, 1},
+	{133, 1},
 };
 static arc arcs_60_1[3] = {
+	{134, 0},
 	{135, 0},
-	{136, 0},
 	{0, 1},
 };
 static state states_60[2] = {
@@ -1269,11 +1267,11 @@
 	{3, arcs_60_1},
 };
 static arc arcs_61_0[1] = {
-	{137, 1},
+	{136, 1},
 };
 static arc arcs_61_1[3] = {
+	{137, 0},
 	{138, 0},
-	{139, 0},
 	{0, 1},
 };
 static state states_61[2] = {
@@ -1281,13 +1279,13 @@
 	{3, arcs_61_1},
 };
 static arc arcs_62_0[1] = {
-	{140, 1},
+	{139, 1},
 };
 static arc arcs_62_1[5] = {
 	{29, 0},
+	{140, 0},
 	{141, 0},
 	{142, 0},
-	{143, 0},
 	{0, 1},
 };
 static state states_62[2] = {
@@ -1295,13 +1293,13 @@
 	{5, arcs_62_1},
 };
 static arc arcs_63_0[4] = {
+	{137, 1},
 	{138, 1},
-	{139, 1},
-	{144, 1},
-	{145, 2},
+	{143, 1},
+	{144, 2},
 };
 static arc arcs_63_1[1] = {
-	{140, 2},
+	{139, 2},
 };
 static arc arcs_63_2[1] = {
 	{0, 2},
@@ -1312,15 +1310,15 @@
 	{1, arcs_63_2},
 };
 static arc arcs_64_0[1] = {
-	{146, 1},
+	{145, 1},
 };
 static arc arcs_64_1[3] = {
-	{147, 1},
+	{146, 1},
 	{31, 2},
 	{0, 1},
 };
 static arc arcs_64_2[1] = {
-	{140, 3},
+	{139, 3},
 };
 static arc arcs_64_3[1] = {
 	{0, 3},
@@ -1333,41 +1331,41 @@
 };
 static arc arcs_65_0[7] = {
 	{13, 1},
-	{149, 2},
-	{152, 3},
+	{148, 2},
+	{150, 3},
 	{19, 4},
-	{155, 4},
-	{156, 5},
+	{153, 4},
+	{154, 5},
 	{79, 4},
 };
 static arc arcs_65_1[3] = {
 	{48, 6},
-	{148, 6},
+	{147, 6},
 	{15, 4},
 };
 static arc arcs_65_2[2] = {
-	{150, 7},
-	{151, 4},
+	{147, 7},
+	{149, 4},
 };
 static arc arcs_65_3[2] = {
-	{153, 8},
-	{154, 4},
+	{151, 8},
+	{152, 4},
 };
 static arc arcs_65_4[1] = {
 	{0, 4},
 };
 static arc arcs_65_5[2] = {
-	{156, 5},
+	{154, 5},
 	{0, 5},
 };
 static arc arcs_65_6[1] = {
 	{15, 4},
 };
 static arc arcs_65_7[1] = {
-	{151, 4},
+	{149, 4},
 };
 static arc arcs_65_8[1] = {
-	{154, 4},
+	{152, 4},
 };
 static state states_65[9] = {
 	{7, arcs_65_0},
@@ -1384,7 +1382,7 @@
 	{22, 1},
 };
 static arc arcs_66_1[3] = {
-	{157, 2},
+	{155, 2},
 	{28, 3},
 	{0, 1},
 };
@@ -1406,644 +1404,533 @@
 	{2, arcs_66_3},
 	{2, arcs_66_4},
 };
-static arc arcs_67_0[1] = {
-	{22, 1},
-};
-static arc arcs_67_1[3] = {
-	{158, 2},
-	{28, 3},
-	{0, 1},
-};
-static arc arcs_67_2[1] = {
-	{0, 2},
-};
-static arc arcs_67_3[2] = {
-	{22, 4},
-	{0, 3},
-};
-static arc arcs_67_4[2] = {
-	{28, 3},
-	{0, 4},
-};
-static state states_67[5] = {
-	{1, arcs_67_0},
-	{3, arcs_67_1},
-	{1, arcs_67_2},
-	{2, arcs_67_3},
-	{2, arcs_67_4},
-};
-static arc arcs_68_0[1] = {
-	{112, 1},
-};
-static arc arcs_68_1[2] = {
-	{33, 2},
-	{23, 3},
-};
-static arc arcs_68_2[1] = {
-	{23, 3},
-};
-static arc arcs_68_3[1] = {
-	{22, 4},
-};
-static arc arcs_68_4[1] = {
-	{0, 4},
-};
-static state states_68[5] = {
-	{1, arcs_68_0},
-	{2, arcs_68_1},
-	{1, arcs_68_2},
-	{1, arcs_68_3},
-	{1, arcs_68_4},
-};
-static arc arcs_69_0[3] = {
+static arc arcs_67_0[3] = {
 	{13, 1},
-	{149, 2},
+	{148, 2},
 	{78, 3},
 };
-static arc arcs_69_1[2] = {
+static arc arcs_67_1[2] = {
 	{14, 4},
 	{15, 5},
 };
-static arc arcs_69_2[1] = {
-	{159, 6},
+static arc arcs_67_2[1] = {
+	{156, 6},
 };
-static arc arcs_69_3[1] = {
+static arc arcs_67_3[1] = {
 	{19, 5},
 };
-static arc arcs_69_4[1] = {
+static arc arcs_67_4[1] = {
 	{15, 5},
 };
-static arc arcs_69_5[1] = {
+static arc arcs_67_5[1] = {
 	{0, 5},
 };
-static arc arcs_69_6[1] = {
-	{151, 5},
+static arc arcs_67_6[1] = {
+	{149, 5},
 };
-static state states_69[7] = {
-	{3, arcs_69_0},
-	{2, arcs_69_1},
-	{1, arcs_69_2},
-	{1, arcs_69_3},
-	{1, arcs_69_4},
-	{1, arcs_69_5},
-	{1, arcs_69_6},
+static state states_67[7] = {
+	{3, arcs_67_0},
+	{2, arcs_67_1},
+	{1, arcs_67_2},
+	{1, arcs_67_3},
+	{1, arcs_67_4},
+	{1, arcs_67_5},
+	{1, arcs_67_6},
 };
-static arc arcs_70_0[1] = {
-	{160, 1},
+static arc arcs_68_0[1] = {
+	{157, 1},
 };
-static arc arcs_70_1[2] = {
+static arc arcs_68_1[2] = {
 	{28, 2},
 	{0, 1},
 };
-static arc arcs_70_2[2] = {
-	{160, 1},
+static arc arcs_68_2[2] = {
+	{157, 1},
 	{0, 2},
 };
-static state states_70[3] = {
-	{1, arcs_70_0},
-	{2, arcs_70_1},
-	{2, arcs_70_2},
+static state states_68[3] = {
+	{1, arcs_68_0},
+	{2, arcs_68_1},
+	{2, arcs_68_2},
 };
-static arc arcs_71_0[2] = {
+static arc arcs_69_0[2] = {
 	{22, 1},
 	{23, 2},
 };
-static arc arcs_71_1[2] = {
+static arc arcs_69_1[2] = {
 	{23, 2},
 	{0, 1},
 };
-static arc arcs_71_2[3] = {
+static arc arcs_69_2[3] = {
 	{22, 3},
-	{161, 4},
+	{158, 4},
 	{0, 2},
 };
-static arc arcs_71_3[2] = {
-	{161, 4},
+static arc arcs_69_3[2] = {
+	{158, 4},
 	{0, 3},
 };
-static arc arcs_71_4[1] = {
+static arc arcs_69_4[1] = {
 	{0, 4},
 };
-static state states_71[5] = {
-	{2, arcs_71_0},
-	{2, arcs_71_1},
-	{3, arcs_71_2},
-	{2, arcs_71_3},
-	{1, arcs_71_4},
+static state states_69[5] = {
+	{2, arcs_69_0},
+	{2, arcs_69_1},
+	{3, arcs_69_2},
+	{2, arcs_69_3},
+	{1, arcs_69_4},
 };
-static arc arcs_72_0[1] = {
+static arc arcs_70_0[1] = {
 	{23, 1},
 };
-static arc arcs_72_1[2] = {
+static arc arcs_70_1[2] = {
 	{22, 2},
 	{0, 1},
 };
-static arc arcs_72_2[1] = {
+static arc arcs_70_2[1] = {
 	{0, 2},
 };
-static state states_72[3] = {
-	{1, arcs_72_0},
-	{2, arcs_72_1},
-	{1, arcs_72_2},
+static state states_70[3] = {
+	{1, arcs_70_0},
+	{2, arcs_70_1},
+	{1, arcs_70_2},
 };
-static arc arcs_73_0[1] = {
+static arc arcs_71_0[1] = {
 	{104, 1},
 };
-static arc arcs_73_1[2] = {
+static arc arcs_71_1[2] = {
 	{28, 2},
 	{0, 1},
 };
-static arc arcs_73_2[2] = {
+static arc arcs_71_2[2] = {
 	{104, 1},
 	{0, 2},
 };
-static state states_73[3] = {
-	{1, arcs_73_0},
-	{2, arcs_73_1},
-	{2, arcs_73_2},
+static state states_71[3] = {
+	{1, arcs_71_0},
+	{2, arcs_71_1},
+	{2, arcs_71_2},
 };
-static arc arcs_74_0[1] = {
+static arc arcs_72_0[1] = {
 	{22, 1},
 };
-static arc arcs_74_1[2] = {
+static arc arcs_72_1[2] = {
 	{28, 2},
 	{0, 1},
 };
-static arc arcs_74_2[2] = {
+static arc arcs_72_2[2] = {
 	{22, 1},
 	{0, 2},
 };
-static state states_74[3] = {
-	{1, arcs_74_0},
-	{2, arcs_74_1},
-	{2, arcs_74_2},
+static state states_72[3] = {
+	{1, arcs_72_0},
+	{2, arcs_72_1},
+	{2, arcs_72_2},
 };
-static arc arcs_75_0[1] = {
+static arc arcs_73_0[1] = {
 	{22, 1},
 };
-static arc arcs_75_1[3] = {
+static arc arcs_73_1[4] = {
 	{23, 2},
-	{28, 3},
+	{155, 3},
+	{28, 4},
 	{0, 1},
 };
-static arc arcs_75_2[1] = {
-	{22, 4},
-};
-static arc arcs_75_3[2] = {
+static arc arcs_73_2[1] = {
 	{22, 5},
+};
+static arc arcs_73_3[1] = {
 	{0, 3},
 };
-static arc arcs_75_4[2] = {
-	{28, 6},
+static arc arcs_73_4[2] = {
+	{22, 6},
 	{0, 4},
 };
-static arc arcs_75_5[2] = {
-	{28, 3},
+static arc arcs_73_5[2] = {
+	{28, 7},
 	{0, 5},
 };
-static arc arcs_75_6[2] = {
-	{22, 7},
+static arc arcs_73_6[2] = {
+	{28, 4},
 	{0, 6},
 };
-static arc arcs_75_7[1] = {
+static arc arcs_73_7[2] = {
+	{22, 8},
+	{0, 7},
+};
+static arc arcs_73_8[1] = {
 	{23, 2},
 };
-static state states_75[8] = {
-	{1, arcs_75_0},
-	{3, arcs_75_1},
-	{1, arcs_75_2},
-	{2, arcs_75_3},
-	{2, arcs_75_4},
-	{2, arcs_75_5},
-	{2, arcs_75_6},
-	{1, arcs_75_7},
+static state states_73[9] = {
+	{1, arcs_73_0},
+	{4, arcs_73_1},
+	{1, arcs_73_2},
+	{1, arcs_73_3},
+	{2, arcs_73_4},
+	{2, arcs_73_5},
+	{2, arcs_73_6},
+	{2, arcs_73_7},
+	{1, arcs_73_8},
 };
-static arc arcs_76_0[1] = {
-	{162, 1},
+static arc arcs_74_0[1] = {
+	{159, 1},
 };
-static arc arcs_76_1[1] = {
+static arc arcs_74_1[1] = {
 	{19, 2},
 };
-static arc arcs_76_2[2] = {
+static arc arcs_74_2[2] = {
 	{13, 3},
 	{23, 4},
 };
-static arc arcs_76_3[2] = {
+static arc arcs_74_3[2] = {
 	{14, 5},
 	{15, 6},
 };
-static arc arcs_76_4[1] = {
+static arc arcs_74_4[1] = {
 	{24, 7},
 };
-static arc arcs_76_5[1] = {
+static arc arcs_74_5[1] = {
 	{15, 6},
 };
-static arc arcs_76_6[1] = {
+static arc arcs_74_6[1] = {
 	{23, 4},
 };
-static arc arcs_76_7[1] = {
+static arc arcs_74_7[1] = {
 	{0, 7},
 };
-static state states_76[8] = {
-	{1, arcs_76_0},
-	{1, arcs_76_1},
-	{2, arcs_76_2},
-	{2, arcs_76_3},
-	{1, arcs_76_4},
-	{1, arcs_76_5},
-	{1, arcs_76_6},
-	{1, arcs_76_7},
+static state states_74[8] = {
+	{1, arcs_74_0},
+	{1, arcs_74_1},
+	{2, arcs_74_2},
+	{2, arcs_74_3},
+	{1, arcs_74_4},
+	{1, arcs_74_5},
+	{1, arcs_74_6},
+	{1, arcs_74_7},
 };
-static arc arcs_77_0[3] = {
-	{163, 1},
+static arc arcs_75_0[3] = {
+	{160, 1},
 	{29, 2},
 	{31, 3},
 };
-static arc arcs_77_1[2] = {
+static arc arcs_75_1[2] = {
 	{28, 4},
 	{0, 1},
 };
-static arc arcs_77_2[1] = {
+static arc arcs_75_2[1] = {
 	{22, 5},
 };
-static arc arcs_77_3[1] = {
+static arc arcs_75_3[1] = {
 	{22, 6},
 };
-static arc arcs_77_4[4] = {
-	{163, 1},
+static arc arcs_75_4[4] = {
+	{160, 1},
 	{29, 2},
 	{31, 3},
 	{0, 4},
 };
-static arc arcs_77_5[2] = {
+static arc arcs_75_5[2] = {
 	{28, 7},
 	{0, 5},
 };
-static arc arcs_77_6[1] = {
+static arc arcs_75_6[1] = {
 	{0, 6},
 };
-static arc arcs_77_7[1] = {
+static arc arcs_75_7[1] = {
 	{31, 3},
 };
-static state states_77[8] = {
-	{3, arcs_77_0},
-	{2, arcs_77_1},
-	{1, arcs_77_2},
-	{1, arcs_77_3},
-	{4, arcs_77_4},
-	{2, arcs_77_5},
-	{1, arcs_77_6},
-	{1, arcs_77_7},
+static state states_75[8] = {
+	{3, arcs_75_0},
+	{2, arcs_75_1},
+	{1, arcs_75_2},
+	{1, arcs_75_3},
+	{4, arcs_75_4},
+	{2, arcs_75_5},
+	{1, arcs_75_6},
+	{1, arcs_75_7},
 };
-static arc arcs_78_0[1] = {
+static arc arcs_76_0[1] = {
 	{22, 1},
 };
-static arc arcs_78_1[3] = {
-	{158, 2},
+static arc arcs_76_1[3] = {
+	{155, 2},
 	{27, 3},
 	{0, 1},
 };
-static arc arcs_78_2[1] = {
+static arc arcs_76_2[1] = {
 	{0, 2},
 };
-static arc arcs_78_3[1] = {
+static arc arcs_76_3[1] = {
 	{22, 2},
 };
-static state states_78[4] = {
-	{1, arcs_78_0},
-	{3, arcs_78_1},
-	{1, arcs_78_2},
-	{1, arcs_78_3},
+static state states_76[4] = {
+	{1, arcs_76_0},
+	{3, arcs_76_1},
+	{1, arcs_76_2},
+	{1, arcs_76_3},
 };
-static arc arcs_79_0[2] = {
-	{157, 1},
-	{165, 1},
+static arc arcs_77_0[2] = {
+	{155, 1},
+	{162, 1},
 };
-static arc arcs_79_1[1] = {
+static arc arcs_77_1[1] = {
 	{0, 1},
 };
-static state states_79[2] = {
-	{2, arcs_79_0},
-	{1, arcs_79_1},
+static state states_77[2] = {
+	{2, arcs_77_0},
+	{1, arcs_77_1},
 };
-static arc arcs_80_0[1] = {
+static arc arcs_78_0[1] = {
 	{97, 1},
 };
-static arc arcs_80_1[1] = {
+static arc arcs_78_1[1] = {
 	{62, 2},
 };
-static arc arcs_80_2[1] = {
+static arc arcs_78_2[1] = {
 	{98, 3},
 };
-static arc arcs_80_3[1] = {
+static arc arcs_78_3[1] = {
 	{108, 4},
 };
-static arc arcs_80_4[2] = {
-	{164, 5},
-	{0, 4},
-};
-static arc arcs_80_5[1] = {
-	{0, 5},
-};
-static state states_80[6] = {
-	{1, arcs_80_0},
-	{1, arcs_80_1},
-	{1, arcs_80_2},
-	{1, arcs_80_3},
-	{2, arcs_80_4},
-	{1, arcs_80_5},
-};
-static arc arcs_81_0[1] = {
-	{93, 1},
-};
-static arc arcs_81_1[1] = {
-	{109, 2},
-};
-static arc arcs_81_2[2] = {
-	{164, 3},
-	{0, 2},
-};
-static arc arcs_81_3[1] = {
-	{0, 3},
-};
-static state states_81[4] = {
-	{1, arcs_81_0},
-	{1, arcs_81_1},
-	{2, arcs_81_2},
-	{1, arcs_81_3},
-};
-static arc arcs_82_0[2] = {
-	{158, 1},
-	{167, 1},
-};
-static arc arcs_82_1[1] = {
-	{0, 1},
-};
-static state states_82[2] = {
-	{2, arcs_82_0},
-	{1, arcs_82_1},
-};
-static arc arcs_83_0[1] = {
-	{97, 1},
-};
-static arc arcs_83_1[1] = {
-	{62, 2},
-};
-static arc arcs_83_2[1] = {
-	{98, 3},
-};
-static arc arcs_83_3[1] = {
-	{110, 4},
-};
-static arc arcs_83_4[2] = {
-	{166, 5},
+static arc arcs_78_4[2] = {
+	{161, 5},
 	{0, 4},
 };
-static arc arcs_83_5[1] = {
+static arc arcs_78_5[1] = {
 	{0, 5},
 };
-static state states_83[6] = {
-	{1, arcs_83_0},
-	{1, arcs_83_1},
-	{1, arcs_83_2},
-	{1, arcs_83_3},
-	{2, arcs_83_4},
-	{1, arcs_83_5},
+static state states_78[6] = {
+	{1, arcs_78_0},
+	{1, arcs_78_1},
+	{1, arcs_78_2},
+	{1, arcs_78_3},
+	{2, arcs_78_4},
+	{1, arcs_78_5},
 };
-static arc arcs_84_0[1] = {
+static arc arcs_79_0[1] = {
 	{93, 1},
 };
-static arc arcs_84_1[1] = {
-	{109, 2},
+static arc arcs_79_1[1] = {
+	{110, 2},
 };
-static arc arcs_84_2[2] = {
-	{166, 3},
+static arc arcs_79_2[2] = {
+	{161, 3},
 	{0, 2},
 };
-static arc arcs_84_3[1] = {
+static arc arcs_79_3[1] = {
 	{0, 3},
 };
-static state states_84[4] = {
-	{1, arcs_84_0},
-	{1, arcs_84_1},
-	{2, arcs_84_2},
-	{1, arcs_84_3},
+static state states_79[4] = {
+	{1, arcs_79_0},
+	{1, arcs_79_1},
+	{2, arcs_79_2},
+	{1, arcs_79_3},
 };
-static arc arcs_85_0[1] = {
+static arc arcs_80_0[1] = {
 	{22, 1},
 };
-static arc arcs_85_1[2] = {
+static arc arcs_80_1[2] = {
 	{28, 0},
 	{0, 1},
 };
-static state states_85[2] = {
-	{1, arcs_85_0},
-	{2, arcs_85_1},
+static state states_80[2] = {
+	{1, arcs_80_0},
+	{2, arcs_80_1},
 };
-static arc arcs_86_0[1] = {
+static arc arcs_81_0[1] = {
 	{19, 1},
 };
-static arc arcs_86_1[1] = {
+static arc arcs_81_1[1] = {
 	{0, 1},
 };
-static state states_86[2] = {
-	{1, arcs_86_0},
-	{1, arcs_86_1},
+static state states_81[2] = {
+	{1, arcs_81_0},
+	{1, arcs_81_1},
 };
-static arc arcs_87_0[1] = {
-	{170, 1},
+static arc arcs_82_0[1] = {
+	{165, 1},
 };
-static arc arcs_87_1[2] = {
+static arc arcs_82_1[2] = {
 	{9, 2},
 	{0, 1},
 };
-static arc arcs_87_2[1] = {
+static arc arcs_82_2[1] = {
 	{0, 2},
 };
-static state states_87[3] = {
-	{1, arcs_87_0},
-	{2, arcs_87_1},
-	{1, arcs_87_2},
+static state states_82[3] = {
+	{1, arcs_82_0},
+	{2, arcs_82_1},
+	{1, arcs_82_2},
 };
-static dfa dfas[88] = {
+static dfa dfas[83] = {
 	{256, "single_input", 0, 3, states_0,
-	 "\004\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"},
+	 "\004\050\014\000\000\000\000\240\340\251\160\040\113\000\041\000\000\206\120\206\040"},
 	{257, "file_input", 0, 2, states_1,
-	 "\204\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"},
+	 "\204\050\014\000\000\000\000\240\340\251\160\040\113\000\041\000\000\206\120\206\040"},
 	{258, "eval_input", 0, 3, states_2,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
 	{259, "decorator", 0, 7, states_3,
-	 "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{260, "decorators", 0, 2, states_4,
-	 "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{261, "funcdef", 0, 9, states_5,
-	 "\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\010\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{262, "parameters", 0, 4, states_6,
-	 "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{263, "typedargslist", 0, 12, states_7,
-	 "\000\040\010\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{264, "tname", 0, 4, states_8,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{265, "tfpdef", 0, 4, states_9,
-	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{266, "tfplist", 0, 3, states_10,
-	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{267, "varargslist", 0, 12, states_11,
-	 "\000\040\010\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{268, "vname", 0, 2, states_12,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{269, "vfpdef", 0, 4, states_13,
-	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{270, "vfplist", 0, 3, states_14,
-	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{271, "stmt", 0, 2, states_15,
-	 "\000\050\014\000\000\000\000\240\340\251\160\040\113\000\101\000\000\014\041\031\004\004"},
+	 "\000\050\014\000\000\000\000\240\340\251\160\040\113\000\041\000\000\206\120\206\040"},
 	{272, "simple_stmt", 0, 4, states_16,
-	 "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"},
+	 "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\041\000\000\206\120\006\040"},
 	{273, "small_stmt", 0, 2, states_17,
-	 "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"},
+	 "\000\040\010\000\000\000\000\240\340\251\160\000\000\000\041\000\000\206\120\006\040"},
 	{274, "expr_stmt", 0, 6, states_18,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
 	{275, "augassign", 0, 2, states_19,
-	 "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{276, "del_stmt", 0, 3, states_20,
-	 "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{277, "pass_stmt", 0, 2, states_21,
-	 "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{278, "flow_stmt", 0, 2, states_22,
-	 "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\000\004"},
+	 "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\040"},
 	{279, "break_stmt", 0, 2, states_23,
-	 "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{280, "continue_stmt", 0, 2, states_24,
-	 "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{281, "return_stmt", 0, 3, states_25,
-	 "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{282, "yield_stmt", 0, 2, states_26,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040"},
 	{283, "raise_stmt", 0, 7, states_27,
-	 "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"},
 	{284, "import_stmt", 0, 2, states_28,
-	 "\000\000\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\000\000\000\000"},
 	{285, "import_name", 0, 3, states_29,
-	 "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000"},
 	{286, "import_from", 0, 8, states_30,
-	 "\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"},
 	{287, "import_as_name", 0, 4, states_31,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{288, "dotted_as_name", 0, 4, states_32,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{289, "import_as_names", 0, 3, states_33,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{290, "dotted_as_names", 0, 2, states_34,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{291, "dotted_name", 0, 2, states_35,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
 	{292, "global_stmt", 0, 3, states_36,
-	 "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"},
 	{293, "nonlocal_stmt", 0, 3, states_37,
-	 "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
 	{294, "assert_stmt", 0, 5, states_38,
-	 "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000"},
 	{295, "compound_stmt", 0, 2, states_39,
-	 "\000\010\004\000\000\000\000\000\000\000\000\040\113\000\000\000\000\000\000\000\004\000"},
+	 "\000\010\004\000\000\000\000\000\000\000\000\040\113\000\000\000\000\000\000\200\000"},
 	{296, "if_stmt", 0, 8, states_40,
-	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
 	{297, "while_stmt", 0, 8, states_41,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"},
 	{298, "for_stmt", 0, 10, states_42,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
 	{299, "try_stmt", 0, 13, states_43,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000"},
 	{300, "with_stmt", 0, 6, states_44,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"},
 	{301, "with_var", 0, 3, states_45,
-	 "\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000"},
 	{302, "except_clause", 0, 5, states_46,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000"},
 	{303, "suite", 0, 5, states_47,
-	 "\004\040\010\000\000\000\000\240\340\251\160\000\000\000\101\000\000\014\041\031\000\004"},
-	{304, "testlist_safe", 0, 5, states_48,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{305, "old_test", 0, 2, states_49,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{306, "old_lambdef", 0, 5, states_50,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"},
-	{307, "test", 0, 6, states_51,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
+	 "\004\040\010\000\000\000\000\240\340\251\160\000\000\000\041\000\000\206\120\006\040"},
+	{304, "test", 0, 6, states_48,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{305, "test_nocond", 0, 2, states_49,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{306, "lambdef", 0, 5, states_50,
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"},
+	{307, "lambdef_nocond", 0, 5, states_51,
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"},
 	{308, "or_test", 0, 2, states_52,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\040\000\000\206\120\006\000"},
 	{309, "and_test", 0, 2, states_53,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\040\000\000\206\120\006\000"},
 	{310, "not_test", 0, 3, states_54,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\100\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\040\000\000\206\120\006\000"},
 	{311, "comparison", 0, 2, states_55,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{312, "comp_op", 0, 4, states_56,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\100\376\000\000\000\000\000\000"},
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\040\177\000\000\000\000\000"},
 	{313, "expr", 0, 2, states_57,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{314, "xor_expr", 0, 2, states_58,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{315, "and_expr", 0, 2, states_59,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{316, "shift_expr", 0, 2, states_60,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{317, "arith_expr", 0, 2, states_61,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{318, "term", 0, 2, states_62,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{319, "factor", 0, 3, states_63,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
 	{320, "power", 0, 4, states_64,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\040\031\000\000"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\006\000"},
 	{321, "atom", 0, 9, states_65,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\040\031\000\000"},
-	{322, "listmaker", 0, 5, states_66,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{323, "testlist_gexp", 0, 5, states_67,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{324, "lambdef", 0, 5, states_68,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"},
-	{325, "trailer", 0, 7, states_69,
-	 "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\040\000\000\000"},
-	{326, "subscriptlist", 0, 3, states_70,
-	 "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{327, "subscript", 0, 5, states_71,
-	 "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{328, "sliceop", 0, 3, states_72,
-	 "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
-	{329, "exprlist", 0, 3, states_73,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\014\041\031\000\000"},
-	{330, "testlist", 0, 3, states_74,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{331, "dictsetmaker", 0, 8, states_75,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{332, "classdef", 0, 8, states_76,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"},
-	{333, "arglist", 0, 8, states_77,
-	 "\000\040\010\240\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{334, "argument", 0, 4, states_78,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{335, "list_iter", 0, 2, states_79,
-	 "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"},
-	{336, "list_for", 0, 6, states_80,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
-	{337, "list_if", 0, 4, states_81,
-	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
-	{338, "gen_iter", 0, 2, states_82,
-	 "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000\000"},
-	{339, "gen_for", 0, 6, states_83,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"},
-	{340, "gen_if", 0, 4, states_84,
-	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"},
-	{341, "testlist1", 0, 2, states_85,
-	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\101\000\000\014\041\031\000\000"},
-	{342, "encoding_decl", 0, 2, states_86,
-	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
-	{343, "yield_expr", 0, 3, states_87,
-	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"},
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\006\000"},
+	{322, "testlist_comp", 0, 5, states_66,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{323, "trailer", 0, 7, states_67,
+	 "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000"},
+	{324, "subscriptlist", 0, 3, states_68,
+	 "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{325, "subscript", 0, 5, states_69,
+	 "\000\040\210\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{326, "sliceop", 0, 3, states_70,
+	 "\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	{327, "exprlist", 0, 3, states_71,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\006\000"},
+	{328, "testlist", 0, 3, states_72,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{329, "dictorsetmaker", 0, 9, states_73,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{330, "classdef", 0, 8, states_74,
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000"},
+	{331, "arglist", 0, 8, states_75,
+	 "\000\040\010\240\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{332, "argument", 0, 4, states_76,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{333, "comp_iter", 0, 2, states_77,
+	 "\000\000\000\000\000\000\000\000\000\000\000\040\002\000\000\000\000\000\000\000\000"},
+	{334, "comp_for", 0, 6, states_78,
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},
+	{335, "comp_if", 0, 4, states_79,
+	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
+	{336, "testlist1", 0, 2, states_80,
+	 "\000\040\010\000\000\000\000\000\000\200\000\000\000\000\041\000\000\206\120\006\000"},
+	{337, "encoding_decl", 0, 2, states_81,
+	 "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
+	{338, "yield_expr", 0, 3, states_82,
+	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040"},
 };
-static label labels[171] = {
+static label labels[166] = {
 	{0, "EMPTY"},
 	{256, 0},
 	{4, 0},
@@ -2053,12 +1940,12 @@
 	{271, 0},
 	{0, 0},
 	{258, 0},
-	{330, 0},
+	{328, 0},
 	{259, 0},
 	{50, 0},
 	{291, 0},
 	{7, 0},
-	{333, 0},
+	{331, 0},
 	{8, 0},
 	{260, 0},
 	{261, 0},
@@ -2066,7 +1953,7 @@
 	{1, 0},
 	{262, 0},
 	{51, 0},
-	{307, 0},
+	{304, 0},
 	{11, 0},
 	{303, 0},
 	{263, 0},
@@ -2092,7 +1979,7 @@
 	{293, 0},
 	{294, 0},
 	{275, 0},
-	{343, 0},
+	{338, 0},
 	{37, 0},
 	{38, 0},
 	{39, 0},
@@ -2106,7 +1993,7 @@
 	{47, 0},
 	{49, 0},
 	{1, "del"},
-	{329, 0},
+	{327, 0},
 	{1, "pass"},
 	{279, 0},
 	{280, 0},
@@ -2136,7 +2023,7 @@
 	{298, 0},
 	{299, 0},
 	{300, 0},
-	{332, 0},
+	{330, 0},
 	{1, "if"},
 	{1, "elif"},
 	{1, "else"},
@@ -2152,12 +2039,11 @@
 	{1, "except"},
 	{5, 0},
 	{6, 0},
-	{304, 0},
-	{305, 0},
 	{308, 0},
 	{306, 0},
+	{305, 0},
+	{307, 0},
 	{1, "lambda"},
-	{324, 0},
 	{309, 0},
 	{1, "or"},
 	{310, 0},
@@ -2191,34 +2077,30 @@
 	{32, 0},
 	{320, 0},
 	{321, 0},
-	{325, 0},
 	{323, 0},
-	{9, 0},
 	{322, 0},
+	{9, 0},
 	{10, 0},
 	{26, 0},
-	{331, 0},
+	{329, 0},
 	{27, 0},
 	{2, 0},
 	{3, 0},
-	{336, 0},
-	{339, 0},
+	{334, 0},
+	{324, 0},
+	{325, 0},
 	{326, 0},
-	{327, 0},
-	{328, 0},
 	{1, "class"},
-	{334, 0},
+	{332, 0},
+	{333, 0},
 	{335, 0},
+	{336, 0},
 	{337, 0},
-	{338, 0},
-	{340, 0},
-	{341, 0},
-	{342, 0},
 	{1, "yield"},
 };
 grammar _PyParser_Grammar = {
-	88,
+	83,
 	dfas,
-	{171, labels},
+	{166, labels},
 	256
 };

Modified: python/branches/p3yk/Python/symtable.c
==============================================================================
--- python/branches/p3yk/Python/symtable.c	(original)
+++ python/branches/p3yk/Python/symtable.c	Sun Apr 15 14:05:43 2007
@@ -76,7 +76,7 @@
 	ste->ste_generator = 0;
 	ste->ste_returns_value = 0;
 
-	if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0)
+	if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)
 	    goto fail;
 	
 	return ste;
@@ -172,6 +172,8 @@
 static int symtable_visit_stmt(struct symtable *st, stmt_ty s);
 static int symtable_visit_expr(struct symtable *st, expr_ty s);
 static int symtable_visit_genexp(struct symtable *st, expr_ty s);
+static int symtable_visit_listcomp(struct symtable *st, expr_ty s);
+static int symtable_visit_setcomp(struct symtable *st, expr_ty s);
 static int symtable_visit_arguments(struct symtable *st, arguments_ty);
 static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty);
 static int symtable_visit_alias(struct symtable *st, alias_ty);
@@ -186,7 +188,8 @@
 static int symtable_visit_annotations(struct symtable *st, stmt_ty s);
 
 
-static identifier top = NULL, lambda = NULL, genexpr = NULL;
+static identifier top = NULL, lambda = NULL, genexpr = NULL,
+    listcomp = NULL, setcomp = NULL;
 
 #define GET_IDENTIFIER(VAR) \
 	((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR)))
@@ -204,14 +207,13 @@
 		return NULL;
 
 	st->st_filename = NULL;
-	st->st_symbols = NULL;
+	st->st_blocks = NULL;
 
 	if ((st->st_stack = PyList_New(0)) == NULL)
 		goto fail;
-	if ((st->st_symbols = PyDict_New()) == NULL)
+	if ((st->st_blocks = PyDict_New()) == NULL)
 		goto fail; 
 	st->st_cur = NULL;
-	st->st_tmpname = 0;
 	st->st_private = NULL;
 	return st;
  fail:
@@ -230,6 +232,7 @@
 		return st;
 	st->st_filename = filename;
 	st->st_future = future;
+	/* Make the initial symbol information gathering pass */
 	if (!GET_IDENTIFIER(top) ||
 	    !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) {
 		PySymtable_Free(st);
@@ -238,7 +241,6 @@
 
 	st->st_top = st->st_cur;
 	st->st_cur->ste_unoptimized = OPT_TOPLEVEL;
-	/* Any other top-level initialization? */
 	switch (mod->kind) {
 	case Module_kind:
 		seq = mod->v.Module.body;
@@ -267,6 +269,7 @@
 		PySymtable_Free(st);
 		return NULL;
 	}
+	/* Make the second symbol analysis pass */
 	if (symtable_analyze(st))
 		return st;
 	PySymtable_Free(st);
@@ -280,7 +283,7 @@
 void
 PySymtable_Free(struct symtable *st)
 {
-	Py_XDECREF(st->st_symbols);
+	Py_XDECREF(st->st_blocks);
 	Py_XDECREF(st->st_stack);
 	PyMem_Free((void *)st);
 }
@@ -293,7 +296,7 @@
 	k = PyLong_FromVoidPtr(key);
 	if (k == NULL)
 		return NULL;
-	v = PyDict_GetItem(st->st_symbols, k);
+	v = PyDict_GetItem(st->st_blocks, k);
 	if (v) {
 		assert(PySTEntry_Check(v));
 		Py_INCREF(v);
@@ -314,7 +317,7 @@
 	if (!v)
 		return 0;
 	assert(PyInt_Check(v));
-	return (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
+	return (PyInt_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
 }
 
 
@@ -325,7 +328,7 @@
    it determines which local variables are cell variables; they provide
    bindings that are used for free variables in enclosed blocks.  
 
-   There are also two kinds of free variables, implicit and explicit.  An 
+   There are also two kinds of global variables, implicit and explicit.  An 
    explicit global is declared with the global statement.  An implicit
    global is a free variable for which the compiler has found no binding
    in an enclosing function scope.  The implicit global is either a global
@@ -337,24 +340,30 @@
    TODO(jhylton): Discuss nonlocal
 
    The symbol table requires two passes to determine the scope of each name.
-   The first pass collects raw facts from the AST: the name is a parameter 
-   here, the name is used by not defined here, etc.  The second pass analyzes
-   these facts during a pass over the PySTEntryObjects created during pass 1.
+   The first pass collects raw facts from the AST via the symtable_visit_*
+   functions: the name is a parameter here, the name is used but not defined
+   here, etc.  The second pass analyzes these facts during a pass over the
+   PySTEntryObjects created during pass 1.
 
    When a function is entered during the second pass, the parent passes
    the set of all name bindings visible to its children.  These bindings 
-   are used to determine if the variable is free or an implicit global.
+   are used to determine if non-local variables are free or implicit globals.
    After doing the local analysis, it analyzes each of its child blocks
-   using an updated set of name bindings.  
+   using an updated set of name bindings.
 
-   The children update the free variable set.  If a local variable is free 
-   in a child, the variable is marked as a cell.  The current function must 
-   provide runtime storage for the variable that may outlive the function's 
-   frame.  Cell variables are removed from the free set before the analyze
-   function returns to its parent.
+   The children update the free variable set.  If a local variable is added to
+   the free variable set by the child, the variable is marked as a cell.  The
+   function object being defined must provide runtime storage for the variable
+   that may outlive the function's frame.  Cell variables are removed from the
+   free set before the analyze function returns to its parent.
    
-   The sets of bound and free variables are implemented as dictionaries
-   mapping strings to None.
+   During analysis, the names are:
+      symbols: dict mapping from symbol names to flag values (including offset scope values)
+      scopes: dict mapping from symbol names to scope values (no offset)
+      local: set of all symbol names local to the current scope
+      bound: set of all symbol names local to a containing function scope
+      free: set of all symbol names referenced but not bound in child scopes
+      global: set of all symbol names explicitly declared as global
 */
 
 #define SET_SCOPE(DICT, NAME, I) { \
@@ -375,14 +384,14 @@
 */
 
 static int 
-analyze_name(PySTEntryObject *ste, PyObject *dict, PyObject *name, long flags,
+analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
 	     PyObject *bound, PyObject *local, PyObject *free, 
 	     PyObject *global)
 {
 	if (flags & DEF_GLOBAL) {
 		if (flags & DEF_PARAM) {
 			PyErr_Format(PyExc_SyntaxError,
-				     "name '%s' is local and global",
+				     "name '%s' is parameter and global",
 				     PyString_AS_STRING(name));
 			return 0;
 		}
@@ -392,41 +401,37 @@
 				     PyString_AS_STRING(name));
 			return 0;
                 }
-		SET_SCOPE(dict, name, GLOBAL_EXPLICIT);
-		if (PyDict_SetItem(global, name, Py_None) < 0)
+		SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
+		if (PySet_Add(global, name) < 0)
+			return 0;
+		if (bound && (PySet_Discard(bound, name) < 0))
 			return 0;
-		if (bound && PyDict_GetItem(bound, name)) {
-			if (PyDict_DelItem(bound, name) < 0)
-				return 0;
-		}
 		return 1;
 	}
         if (flags & DEF_NONLOCAL) {
 		if (flags & DEF_PARAM) {
 			PyErr_Format(PyExc_SyntaxError,
-				     "name '%s' is local and nonlocal",
+				     "name '%s' is parameter and nonlocal",
 				     PyString_AS_STRING(name));
 			return 0;
 		}
-                if (!PyDict_GetItem(bound, name)) {
+                if (!PySet_Contains(bound, name)) {
                         PyErr_Format(PyExc_SyntaxError,
                                      "no binding for nonlocal '%s' found",
 				     PyString_AS_STRING(name));
                                      
                         return 0;
                 }
-                SET_SCOPE(dict, name, FREE);
+                SET_SCOPE(scopes, name, FREE);
                 ste->ste_free = 1;
-                return PyDict_SetItem(free, name, Py_None) >= 0;
+                return PySet_Add(free, name) >= 0;
         }
 	if (flags & DEF_BOUND) {
-		SET_SCOPE(dict, name, LOCAL);
-		if (PyDict_SetItem(local, name, Py_None) < 0)
+		SET_SCOPE(scopes, name, LOCAL);
+		if (PySet_Add(local, name) < 0)
+			return 0;
+		if (PySet_Discard(global, name) < 0)
 			return 0;
-		if (PyDict_GetItem(global, name)) {
-			if (PyDict_DelItem(global, name) < 0)
-				return 0;
-		}
 		return 1;
 	}
 	/* If an enclosing block has a binding for this name, it
@@ -434,21 +439,21 @@
 	   Note that having a non-NULL bound implies that the block
 	   is nested.
 	*/
-	if (bound && PyDict_GetItem(bound, name)) {
-		SET_SCOPE(dict, name, FREE);
+	if (bound && PySet_Contains(bound, name)) {
+		SET_SCOPE(scopes, name, FREE);
 		ste->ste_free = 1;
-		return PyDict_SetItem(free, name, Py_None) >= 0;
+		return PySet_Add(free, name) >= 0;
 	}
 	/* If a parent has a global statement, then call it global
 	   explicit?  It could also be global implicit.
 	 */
-	if (global && PyDict_GetItem(global, name)) {
-		SET_SCOPE(dict, name, GLOBAL_EXPLICIT);
+	if (global && PySet_Contains(global, name)) {
+		SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
 		return 1;
 	}
 	if (ste->ste_nested)
 		ste->ste_free = 1;
-	SET_SCOPE(dict, name, GLOBAL_IMPLICIT);
+	SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
 	return 1;
 }
 
@@ -463,35 +468,35 @@
 */
 
 static int
-analyze_cells(PyObject *scope, PyObject *free)
+analyze_cells(PyObject *scopes, PyObject *free)
 {
-        PyObject *name, *v, *w;
+        PyObject *name, *v, *v_cell;
 	int success = 0;
 	Py_ssize_t pos = 0;
 
-	w = PyInt_FromLong(CELL);
-	if (!w)
+	v_cell = PyInt_FromLong(CELL);
+	if (!v_cell)
 		return 0;
-	while (PyDict_Next(scope, &pos, &name, &v)) {
-		long flags;
+	while (PyDict_Next(scopes, &pos, &name, &v)) {
+		long scope;
 		assert(PyInt_Check(v));
-		flags = PyInt_AS_LONG(v);
-		if (flags != LOCAL)
+		scope = PyInt_AS_LONG(v);
+		if (scope != LOCAL)
 			continue;
-		if (!PyDict_GetItem(free, name))
+		if (!PySet_Contains(free, name))
 			continue;
 		/* Replace LOCAL with CELL for this name, and remove
 		   from free. It is safe to replace the value of name 
 		   in the dict, because it will not cause a resize.
 		 */
-		if (PyDict_SetItem(scope, name, w) < 0)
+		if (PyDict_SetItem(scopes, name, v_cell) < 0)
 			goto error;
-		if (!PyDict_DelItem(free, name) < 0)
+		if (PySet_Discard(free, name) < 0)
 			goto error;
 	}
 	success = 1;
  error:
-	Py_DECREF(w);
+	Py_DECREF(v_cell);
 	return success;
 }
 
@@ -526,77 +531,91 @@
 	return 0;
 }
 
-/* Enter the final scope information into the st_symbols dict. 
+/* Enter the final scope information into the ste_symbols dict. 
  * 
  * All arguments are dicts.  Modifies symbols, others are read-only.
 */
 static int
-update_symbols(PyObject *symbols, PyObject *scope, 
+update_symbols(PyObject *symbols, PyObject *scopes, 
                PyObject *bound, PyObject *free, int classflag)
 {
-	PyObject *name, *v, *u, *w, *free_value = NULL;
+	PyObject *name = NULL, *itr = NULL;
+	PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL;
 	Py_ssize_t pos = 0;
 
+	/* Update scope information for all symbols in this scope */
 	while (PyDict_Next(symbols, &pos, &name, &v)) {
-		long i, flags;
+		long scope, flags;
 		assert(PyInt_Check(v));
 		flags = PyInt_AS_LONG(v);
-		w = PyDict_GetItem(scope, name);
-		assert(w && PyInt_Check(w));
-		i = PyInt_AS_LONG(w);
-		flags |= (i << SCOPE_OFF);
-		u = PyInt_FromLong(flags);
-		if (!u)
+		v_scope = PyDict_GetItem(scopes, name);
+		assert(v_scope && PyInt_Check(v_scope));
+		scope = PyInt_AS_LONG(v_scope);
+		flags |= (scope << SCOPE_OFFSET);
+		v_new = PyInt_FromLong(flags);
+		if (!v_new)
 			return 0;
-		if (PyDict_SetItem(symbols, name, u) < 0) {
-			Py_DECREF(u);
+		if (PyDict_SetItem(symbols, name, v_new) < 0) {
+			Py_DECREF(v_new);
 			return 0;
 		}
-		Py_DECREF(u);
+		Py_DECREF(v_new);
 	}
 
-        free_value = PyInt_FromLong(FREE << SCOPE_OFF);
-        if (!free_value)
+	/* Record not yet resolved free variables from children (if any) */
+        v_free = PyInt_FromLong(FREE << SCOPE_OFFSET);
+        if (!v_free)
 		return 0;
 
-        /* add a free variable when it's only use is for creating a closure */
-        pos = 0;
-	while (PyDict_Next(free, &pos, &name, &v)) {
-		PyObject *o = PyDict_GetItem(symbols, name);
+	itr = PyObject_GetIter(free);
+	if (!itr)
+		goto error;
+
+	while ((name = PyIter_Next(itr))) {
+		v = PyDict_GetItem(symbols, name);
 
-		if (o) {
-			/* It could be a free variable in a method of
+		/* Handle symbol that already exists in this scope */
+		if (v) {
+			/* Handle a free variable in a method of
 			   the class that has the same name as a local
 			   or global in the class scope.
 			*/
 			if  (classflag && 
-			     PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) {
-				long i = PyInt_AS_LONG(o) | DEF_FREE_CLASS;
-				o = PyInt_FromLong(i);
-				if (!o) {
-					Py_DECREF(free_value);
-					return 0;
+			     PyInt_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) {
+				long flags = PyInt_AS_LONG(v) | DEF_FREE_CLASS;
+				v_new = PyInt_FromLong(flags);
+				if (!v_new) {
+					goto error;
 				}
-				if (PyDict_SetItem(symbols, name, o) < 0) {
-					Py_DECREF(o);
-					Py_DECREF(free_value);
-					return 0;
+				if (PyDict_SetItem(symbols, name, v_new) < 0) {
+					Py_DECREF(v_new);
+					goto error;
 				}
-				Py_DECREF(o);
+				Py_DECREF(v_new);
 			}
-			/* else it's not free, probably a cell */
+			/* It's a cell, or already a free variable in this scope */
+			Py_DECREF(name);
 			continue;
 		}
-		if (!PyDict_GetItem(bound, name))
+		/* Handle global symbol */
+		if (!PySet_Contains(bound, name)) {
+			Py_DECREF(name);
 			continue;       /* it's a global */
-
-		if (PyDict_SetItem(symbols, name, free_value) < 0) {
-			Py_DECREF(free_value);
-			return 0;
 		}
+		/* Propagate new free symbol up the lexical stack */
+		if (PyDict_SetItem(symbols, name, v_free) < 0) {
+			goto error;
+		}
+		Py_DECREF(name);
         }
-        Py_DECREF(free_value);
+	Py_DECREF(itr);
+        Py_DECREF(v_free);
 	return 1;
+error:
+	Py_XDECREF(v_free);
+	Py_XDECREF(itr);
+	Py_XDECREF(name);
+	return 0;
 }   
 
 /* Make final symbol table decisions for block of ste.
@@ -611,59 +630,74 @@
 analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, 
 	      PyObject *global)
 {
-	PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL;
+	PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL;
 	PyObject *newglobal = NULL, *newfree = NULL;
 	int i, success = 0;
 	Py_ssize_t pos = 0;
 
-	local = PyDict_New();
-	if (!local)
+	scopes = PyDict_New();
+	if (!scopes)
 		goto error;
-	scope = PyDict_New();
-	if (!scope)
+	local = PySet_New(NULL);
+	if (!local)
 		goto error;
-	newglobal = PyDict_New();
+	newglobal = PySet_New(NULL);
 	if (!newglobal)
 		goto error;
-	newfree = PyDict_New();
+	newfree = PySet_New(NULL);
 	if (!newfree)
 		goto error;
-	newbound = PyDict_New();
+	newbound = PySet_New(NULL);
 	if (!newbound)
 		goto error;
 
+	/* Class namespace has no effect on names visible in
+	   nested functions, so populate the global and bound
+	   sets to be passed to child blocks before analyzing
+	   this one.
+	 */
 	if (ste->ste_type == ClassBlock) {
-		/* make a copy of globals before calling analyze_name(),
-		   because global statements in the class have no effect
-		   on nested functions.
-		*/
-		if (PyDict_Update(newglobal, global) < 0)
-			goto error;
-		if (bound)
-			if (PyDict_Update(newbound, bound) < 0)
+		/* Pass down previously bound symbols */
+		if (bound) {
+			if (!PyNumber_InPlaceOr(newbound, bound))
 				goto error;
+			Py_DECREF(newbound);
+		}
+		/* Pass down known globals */
+		if (!PyNumber_InPlaceOr(newglobal, global))
+			goto error;
+		Py_DECREF(newglobal);
 	}
 
+	/* Analyze symbols in current scope */
 	assert(PySTEntry_Check(ste));
 	assert(PyDict_Check(ste->ste_symbols));
 	while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
 		long flags = PyInt_AS_LONG(v);
-		if (!analyze_name(ste, scope, name, flags, bound, local, free,
+		if (!analyze_name(ste, scopes, name, flags, bound, local, free,
 				  global))
 			goto error;
 	}
 
+	/* Populate global and bound sets to be passed to children.
+	 */
 	if (ste->ste_type != ClassBlock) {
+		/* Add function locals to bound set */
 		if (ste->ste_type == FunctionBlock) {
-			if (PyDict_Update(newbound, local) < 0)
+			if (!PyNumber_InPlaceOr(newbound, local))
 				goto error;
+			Py_DECREF(newbound);
 		}
+		/* Pass down previously bound symbols */
 		if (bound) {
-			if (PyDict_Update(newbound, bound) < 0)
+			if (!PyNumber_InPlaceOr(newbound, bound))
 				goto error;
+			Py_DECREF(newbound);
 		}
-		if (PyDict_Update(newglobal, global) < 0)
+		/* Pass down known globals */
+		if (!PyNumber_InPlaceOr(newglobal, global))
 			goto error;
+		Py_DECREF(newglobal);
 	}
 
 	/* Recursively call analyze_block() on each child block */
@@ -674,24 +708,28 @@
 		entry = (PySTEntryObject*)c;
 		if (!analyze_block(entry, newbound, newfree, newglobal))
 			goto error;
+		/* Check if any children have free variables */
 		if (entry->ste_free || entry->ste_child_free)
 			ste->ste_child_free = 1;
 	}
 
-	if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree))
+	/* Check if any local variables need to be converted to cell variables */
+	if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree))
 		goto error;
-	if (!update_symbols(ste->ste_symbols, scope, bound, newfree,
+	/* Records the results of the analysis in the symbol table entry */
+	if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
 			    ste->ste_type == ClassBlock))
 		goto error;
 	if (!check_unoptimized(ste))
 		goto error;
 
-	if (PyDict_Update(free, newfree) < 0)
+	if (!PyNumber_InPlaceOr(free, newfree))
 		goto error;
+	Py_DECREF(free);
 	success = 1;
  error:
+	Py_XDECREF(scopes);
 	Py_XDECREF(local);
-	Py_XDECREF(scope);
 	Py_XDECREF(newbound);
 	Py_XDECREF(newglobal);
 	Py_XDECREF(newfree);
@@ -706,10 +744,10 @@
 	PyObject *free, *global;
 	int r;
 
-	free = PyDict_New();
+	free = PySet_New(NULL);
 	if (!free)
 	    return 0;
-	global = PyDict_New();
+	global = PySet_New(NULL);
 	if (!global) {
 	    Py_DECREF(free);
 	    return 0;
@@ -1200,14 +1238,16 @@
 	case Set_kind:
 		VISIT_SEQ(st, expr, e->v.Set.elts);
 		break;
+        case GeneratorExp_kind:
+		if (!symtable_visit_genexp(st, e))
+			return 0;
+		break;
         case ListComp_kind:
-		if (!symtable_new_tmpname(st))
+		if (!symtable_visit_listcomp(st, e))
 			return 0;
-		VISIT(st, expr, e->v.ListComp.elt);
-		VISIT_SEQ(st, comprehension, e->v.ListComp.generators);
 		break;
-        case GeneratorExp_kind:
-		if (!symtable_visit_genexp(st, e))
+	case SetComp_kind:
+		if (!symtable_visit_setcomp(st, e))
 			return 0;
 		break;
         case Yield_kind:
@@ -1479,27 +1519,60 @@
 }
 
 static int 
-symtable_visit_genexp(struct symtable *st, expr_ty e)
+symtable_handle_comprehension(struct symtable *st, expr_ty e,
+                              identifier scope_name,
+                              asdl_seq *generators, expr_ty elt)
 {
+	int is_generator = (e->kind == GeneratorExp_kind);
+	int needs_tmp = !is_generator;
 	comprehension_ty outermost = ((comprehension_ty)
-			 (asdl_seq_GET(e->v.GeneratorExp.generators, 0)));
+                                        asdl_seq_GET(generators, 0));
 	/* Outermost iterator is evaluated in current scope */
 	VISIT(st, expr, outermost->iter);
-	/* Create generator scope for the rest */
-	if (!GET_IDENTIFIER(genexpr) ||
-	    !symtable_enter_block(st, genexpr, FunctionBlock, (void *)e, 0)) {
+	/* Create comprehension scope for the rest */
+	if (!scope_name ||
+	    !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) {
 		return 0;
 	}
-	st->st_cur->ste_generator = 1;
+	st->st_cur->ste_generator = is_generator;
 	/* Outermost iter is received as an argument */
 	if (!symtable_implicit_arg(st, 0)) {
 		symtable_exit_block(st, (void *)e);
 		return 0;
 	}
+	/* Allocate temporary name if needed */
+	if (needs_tmp && !symtable_new_tmpname(st)) {
+		symtable_exit_block(st, (void *)e);
+		return 0;
+	}
 	VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
 	VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
 	VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
-				e->v.GeneratorExp.generators, 1, (void*)e);
-	VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e);
+				generators, 1, (void*)e);
+	VISIT_IN_BLOCK(st, expr, elt, (void*)e);
 	return symtable_exit_block(st, (void *)e);
 }
+
+static int 
+symtable_visit_genexp(struct symtable *st, expr_ty e)
+{
+	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr),
+                                             e->v.GeneratorExp.generators,
+                                             e->v.GeneratorExp.elt);
+}
+
+static int 
+symtable_visit_listcomp(struct symtable *st, expr_ty e)
+{
+	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(listcomp),
+                                             e->v.ListComp.generators,
+                                             e->v.ListComp.elt);
+}
+
+static int
+symtable_visit_setcomp(struct symtable *st, expr_ty e)
+{
+	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp),
+					     e->v.SetComp.generators,
+					     e->v.SetComp.elt);
+}

Modified: python/branches/p3yk/setup.py
==============================================================================
--- python/branches/p3yk/setup.py	(original)
+++ python/branches/p3yk/setup.py	Sun Apr 15 14:05:43 2007
@@ -1175,8 +1175,8 @@
         #
         include_dirs = [
             join(F, fw + '.framework', H)
-            for fw in 'Tcl', 'Tk'
-            for H in 'Headers', 'Versions/Current/PrivateHeaders'
+            for fw in ('Tcl', 'Tk')
+            for H in ('Headers', 'Versions/Current/PrivateHeaders')
         ]
 
         # For 8.4a2, the X11 headers are not included. Rather than include a


More information about the Python-3000-checkins mailing list