[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler pycodegen.py,1.46,1.47

Jeremy Hylton jhylton@users.sourceforge.net
Wed, 29 Aug 2001 15:30:11 -0700


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

Modified Files:
	pycodegen.py 
Log Message:
Track the block stack more reasonably in order to handle continue in
try/except or try/finally.

Previous versions had only track SETUP_LOOP blocks and ignored the
exception part.  This meant that it allowed continue inside a
try/except but generated buggy code.  Now it does the right thing.



Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/pycodegen.py,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** pycodegen.py	2001/08/29 20:57:43	1.46
--- pycodegen.py	2001/08/29 22:30:09	1.47
***************
*** 29,32 ****
--- 29,37 ----
  }
  
+ LOOP = 1
+ EXCEPT = 2
+ TRY_FINALLY = 3
+ END_FINALLY = 4
+ 
  def compile(filename, display=0):
      f = open(filename)
***************
*** 143,147 ****
          self.filename = filename
          self.locals = misc.Stack()
!         self.loops = misc.Stack()
          self.curStack = 0
          self.maxStack = 0
--- 148,152 ----
          self.filename = filename
          self.locals = misc.Stack()
!         self.setups = misc.Stack()
          self.curStack = 0
          self.maxStack = 0
***************
*** 328,332 ****
  
          self.nextBlock(loop)
!         self.loops.push(loop)
  
          self.set_lineno(node, force=1)
--- 333,337 ----
  
          self.nextBlock(loop)
!         self.setups.push((LOOP, loop))
  
          self.set_lineno(node, force=1)
***************
*** 342,346 ****
          self.emit('POP_TOP')
          self.emit('POP_BLOCK')
!         self.loops.pop()
          if node.else_:
              self.visit(node.else_)
--- 347,351 ----
          self.emit('POP_TOP')
          self.emit('POP_BLOCK')
!         self.setups.pop()
          if node.else_:
              self.visit(node.else_)
***************
*** 351,355 ****
          anchor = self.newBlock()
          after = self.newBlock()
!         self.loops.push(start)
  
          self.set_lineno(node)
--- 356,360 ----
          anchor = self.newBlock()
          after = self.newBlock()
!         self.setups.push((LOOP, start))
  
          self.set_lineno(node)
***************
*** 366,370 ****
          self.nextBlock(anchor)
          self.emit('POP_BLOCK')
!         self.loops.pop()
          if node.else_:
              self.visit(node.else_)
--- 371,375 ----
          self.nextBlock(anchor)
          self.emit('POP_BLOCK')
!         self.setups.pop()
          if node.else_:
              self.visit(node.else_)
***************
*** 372,376 ****
  
      def visitBreak(self, node):
!         if not self.loops:
              raise SyntaxError, "'break' outside loop (%s, %d)" % \
                    (self.filename, node.lineno)
--- 377,381 ----
  
      def visitBreak(self, node):
!         if not self.setups:
              raise SyntaxError, "'break' outside loop (%s, %d)" % \
                    (self.filename, node.lineno)
***************
*** 379,389 ****
  
      def visitContinue(self, node):
!         if not self.loops:
              raise SyntaxError, "'continue' outside loop (%s, %d)" % \
                    (self.filename, node.lineno)
!         l = self.loops.top()
!         self.set_lineno(node)
!         self.emit('JUMP_ABSOLUTE', l)
!         self.nextBlock()
  
      def visitTest(self, node, jump):
--- 384,412 ----
  
      def visitContinue(self, node):
!         if not self.setups:
              raise SyntaxError, "'continue' outside loop (%s, %d)" % \
                    (self.filename, node.lineno)
!         kind, block = self.setups.top()
!         if kind == LOOP:
!             self.set_lineno(node)
!             self.emit('JUMP_ABSOLUTE', block)
!             self.nextBlock()
!         elif kind == EXCEPT or kind == TRY_FINALLY:
!             self.set_lineno(node)
!             # find the block that starts the loop
!             top = len(self.setups)
!             while top > 0:
!                 top = top - 1
!                 kind, loop_block = self.setups[top]
!                 if kind == LOOP:
!                     break
!             if kind != LOOP:
!                 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
!                       (self.filename, node.lineno)
!             self.emit('CONTINUE_LOOP', loop_block)
!             self.nextBlock()
!         elif kind == END_FINALLY:
!             msg = "'continue' not allowed inside 'finally' clause (%s, %d)"  
!             raise SyntaxError, msg % (self.filename, node.lineno)
  
      def visitTest(self, node, jump):
***************
*** 530,533 ****
--- 553,557 ----
  
      def visitTryExcept(self, node):
+         body = self.newBlock()
          handlers = self.newBlock()
          end = self.newBlock()
***************
*** 538,544 ****
          self.set_lineno(node)
          self.emit('SETUP_EXCEPT', handlers)
!         self.nextBlock()
          self.visit(node.body)
          self.emit('POP_BLOCK')
          self.emit('JUMP_FORWARD', lElse)
          self.startBlock(handlers)
--- 562,570 ----
          self.set_lineno(node)
          self.emit('SETUP_EXCEPT', handlers)
!         self.nextBlock(body)
!         self.setups.push((EXCEPT, body))
          self.visit(node.body)
          self.emit('POP_BLOCK')
+         self.setups.pop()
          self.emit('JUMP_FORWARD', lElse)
          self.startBlock(handlers)
***************
*** 571,574 ****
--- 597,601 ----
                  self.emit('POP_TOP')
          self.emit('END_FINALLY')
+         self.setups.pop()
          if node.else_:
              self.nextBlock(lElse)
***************
*** 577,590 ****
      
      def visitTryFinally(self, node):
          final = self.newBlock()
          self.set_lineno(node)
          self.emit('SETUP_FINALLY', final)
!         self.nextBlock()
          self.visit(node.body)
          self.emit('POP_BLOCK')
          self.emit('LOAD_CONST', None)
          self.nextBlock(final)
          self.visit(node.final)
          self.emit('END_FINALLY')
  
      # misc
--- 604,622 ----
      
      def visitTryFinally(self, node):
+         body = self.newBlock()
          final = self.newBlock()
          self.set_lineno(node)
          self.emit('SETUP_FINALLY', final)
!         self.nextBlock(body)
!         self.setups.push((TRY_FINALLY, body))
          self.visit(node.body)
          self.emit('POP_BLOCK')
+         self.setups.pop()
          self.emit('LOAD_CONST', None)
          self.nextBlock(final)
+         self.setups.push((END_FINALLY, final))
          self.visit(node.final)
          self.emit('END_FINALLY')
+         self.setups.pop()
  
      # misc