Many changes -- bug fixes and sundry improvements

Make nested scopes enabled by default

Add is_constant_false() helper so that compiled code and symbols are
consistent with builtin compiler's handling of "if 0:"

Fix doc string handling to be consistent with recent change that
eliminates the doc string from the Module's node attribute.

Add fix to print handling from Evan & Shane.

Track change to visitor api by making "verbose" explicit.

Comment out setting CO_NESTED flag (it's unnecessary in 2.2).
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 9f58067..67a1033 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -40,18 +40,14 @@
 
 class Module:
     def __init__(self, source, filename):
-        self.filename = filename
+        self.filename = os.path.abspath(filename)
         self.source = source
         self.code = None
 
     def compile(self, display=0):
         tree = parse(self.source)
-        root, filename = os.path.split(self.filename)
-        if "nested_scopes" in future.find_futures(tree):
-            gen = NestedScopeModuleCodeGenerator(filename)
-        else:
-            gen = ModuleCodeGenerator(filename)
-        walk(tree, gen, 1)
+        gen = NestedScopeModuleCodeGenerator(self.filename)
+        walk(tree, gen, verbose=1)
         if display:
             import pprint
             print pprint.pprint(tree)
@@ -115,6 +111,12 @@
     def visitAssName(self, node):
         self.names.add(node.name)
 
+def is_constant_false(node):
+    if isinstance(node, ast.Const):
+        if not node.value:
+            return 1
+    return 0
+
 class CodeGenerator:
     """Defines basic code generator for Python bytecode
 
@@ -234,10 +236,11 @@
 
     def visitModule(self, node):
         self.emit('SET_LINENO', 0)
-        lnf = walk(node.node, self.NameFinder(), 0)
-        self.locals.push(lnf.getLocals())
         if node.doc:
-            self.fixDocstring(node.node)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
+        lnf = walk(node.node, self.NameFinder(), verbose=0)
+        self.locals.push(lnf.getLocals())
         self.visit(node.node)
         self.emit('LOAD_CONST', None)
         self.emit('RETURN_VALUE')
@@ -264,7 +267,8 @@
     def visitClass(self, node):
         gen = self.ClassGen(node, self.filename, self.scopes)
         if node.doc:
-            self.fixDocstring(node.code)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -278,19 +282,6 @@
         self.emit('BUILD_CLASS')
         self.storeName(node.name)
 
-    def fixDocstring(self, node):
-        """Rewrite the ast for a class with a docstring.
-
-        The AST includes a Discard(Const(docstring)) node.  Replace
-        this with an Assign([AssName('__doc__', ...])
-        """
-        assert isinstance(node, ast.Stmt)
-        stmts = node.nodes
-        discard = stmts[0]
-        assert isinstance(discard, ast.Discard)
-        stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
-                              discard.expr)
-        stmts[0].lineno = discard.lineno
     # The rest are standard visitor methods
 
     # The next few implement control-flow statements
@@ -300,6 +291,9 @@
         numtests = len(node.tests)
         for i in range(numtests):
             test, suite = node.tests[i]
+            if is_constant_false(test):
+                # XXX will need to check generator stuff here
+                continue
             self.set_lineno(test)
             self.visit(test)
             nextTest = self.newBlock()
@@ -793,7 +787,7 @@
         opcode = callfunc_opcode_info[have_star, have_dstar]
         self.emit(opcode, kw << 8 | pos)
 
-    def visitPrint(self, node):
+    def visitPrint(self, node, newline=0):
         self.set_lineno(node)
         if node.dest:
             self.visit(node.dest)
@@ -806,9 +800,11 @@
                 self.emit('PRINT_ITEM_TO')
             else:
                 self.emit('PRINT_ITEM')
+        if node.dest and not newline:
+            self.emit('POP_TOP')
 
     def visitPrintnl(self, node):
-        self.visitPrint(node)
+        self.visitPrint(node, newline=1)
         if node.dest:
             self.emit('PRINT_NEWLINE_TO')
         else:
@@ -1021,7 +1017,8 @@
     def visitClass(self, node):
         gen = self.ClassGen(node, self.filename, self.scopes)
         if node.doc:
-            self.fixDocstring(node.code)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -1072,7 +1069,7 @@
     def __init__(self, filename):
         self.graph = pyassem.PyFlowGraph("<module>", filename)
         self.__super_init(filename)
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 class AbstractFunctionCode:
     optimized = 1
@@ -1094,7 +1091,7 @@
         if not isLambda and func.doc:
             self.setDocstring(func.doc)
 
-        lnf = walk(func.code, self.NameFinder(args), 0)
+        lnf = walk(func.code, self.NameFinder(args), verbose=0)
         self.locals.push(lnf.getLocals())
         if func.varargs:
             self.graph.setFlag(CO_VARARGS)
@@ -1147,7 +1144,7 @@
         self.__super_init(func, filename, scopes, isLambda)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 class AbstractClassCode:
 
@@ -1155,7 +1152,7 @@
         self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                            optimized=0)
         self.super_init(filename)
-        lnf = walk(klass.code, self.NameFinder(), 0)
+        lnf = walk(klass.code, self.NameFinder(), verbose=0)
         self.locals.push(lnf.getLocals())
         self.graph.setFlag(CO_NEWLOCALS)
         if klass.doc:
@@ -1186,7 +1183,7 @@
         self.__super_init(klass, filename, scopes)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 def generateArgList(arglist):
     """Generate an arg list marking TupleArgs"""
@@ -1208,7 +1205,7 @@
 def findOp(node):
     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
     v = OpFinder()
-    walk(node, v, 0)
+    walk(node, v, verbose=0)
     return v.op
 
 class OpFinder:
diff --git a/Tools/compiler/compiler/pycodegen.py b/Tools/compiler/compiler/pycodegen.py
index 9f58067..67a1033 100644
--- a/Tools/compiler/compiler/pycodegen.py
+++ b/Tools/compiler/compiler/pycodegen.py
@@ -40,18 +40,14 @@
 
 class Module:
     def __init__(self, source, filename):
-        self.filename = filename
+        self.filename = os.path.abspath(filename)
         self.source = source
         self.code = None
 
     def compile(self, display=0):
         tree = parse(self.source)
-        root, filename = os.path.split(self.filename)
-        if "nested_scopes" in future.find_futures(tree):
-            gen = NestedScopeModuleCodeGenerator(filename)
-        else:
-            gen = ModuleCodeGenerator(filename)
-        walk(tree, gen, 1)
+        gen = NestedScopeModuleCodeGenerator(self.filename)
+        walk(tree, gen, verbose=1)
         if display:
             import pprint
             print pprint.pprint(tree)
@@ -115,6 +111,12 @@
     def visitAssName(self, node):
         self.names.add(node.name)
 
+def is_constant_false(node):
+    if isinstance(node, ast.Const):
+        if not node.value:
+            return 1
+    return 0
+
 class CodeGenerator:
     """Defines basic code generator for Python bytecode
 
@@ -234,10 +236,11 @@
 
     def visitModule(self, node):
         self.emit('SET_LINENO', 0)
-        lnf = walk(node.node, self.NameFinder(), 0)
-        self.locals.push(lnf.getLocals())
         if node.doc:
-            self.fixDocstring(node.node)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
+        lnf = walk(node.node, self.NameFinder(), verbose=0)
+        self.locals.push(lnf.getLocals())
         self.visit(node.node)
         self.emit('LOAD_CONST', None)
         self.emit('RETURN_VALUE')
@@ -264,7 +267,8 @@
     def visitClass(self, node):
         gen = self.ClassGen(node, self.filename, self.scopes)
         if node.doc:
-            self.fixDocstring(node.code)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -278,19 +282,6 @@
         self.emit('BUILD_CLASS')
         self.storeName(node.name)
 
-    def fixDocstring(self, node):
-        """Rewrite the ast for a class with a docstring.
-
-        The AST includes a Discard(Const(docstring)) node.  Replace
-        this with an Assign([AssName('__doc__', ...])
-        """
-        assert isinstance(node, ast.Stmt)
-        stmts = node.nodes
-        discard = stmts[0]
-        assert isinstance(discard, ast.Discard)
-        stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
-                              discard.expr)
-        stmts[0].lineno = discard.lineno
     # The rest are standard visitor methods
 
     # The next few implement control-flow statements
@@ -300,6 +291,9 @@
         numtests = len(node.tests)
         for i in range(numtests):
             test, suite = node.tests[i]
+            if is_constant_false(test):
+                # XXX will need to check generator stuff here
+                continue
             self.set_lineno(test)
             self.visit(test)
             nextTest = self.newBlock()
@@ -793,7 +787,7 @@
         opcode = callfunc_opcode_info[have_star, have_dstar]
         self.emit(opcode, kw << 8 | pos)
 
-    def visitPrint(self, node):
+    def visitPrint(self, node, newline=0):
         self.set_lineno(node)
         if node.dest:
             self.visit(node.dest)
@@ -806,9 +800,11 @@
                 self.emit('PRINT_ITEM_TO')
             else:
                 self.emit('PRINT_ITEM')
+        if node.dest and not newline:
+            self.emit('POP_TOP')
 
     def visitPrintnl(self, node):
-        self.visitPrint(node)
+        self.visitPrint(node, newline=1)
         if node.dest:
             self.emit('PRINT_NEWLINE_TO')
         else:
@@ -1021,7 +1017,8 @@
     def visitClass(self, node):
         gen = self.ClassGen(node, self.filename, self.scopes)
         if node.doc:
-            self.fixDocstring(node.code)
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
         walk(node.code, gen)
         gen.finish()
         self.set_lineno(node)
@@ -1072,7 +1069,7 @@
     def __init__(self, filename):
         self.graph = pyassem.PyFlowGraph("<module>", filename)
         self.__super_init(filename)
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 class AbstractFunctionCode:
     optimized = 1
@@ -1094,7 +1091,7 @@
         if not isLambda and func.doc:
             self.setDocstring(func.doc)
 
-        lnf = walk(func.code, self.NameFinder(args), 0)
+        lnf = walk(func.code, self.NameFinder(args), verbose=0)
         self.locals.push(lnf.getLocals())
         if func.varargs:
             self.graph.setFlag(CO_VARARGS)
@@ -1147,7 +1144,7 @@
         self.__super_init(func, filename, scopes, isLambda)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 class AbstractClassCode:
 
@@ -1155,7 +1152,7 @@
         self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                            optimized=0)
         self.super_init(filename)
-        lnf = walk(klass.code, self.NameFinder(), 0)
+        lnf = walk(klass.code, self.NameFinder(), verbose=0)
         self.locals.push(lnf.getLocals())
         self.graph.setFlag(CO_NEWLOCALS)
         if klass.doc:
@@ -1186,7 +1183,7 @@
         self.__super_init(klass, filename, scopes)
         self.graph.setFreeVars(self.scope.get_free_vars())
         self.graph.setCellVars(self.scope.get_cell_vars())
-        self.graph.setFlag(CO_NESTED)
+##        self.graph.setFlag(CO_NESTED)
 
 def generateArgList(arglist):
     """Generate an arg list marking TupleArgs"""
@@ -1208,7 +1205,7 @@
 def findOp(node):
     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
     v = OpFinder()
-    walk(node, v, 0)
+    walk(node, v, verbose=0)
     return v.op
 
 class OpFinder: