[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler pyassem.py,1.26,1.27 pycodegen.py,1.49,1.50

Jeremy Hylton jhylton@users.sourceforge.net
Fri, 14 Sep 2001 15:49:10 -0700


Update of /cvsroot/python/python/dist/src/Tools/compiler/compiler
In directory usw-pr-cvs1:/tmp/cvs-serv23974

Modified Files:
	pyassem.py pycodegen.py 
Log Message:
Various sundry changes for 2.2 compatibility

Remove the option to have nested scopes or old LGB scopes.  This has a
large impact on the code base, by removing the need for two variants
of each CodeGenerator.

Add a get_module() method to CodeGenerator objects, used to get the
future features for the current module.

Set CO_GENERATOR, CO_GENERATOR_ALLOWED, and CO_FUTURE_DIVISION flags
as appropriate.

Attempt to fix the value of nlocals in newCodeObject(), assuming that
nlocals is 0 if CO_NEWLOCALS is not defined.


Index: pyassem.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pyassem.py,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -d -r1.26 -r1.27
*** pyassem.py	2001/08/30 20:25:54	1.26
--- pyassem.py	2001/09/14 22:49:08	1.27
***************
*** 362,365 ****
--- 362,369 ----
              self.argcount = self.argcount - 1
  
+     def checkFlag(self, flag):
+         if self.flags & flag:
+             return 1
+ 
      def setFreeVars(self, names):
          self.freevars = list(names)
***************
*** 565,569 ****
      def newCodeObject(self):
          assert self.stage == DONE
!         if self.flags == 0:
              nlocals = 0
          else:
--- 569,573 ----
      def newCodeObject(self):
          assert self.stage == DONE
!         if (self.flags & CO_NEWLOCALS) == 0:
              nlocals = 0
          else:
***************
*** 762,768 ****
          ]
      
-     # special cases:
-     # UNPACK_SEQUENCE, BUILD_TUPLE,
-     # BUILD_LIST, CALL_FUNCTION, MAKE_FUNCTION, BUILD_SLICE
      def UNPACK_SEQUENCE(self, count):
          return count-1
--- 766,769 ----

Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pycodegen.py,v
retrieving revision 1.49
retrieving revision 1.50
diff -C2 -d -r1.49 -r1.50
*** pycodegen.py	2001/08/30 20:25:55	1.49
--- pycodegen.py	2001/09/14 22:49:08	1.50
***************
*** 13,17 ****
  from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
  from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
!      CO_NESTED, CO_GENERATOR
  from compiler.pyassem import TupleArg
  
--- 13,17 ----
  from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
  from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
!      CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
  from compiler.pyassem import TupleArg
  
***************
*** 35,38 ****
--- 35,47 ----
  END_FINALLY = 4
  
+ class BlockStack(misc.Stack):
+     __super_init = misc.Stack.__init__
+     
+     def __init__(self):
+         self.__super_init(self)
+         self.loop = None
+ 
+     
+ 
  def compile(filename, display=0):
      f = open(filename)
***************
*** 53,58 ****
      def compile(self, display=0):
          tree = parse(self.source)
!         gen = NestedScopeModuleCodeGenerator(self.filename)
!         walk(tree, gen, verbose=1)
          if display:
              import pprint
--- 62,66 ----
      def compile(self, display=0):
          tree = parse(self.source)
!         gen = ModuleCodeGenerator(self.filename, tree)
          if display:
              import pprint
***************
*** 155,158 ****
--- 163,174 ----
          self._setupGraphDelegation()
  
+         # XXX set flags based on future features
+         futures = self.get_module().futures
+         for feature in futures:
+             if feature == "division":
+                 self.graph.setFlag(CO_FUTURE_DIVISION)
+             elif feature == "generators":
+                 self.graph.setFlag(CO_GENERATOR_ALLOWED)
+ 
      def initClass(self):
          """This method is called once for each class"""
***************
*** 186,189 ****
--- 202,213 ----
              return name
  
+     def parseSymbols(self, tree):
+         s = symbols.SymbolVisitor()
+         walk(tree, s)
+         return s.scopes
+ 
+     def get_module(self):
+         raise RuntimeError, "should be implemented by subclasses"
+ 
      # Next five methods handle name access
  
***************
*** 202,212 ****
      def _nameOp(self, prefix, name):
          name = self.mangle(name)
!         if not self.optimized:
!             self.emit(prefix + '_NAME', name)
!             return
!         if self.isLocalName(name):
!             self.emit(prefix + '_FAST', name)
          else:
!             self.emit(prefix + '_GLOBAL', name)
  
      def _implicitNameOp(self, prefix, name):
--- 226,245 ----
      def _nameOp(self, prefix, name):
          name = self.mangle(name)
!         scope = self.scope.check_name(name)
!         if scope == SC_LOCAL:
!             if not self.optimized:
!                 self.emit(prefix + '_NAME', name)
!             else:
!                 self.emit(prefix + '_FAST', name)
!         elif scope == SC_GLOBAL:
!             if not self.optimized:
!                 self.emit(prefix + '_NAME', name)
!             else:
!                 self.emit(prefix + '_GLOBAL', name)
!         elif scope == SC_FREE or scope == SC_CELL:
!             self.emit(prefix + '_DEREF', name)
          else:
!             raise RuntimeError, "unsupported scope for var %s: %d" % \
!                   (name, scope)
  
      def _implicitNameOp(self, prefix, name):
***************
*** 250,253 ****
--- 283,288 ----
  
      def visitModule(self, node):
+         self.scopes = self.parseSymbols(node)
+         self.scope = self.scopes[node]
          self.emit('SET_LINENO', 0)
          if node.doc:
***************
*** 271,275 ****
      def _visitFuncOrLambda(self, node, isLambda=0):
          gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
!                                self.class_name)
          walk(node.code, gen)
          gen.finish()
--- 306,310 ----
      def _visitFuncOrLambda(self, node, isLambda=0):
          gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
!                                self.class_name, self.get_module())
          walk(node.code, gen)
          gen.finish()
***************
*** 277,285 ****
          for default in node.defaults:
              self.visit(default)
!         self.emit('LOAD_CONST', gen)
!         self.emit('MAKE_FUNCTION', len(node.defaults))
  
      def visitClass(self, node):
!         gen = self.ClassGen(node, self.filename, self.scopes)
          if node.doc:
              self.emit('LOAD_CONST', node.doc)
--- 312,328 ----
          for default in node.defaults:
              self.visit(default)
!         frees = gen.scope.get_free_vars()
!         if frees:
!             for name in frees:
!                 self.emit('LOAD_CLOSURE', name)
!             self.emit('LOAD_CONST', gen)
!             self.emit('MAKE_CLOSURE', len(node.defaults))
!         else:
!             self.emit('LOAD_CONST', gen)
!             self.emit('MAKE_FUNCTION', len(node.defaults))
  
      def visitClass(self, node):
!         gen = self.ClassGen(node, self.filename, self.scopes,
!                             self.get_module())
          if node.doc:
              self.emit('LOAD_CONST', node.doc)
***************
*** 292,297 ****
              self.visit(base)
          self.emit('BUILD_TUPLE', len(node.bases))
          self.emit('LOAD_CONST', gen)
!         self.emit('MAKE_FUNCTION', 0)
          self.emit('CALL_FUNCTION', 0)
          self.emit('BUILD_CLASS')
--- 335,346 ----
              self.visit(base)
          self.emit('BUILD_TUPLE', len(node.bases))
+         frees = gen.scope.get_free_vars()
+         for name in frees:
+             self.emit('LOAD_CLOSURE', name)
          self.emit('LOAD_CONST', gen)
!         if frees:
!             self.emit('MAKE_CLOSURE', 0)
!         else:
!             self.emit('MAKE_FUNCTION', 0)
          self.emit('CALL_FUNCTION', 0)
          self.emit('BUILD_CLASS')
***************
*** 1018,1129 ****
              self.emit('STORE_SUBSCR')
  
