[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler __init__.py,1.4,1.5 pycodegen.py,1.54,1.55 transformer.py,1.27,1.28

Jeremy Hylton jhylton@users.sourceforge.net
Mon, 17 Sep 2001 14:02:53 -0700


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

Modified Files:
	__init__.py pycodegen.py transformer.py 
Log Message:
API change: 
compile() becomes replacement for builtin compile()
compileFile() generates a .pyc from a .py
both are exported in __init__

compiler.parse() gets optional second argument to specify compilation
mode, e.g. single, eval, exec

Add AbstractCompileMode as parent class and Module, Expression, and
Interactive as concrete subclasses.  Each corresponds to a compilation
mode.

THe AbstractCompileMode instances in turn delegate to CodeGeneration
subclasses specialized for their particular functions --
ModuleCodeGenerator, ExpressionCodeGeneration,
InteractiveCodeGenerator.



Index: __init__.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/__init__.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** __init__.py	2001/04/09 04:23:55	1.4
--- __init__.py	2001/09/17 21:02:51	1.5
***************
*** 4,8 ****
  from modules contained in the package.
  
! parse(buf) -> AST
      Converts a string containing Python source code to an abstract
      syntax tree (AST).  The AST is defined in compiler.ast.
--- 4,8 ----
  from modules contained in the package.
  
! parse(buf, mode="exec") -> AST
      Converts a string containing Python source code to an abstract
      syntax tree (AST).  The AST is defined in compiler.ast.
***************
*** 15,19 ****
      See compiler.visitor for details.
  
! compile(filename)
      Generates a .pyc file by compilining filename.
  """
--- 15,22 ----
      See compiler.visitor for details.
  
! compile(source, filename, mode, flags=None, dont_inherit=None)
!     Returns a code object.  A replacement for the builtin compile() function. 
! 
! compileFile(filename)
      Generates a .pyc file by compilining filename.
  """
***************
*** 21,24 ****
  from transformer import parse, parseFile
  from visitor import walk
! from pycodegen import compile
  
--- 24,27 ----
  from transformer import parse, parseFile
  from visitor import walk
! from pycodegen import compile, compileFile
  

Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pycodegen.py,v
retrieving revision 1.54
retrieving revision 1.55
diff -C2 -d -r1.54 -r1.55
*** pycodegen.py	2001/09/17 19:33:48	1.54
--- pycodegen.py	2001/09/17 21:02:51	1.55
***************
*** 42,46 ****
          self.loop = None
  
! def compile(filename, display=0):
      f = open(filename)
      buf = f.read()
--- 42,46 ----
          self.loop = None
  
! def compileFile(filename, display=0):
      f = open(filename)
      buf = f.read()
***************
*** 56,69 ****
          f.close()
  
! class Module:
      def __init__(self, source, filename):
-         self.filename = os.path.abspath(filename)
          self.source = source
          self.code = None
  
!     def compile(self, display=0):
!         tree = parse(self.source)
          misc.set_filename(self.filename, tree)
          syntax.check(tree)
          gen = ModuleCodeGenerator(tree)
          if display:
--- 56,121 ----
          f.close()
  
! def compile(source, filename, mode, flags=None, dont_inherit=None):
!     """Replacement for builtin compile() function"""
!     if flags is not None or dont_inherit is not None:
!         raise RuntimeError, "not implemented yet"
!     
!     if mode == "single":
!         gen = Interactive(source, filename)
!     elif mode == "exec":
!         gen = Module(source, filename)
!     elif mode == "eval":
!         gen = Expression(source, filename)
!     else:
!         raise ValueError("compile() 3rd arg must be 'exec' or "
!                          "'eval' or 'single'")
!     gen.compile()
!     return gen.code
! 
! class AbstractCompileMode:
! 
!     mode = None # defined by subclass
! 
      def __init__(self, source, filename):
          self.source = source
+         self.filename = filename
          self.code = None
  
!     def _get_tree(self):
!         tree = parse(self.source, self.mode)
          misc.set_filename(self.filename, tree)
          syntax.check(tree)
+         return tree
+ 
+     def compile(self):
+         pass # implemented by subclass
+ 
+     def getCode(self):
+         return self.code
+ 
+ class Expression(AbstractCompileMode):
+ 
+     mode = "eval"
+ 
+     def compile(self):
+         tree = self._get_tree()
+         gen = ExpressionCodeGenerator(tree)
+         self.code = gen.getCode()
+ 
+ class Interactive(AbstractCompileMode):
+ 
+     mode = "single"
+ 
+     def compile(self):
+         tree = self._get_tree()
+         gen = InteractiveCodeGenerator(tree)
+         self.code = gen.getCode()
+ 
+ class Module(AbstractCompileMode):
+ 
+     mode = "exec"
+ 
+     def compile(self, display=0):
+         tree = self._get_tree()
          gen = ModuleCodeGenerator(tree)
          if display:
***************
*** 1097,1100 ****
--- 1149,1190 ----
      def get_module(self):
          return self
+ 
+ class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
+     __super_init = CodeGenerator.__init__
+ 
+     scopes = None
+     futures = ()
+     
+     def __init__(self, tree):
+         self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
+         self.__super_init()
+         self.set_lineno(tree)
+         walk(tree, self)
+         self.emit('RETURN_VALUE')
+ 
+     def get_module(self):
+         return self
+ 
+ class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
+ 
+     __super_init = CodeGenerator.__init__
+ 
+     scopes = None
+     futures = ()
+     
+     def __init__(self, tree):
+         self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
+         self.__super_init()
+         self.set_lineno(tree)
+         walk(tree, self)
+         self.emit('RETURN_VALUE')
+ 
+     def get_module(self):
+         return self
+     def visitDiscard(self, node):
+         # XXX Discard means it's an expression.  Perhaps this is a bad
+         # name.
+         self.visit(node.expr)
+         self.emit('PRINT_EXPR')
  
  class AbstractFunctionCode:

Index: transformer.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/transformer.py,v
retrieving revision 1.27
retrieving revision 1.28
diff -C2 -d -r1.27 -r1.28
*** transformer.py	2001/09/17 19:33:48	1.27
--- transformer.py	2001/09/17 21:02:51	1.28
***************
*** 43,48 ****
      return parse(src)
  
! def parse(buf):
!     return Transformer().parsesuite(buf)
  
  def asList(nodes):
--- 43,54 ----
      return parse(src)
  
! def parse(buf, mode="exec"):
!     if mode == "exec" or mode == "single":
!         return Transformer().parsesuite(buf)
!     elif mode == "eval":
!         return Transformer().parseexpr(buf)
!     else:
!         raise ValueError("compile() arg 3 must be"
!                          " 'exec' or 'eval' or 'single'")
  
  def asList(nodes):