[Python-checkins] CVS: /python/nondist/src/Compiler/compiler ast.py,1.8,1.9 pyassem.py,1.8,1.9 pycodegen.py,1.19,1.20 transformer.py,1.9,1.10

Jeremy Hylton python-dev@python.org
Tue, 2 May 2000 18:33:02 -0400


Update of /projects/cvsroot//python/nondist/src/Compiler/compiler
In directory goon.cnri.reston.va.us:/tmp/Compiler/compiler

Modified Files:
	ast.py pyassem.py pycodegen.py transformer.py 
Log Message:
patches from Mark Hammond

Attached is a set of diffs for the .py compiler that adds support
for the new extended call syntax.

compiler/ast.py:
CallFunc node gets 2 new children to support extended call syntax -
"star_args" (for "*args") and "dstar_args" (for "**args")

compiler/pyassem.py
It appear that self.lnotab is supposed to be responsible for
tracking line numbers, but self.firstlineno was still hanging
around.  Removed self.firstlineno completely.  NOTE - I didnt
actually test that the generated code has the correct line numbers!!

Stack depth tracking appeared a little broken - the checks never
made it beyond the "self.patterns" check - thus, the custom methods
were never called!  Fixed this.

(XXX Jeremy notes: I think this code is still broken because it
doesn't track stack effects across block bounaries.)

Added support for the new extended call syntax opcodes for depth
calculations.

compiler/pycodegen.py

Added support for the new extended call syntax opcodes.

compiler/transformer.py

Added support for the new extended call syntax.


Index: ast.py
===================================================================
RCS file: /projects/cvsroot//python/nondist/src/Compiler/compiler/ast.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** ast.py	2000/03/06 18:50:48	1.8
--- ast.py	2000/05/02 22:32:59	1.9
***************
*** 446,456 ****
    nodes['call_func'] = 'CallFunc'
  
!   def __init__(self, node, args):
      self.node = node
      self.args = args
!     self._children = ('call_func', node, args)
  
    def __repr__(self):
!     return "CallFunc(%s,%s)" % self._children[1:]
  
  class Keyword(Node):
--- 446,458 ----
    nodes['call_func'] = 'CallFunc'
  
!   def __init__(self, node, args, star_args = None, dstar_args = None):
      self.node = node
      self.args = args
!     self.star_args = star_args
!     self.dstar_args = dstar_args
!     self._children = ('call_func', node, args, star_args, dstar_args)
  
    def __repr__(self):
!     return "CallFunc(%s,%s,*%s, **%s)" % self._children[1:]
  
  class Keyword(Node):

Index: pyassem.py
===================================================================
RCS file: /projects/cvsroot//python/nondist/src/Compiler/compiler/pyassem.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** pyassem.py	2000/03/16 20:06:59	1.8
--- pyassem.py	2000/05/02 22:32:59	1.9
***************
*** 150,154 ****
  	else:
  	    self.flags = 0
- 	self.firstlineno = None
  	self.consts = []
  	self.names = []
--- 150,153 ----
***************
*** 315,320 ****
                  if opname == "SET_LINENO":
                      lnotab.nextLine(oparg)
-                     if self.firstlineno is None:
-                         self.firstlineno = oparg
                  hi, lo = twobyte(oparg)
  		try:
--- 314,317 ----
***************
*** 343,347 ****
                          self.lnotab.getCode(), self.getConsts(),
                          tuple(self.names), tuple(self.varnames),
!                         self.filename, self.name, self.firstlineno,
                          self.lnotab.getTable())
  
--- 340,344 ----
                          self.lnotab.getCode(), self.getConsts(),
                          tuple(self.names), tuple(self.varnames),
!                         self.filename, self.name, self.lnotab.firstline,
                          self.lnotab.getTable())
  
***************
*** 465,476 ****
                      maxDepth = depth
                  # now check patterns
!                 for pat, delta in self.patterns:
                      if opname[:len(pat)] == pat:
                          depth = depth + delta
                          break
                  # if we still haven't found a match
                  if delta == 0:
!                     meth = getattr(self, opname)
!                     depth = depth + meth(i[1])
              if depth < 0:
                  depth = 0