- class NestedScopeCodeGenerator(CodeGenerator):
-     __super_visitModule = CodeGenerator.visitModule
-     __super_visitClass = CodeGenerator.visitClass
-     __super__visitFuncOrLambda = CodeGenerator._visitFuncOrLambda
- 
-     def parseSymbols(self, tree):
-         s = symbols.SymbolVisitor()
-         walk(tree, s)
-         return s.scopes
- 
-     def visitModule(self, node):
-         self.scopes = self.parseSymbols(node)
-         self.scope = self.scopes[node]
-         self.__super_visitModule(node)
- 
-     def _nameOp(self, prefix, name):
-         name = self.mangle(name)
-         scope = self.scope.check_name(name)
-         if scope == SC_LOCAL:
-             if not self.optimized:
-                 self.emit(prefix + '_NAME', name)
-             else:
-                 self.emit(prefix + '_FAST', name)
-         elif scope == SC_GLOBAL:
-             if not self.optimized:
-                 self.emit(prefix + '_NAME', name)
-             else:
-                 self.emit(prefix + '_GLOBAL', name)
-         elif scope == SC_FREE or scope == SC_CELL:
-             self.emit(prefix + '_DEREF', name)
-         else:
-             raise RuntimeError, "unsupported scope for var %s: %d" % \
-                   (name, scope)
- 
-     def _visitFuncOrLambda(self, node, isLambda=0):
-         gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
-                                self.class_name)
-         walk(node.code, gen)
-         gen.finish()
-         self.set_lineno(node)
-         for default in node.defaults:
-             self.visit(default)
-         frees = gen.scope.get_free_vars()
-         if frees:
-             for name in frees:
-                 self.emit('LOAD_CLOSURE', name)
-             self.emit('LOAD_CONST', gen)
-             self.emit('MAKE_CLOSURE', len(node.defaults))
-         else:
-             self.emit('LOAD_CONST', gen)
-             self.emit('MAKE_FUNCTION', len(node.defaults))
- 
-     def visitClass(self, node):
-         gen = self.ClassGen(node, self.filename, self.scopes)
-         if node.doc:
-             self.emit('LOAD_CONST', node.doc)
-             self.storeName('__doc__')
-         walk(node.code, gen)
-         gen.finish()
-         self.set_lineno(node)
-         self.emit('LOAD_CONST', node.name)
-         for base in node.bases:
-             self.visit(base)
-         self.emit('BUILD_TUPLE', len(node.bases))
-         frees = gen.scope.get_free_vars()
-         for name in frees:
-             self.emit('LOAD_CLOSURE', name)
-         self.emit('LOAD_CONST', gen)
-         if frees:
-             self.emit('MAKE_CLOSURE', 0)
-         else:
-             self.emit('MAKE_FUNCTION', 0)
-         self.emit('CALL_FUNCTION', 0)
-         self.emit('BUILD_CLASS')
-         self.storeName(node.name)
-         
- 
- class LGBScopeMixin:
-     """Defines initClass() for Python 2.1-compatible scoping"""
-     def initClass(self):
-         self.__class__.NameFinder = LocalNameFinder
-         self.__class__.FunctionGen = FunctionCodeGenerator
-         self.__class__.ClassGen = ClassCodeGenerator
- 
  class NestedScopeMixin:
      """Defines initClass() for nested scoping (Python 2.2-compatible)"""
      def initClass(self):
          self.__class__.NameFinder = LocalNameFinder
!         self.__class__.FunctionGen = NestedFunctionCodeGenerator
!         self.__class__.ClassGen = NestedClassCodeGenerator
  
! class ModuleCodeGenerator(LGBScopeMixin, CodeGenerator):
      __super_init = CodeGenerator.__init__
  
      scopes = None
      
!     def __init__(self, filename):
          self.graph = pyassem.PyFlowGraph("<module>", filename)
          self.__super_init(filename)
  
! class NestedScopeModuleCodeGenerator(NestedScopeMixin,
!                                      NestedScopeCodeGenerator):
!     __super_init = CodeGenerator.__init__
!     
!     def __init__(self, filename):
!         self.graph = pyassem.PyFlowGraph("<module>", filename)
!         self.__super_init(filename)
! ##        self.graph.setFlag(CO_NESTED)
  
  class AbstractFunctionCode:
--- 1067,1090 ----
              self.emit('STORE_SUBSCR')
  
  class NestedScopeMixin:
      """Defines initClass() for nested scoping (Python 2.2-compatible)"""
      def initClass(self):
          self.__class__.NameFinder = LocalNameFinder
!         self.__class__.FunctionGen = FunctionCodeGenerator
!         self.__class__.ClassGen = ClassCodeGenerator
  
! class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
      __super_init = CodeGenerator.__init__
  
      scopes = None
      
!     def __init__(self, filename, tree):
          self.graph = pyassem.PyFlowGraph("<module>", filename)
+         self.futures = future.find_futures(tree)
          self.__super_init(filename)
+         walk(tree, self)
  
!     def get_module(self):
!         return self
  
  class AbstractFunctionCode:
***************
*** 1131,1136 ****
      lambdaCount = 0
  
!     def __init__(self, func, filename, scopes, isLambda, class_name):
          self.class_name = class_name
          if isLambda:
              klass = FunctionCodeGenerator
