summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2000-02-10 20:55:50 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2000-02-10 20:55:50 (GMT)
commit4eb504c2af614aab64dee5e894ad98b0851c1148 (patch)
treec9505df53adc9cf393e585066f2ef688db7f4099 /Lib
parent95b8614353eee05f350c794a0aa37cab39794eed (diff)
downloadcpython-4eb504c2af614aab64dee5e894ad98b0851c1148.zip
cpython-4eb504c2af614aab64dee5e894ad98b0851c1148.tar.gz
cpython-4eb504c2af614aab64dee5e894ad98b0851c1148.tar.bz2
add loop handling via
Loop object to handle StackRegs loops stack attr on CodeGenreeator to hold the current loop object add support for nodes While, Break, Continue
Diffstat (limited to 'Lib')
-rw-r--r--Lib/compiler/pycodegen.py76
1 files changed, 63 insertions, 13 deletions
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 92cbef6..66dd52d 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -162,6 +162,7 @@ class CodeGenerator:
self.code = PythonVMCode(filename=filename)
self.code.setFlags(0)
self.locals = misc.Stack()
+ self.loops = misc.Stack()
self.namespace = self.MODULE_NAMESPACE
self.curStack = 0
self.maxStack = 0
@@ -180,8 +181,6 @@ class CodeGenerator:
self.code.setKWArgs()
lnf = walk(func.code, LocalNameFinder(args), 0)
self.locals.push(lnf.getLocals())
-## print func.name, "(", func.argnames, ")"
-## print lnf.getLocals().items()
self.code.setLineNo(func.lineno)
walk(func.code, self)
self.code.emit('LOAD_CONST', None)
@@ -280,6 +279,8 @@ class CodeGenerator:
return 1
def visitCallFunc(self, node):
+ if hasattr(node, 'lineno'):
+ self.code.emit('SET_LINENO', node.lineno)
self.visit(node.node)
for arg in node.args:
self.visit(arg)
@@ -306,30 +307,76 @@ class CodeGenerator:
after.bind(self.code.getCurInst())
return 1
+ def startLoop(self):
+ l = Loop()
+ self.loops.push(l)
+ self.code.emit('SETUP_LOOP', l.extentAnchor)
+ return l
+
+ def finishLoop(self):
+ l = self.loops.pop()
+ i = self.code.getCurInst()
+ l.extentAnchor.bind(self.code.getCurInst())
+
def visitFor(self, node):
# three refs needed
- start = StackRef()
anchor = StackRef()
- breakAnchor = StackRef()
self.code.emit('SET_LINENO', node.lineno)
- self.code.emit('SETUP_LOOP', breakAnchor)
+ l = self.startLoop()
self.visit(node.list)
self.visit(ast.Const(0))
- start.bind(self.code.getCurInst())
+ l.startAnchor.bind(self.code.getCurInst())
self.code.setLineNo(node.lineno)
self.code.emit('FOR_LOOP', anchor)
self.push(1)
self.visit(node.assign)
self.visit(node.body)
- self.code.emit('JUMP_ABSOLUTE', start)
+ self.code.emit('JUMP_ABSOLUTE', l.startAnchor)
anchor.bind(self.code.getCurInst())
self.code.emit('POP_BLOCK')
if node.else_:
self.visit(node.else_)
- breakAnchor.bind(self.code.getCurInst())
+ self.finishLoop()
+ return 1
+
+ def visitWhile(self, node):
+ self.code.emit('SET_LINENO', node.lineno)
+ l = self.startLoop()
+ if node.else_:
+ lElse = StackRef()
+ else:
+ lElse = l.breakAnchor
+ l.startAnchor.bind(self.code.getCurInst())
+ self.code.emit('SET_LINENO', node.test.lineno)
+ self.visit(node.test)
+ self.code.emit('JUMP_IF_FALSE', lElse)
+ self.code.emit('POP_TOP')
+ self.visit(node.body)
+ self.code.emit('JUMP_ABSOLUTE', l.startAnchor)
+ # note that lElse may be an alias for l.breakAnchor
+ lElse.bind(self.code.getCurInst())
+ self.code.emit('POP_TOP')
+ self.code.emit('POP_BLOCK')
+ if node.else_:
+ self.visit(node.else_)
+ self.finishLoop()
return 1
+ def visitBreak(self, node):
+ if not self.loops:
+ raise SyntaxError, "'break' outside loop"
+ self.code.emit('SET_LINENO', node.lineno)
+ self.code.emit('BREAK_LOOP')
+
+ def visitContinue(self, node):
+ if not self.loops:
+ raise SyntaxError, "'continue' outside loop"
+ l = self.loops.top()
+ self.code.emit('SET_LINENO', node.lineno)
+ self.code.emit('JUMP_ABSOLUTE', l.startAnchor)
+
+
def visitCompare(self, node):
"""Comment from compile.c follows:
@@ -617,11 +664,11 @@ class LocalNameFinder:
def visitAssName(self, node):
self.names.add(node.name)
-class Label:
- def __init__(self, num):
- self.num = num
- def __repr__(self):
- return "Label(%d)" % self.num
+class Loop:
+ def __init__(self):
+ self.startAnchor = StackRef()
+ self.breakAnchor = StackRef()
+ self.extentAnchor = StackRef()
class StackRef:
"""Manage stack locations for jumps, loops, etc."""
@@ -644,6 +691,9 @@ class StackRef:
self.val = inst
def resolve(self):
+ if self.val is None:
+ print "UNRESOLVE REF", self
+ return 0
return self.val
def add_hook(hooks, type, meth):