--- 462,475 ----
                      maxDepth = depth
                  # now check patterns
!                 for pat, pat_delta in self.patterns:
                      if opname[:len(pat)] == pat:
+                         delta = pat_delta
                          depth = depth + delta
                          break
                  # if we still haven't found a match
                  if delta == 0:
!                     meth = getattr(self, opname, None)
!                     if meth is not None:
!                         depth = depth + meth(i[1])
              if depth < 0:
                  depth = 0
***************
*** 528,531 ****
--- 527,536 ----
          hi, lo = divmod(argc, 256)
          return lo + hi * 2
+     def CALL_FUNCTION_VAR(self, argc):
+         return self.CALL_FUNCTION(argc)+1
+     def CALL_FUNCTION_KW(self, argc):
+         return self.CALL_FUNCTION(argc)+1
+     def CALL_FUNCTION_VAR_KW(self, argc):
+         return self.CALL_FUNCTION(argc)+2
      def MAKE_FUNCTION(self, argc):
          return -argc

Index: pycodegen.py
===================================================================
RCS file: /projects/cvsroot//python/nondist/src/Compiler/compiler/pycodegen.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -r1.19 -r1.20
*** pycodegen.py	2000/03/16 20:06:59	1.19
--- pycodegen.py	2000/05/02 22:32:59	1.20
***************
*** 10,13 ****
--- 10,21 ----
  from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, TupleArg
  
+ callfunc_opcode_info = {
+     # (Have *args, Have **args) : opcode
+     (0,0) : "CALL_FUNCTION",
+     (1,0) : "CALL_FUNCTION_VAR",
+     (0,1) : "CALL_FUNCTION_KW",
+     (1,1) : "CALL_FUNCTION_VAR_KW",
+ }
+ 
  def compile(filename):
      f = open(filename)
***************
*** 479,483 ****
              else:
                  pos = pos + 1
!         self.emit('CALL_FUNCTION', kw << 8 | pos)
  
      def visitPrint(self, node):
--- 487,498 ----
              else:
                  pos = pos + 1
!         if node.star_args is not None:
!             self.visit(node.star_args)
!         if node.dstar_args is not None:
!             self.visit(node.dstar_args)
!         have_star = node.star_args is not None
!         have_dstar = node.dstar_args is not None
!         opcode = callfunc_opcode_info[have_star, have_dstar]
!         self.emit(opcode, kw << 8 | pos)
  
      def visitPrint(self, node):

Index: transformer.py
===================================================================
RCS file: /projects/cvsroot//python/nondist/src/Compiler/compiler/transformer.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** transformer.py	2000/03/16 20:03:04	1.9
--- transformer.py	2000/05/02 22:32:59	1.10
***************
*** 985,992 ****
      args = [ ]
      kw = 0
!     for i in range(1, len(nodelist), 2):
!       kw, result = self.com_argument(nodelist[i], kw)
        args.append(result)
!     return Node('call_func', primaryNode, args)
  
    def com_argument(self, nodelist, kw):
--- 985,1014 ----
      args = [ ]
      kw = 0
!     len_nodelist = len(nodelist)
!     for i in range(1, len_nodelist, 2):
!       node = nodelist[i]
!       if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
!           break
!       kw, result = self.com_argument(node, kw)
        args.append(result)
!     else:
!         i = i + 1 # No broken by star arg, so skip the last one we processed.
!     star_node = dstar_node = None
!     while i < len_nodelist:
!         tok = nodelist[i]
!         ch = nodelist[i+1]
!         i = i + 3
!         if tok[0]==token.STAR:
!             if star_node is not None:
!                 raise SyntaxError, 'already have the varargs indentifier'
!             star_node = self.com_node(ch)
!         elif tok[0]==token.DOUBLESTAR:
!             if dstar_node is not None:
!                 raise SyntaxError, 'already have the kwargs indentifier'
!             dstar_node = self.com_node(ch)
!         else:
!             raise SyntaxError, 'unknown node type: %s' % tok
! 
!     return Node('call_func', primaryNode, args, star_node, dstar_node)
  
    def com_argument(self, nodelist, kw):