--- 1092,1098 ----
      lambdaCount = 0
  
!     def __init__(self, func, filename, scopes, isLambda, class_name, mod):
          self.class_name = class_name
+         self.module = mod
          if isLambda:
              klass = FunctionCodeGenerator
***************
*** 1158,1161 ****
--- 1120,1126 ----
              self.generateArgUnpack(func.argnames)
  
+     def get_module(self):
+         return self.module
+ 
      def finish(self):
          self.graph.startExitBlock()
***************
*** 1184,1212 ****
      unpackTuple = unpackSequence
  
! class FunctionCodeGenerator(LGBScopeMixin, AbstractFunctionCode,
                              CodeGenerator): 
      super_init = CodeGenerator.__init__ # call be other init
      scopes = None
  
- class NestedFunctionCodeGenerator(AbstractFunctionCode,
-                                   NestedScopeMixin,
-                                   NestedScopeCodeGenerator):
-     super_init = NestedScopeCodeGenerator.__init__ # call be other init
      __super_init = AbstractFunctionCode.__init__
  
!     def __init__(self, func, filename, scopes, isLambda, class_name):
          self.scopes = scopes
          self.scope = scopes[func]
!         self.__super_init(func, filename, scopes, isLambda, class_name)
          self.graph.setFreeVars(self.scope.get_free_vars())
          self.graph.setCellVars(self.scope.get_cell_vars())
!         if self.scope.generator is not None:
!             self.graph.setFlag(CO_GENERATOR)
! ##        self.graph.setFlag(CO_NESTED)
  
  class AbstractClassCode:
  
!     def __init__(self, klass, filename, scopes):
          self.class_name = klass.name
          self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                             optimized=0, klass=1)
--- 1149,1174 ----
      unpackTuple = unpackSequence
  
! class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
                              CodeGenerator): 
      super_init = CodeGenerator.__init__ # call be other init
      scopes = None
  
      __super_init = AbstractFunctionCode.__init__
  
!     def __init__(self, func, filename, scopes, isLambda, class_name, mod):
          self.scopes = scopes
          self.scope = scopes[func]
!         self.__super_init(func, filename, scopes, isLambda, class_name, mod)
          self.graph.setFreeVars(self.scope.get_free_vars())
          self.graph.setCellVars(self.scope.get_cell_vars())
!         if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
!             if self.scope.generator is not None:
!                 self.graph.setFlag(CO_GENERATOR)
  
  class AbstractClassCode:
  
!     def __init__(self, klass, filename, scopes, module):
          self.class_name = klass.name
+         self.module = module
          self.graph = pyassem.PyFlowGraph(klass.name, filename,
                                             optimized=0, klass=1)
***************
*** 1218,1225 ****
              self.setDocstring(klass.doc)
  
!     def _nameOp(self, prefix, name):
!         name = self.mangle(name)
!         # Class namespaces are always unoptimized
!         self.emit(prefix + '_NAME', name)
  
      def finish(self):
--- 1180,1185 ----
              self.setDocstring(klass.doc)
  
!     def get_module(self):
!         return self.module
  
      def finish(self):
***************
*** 1228,1245 ****
          self.emit('RETURN_VALUE')
  
! class ClassCodeGenerator(LGBScopeMixin, AbstractClassCode, CodeGenerator):
      super_init = CodeGenerator.__init__
      scopes = None
  
- class NestedClassCodeGenerator(AbstractClassCode,
-                                NestedScopeMixin,
-                                NestedScopeCodeGenerator):
-     super_init = NestedScopeCodeGenerator.__init__ # call be other init
      __super_init = AbstractClassCode.__init__
  
!     def __init__(self, klass, filename, scopes):
          self.scopes = scopes
          self.scope = scopes[klass]
!         self.__super_init(klass, filename, scopes)
          self.graph.setFreeVars(self.scope.get_free_vars())
          self.graph.setCellVars(self.scope.get_cell_vars())
--- 1188,1201 ----
          self.emit('RETURN_VALUE')
  
! class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
      super_init = CodeGenerator.__init__
      scopes = None
  
      __super_init = AbstractClassCode.__init__
  
!     def __init__(self, klass, filename, scopes, module):
          self.scopes = scopes
          self.scope = scopes[klass]
!         self.__super_init(klass, filename, scopes, module)
          self.graph.setFreeVars(self.scope.get_free_vars())
          self.graph.setCellVars(self.scope.get_cell_vars())