| Index: Lib/compiler/pycodegen.py |
| =================================================================== |
| --- Lib/compiler/pycodegen.py (revision 70087) |
| +++ Lib/compiler/pycodegen.py (working copy) |
| @@ -413,7 +413,7 @@ |
| def visitIf(self, node): |
| end = self.newBlock() |
| numtests = len(node.tests) |
| - for i in range(numtests): |
| + for i in range(numtests - 1): |
| test, suite = node.tests[i] |
| if is_constant_false(test): |
| # XXX will need to check generator stuff here |
| @@ -426,8 +426,22 @@ |
| self.visit(suite) |
| self.emit('JUMP_FORWARD', end) |
| self.startBlock(nextTest) |
| - if node.else_: |
| - self.visit(node.else_) |
| + # The last test can optimize a few things |
| + test, suite = node.tests[numtests - 1] |
| + if is_constant_false(test): |
| + if node.else_: |
| + self.visit(node.else_) |
| + else: |
| + self.set_lineno(test) |
| + self.visit(test) |
| + else_block = self.newBlock() if node.else_ else end |
| + self.emit('POP_JUMP_IF_FALSE', else_block) |
| + self.nextBlock() |
| + self.visit(suite) |
| + if node.else_: |
| + self.emit('JUMP_FORWARD', end) |
| + self.startBlock(else_block) |
| + self.visit(node.else_) |
| self.nextBlock(end) |
| def visitWhile(self, node): |
| @@ -435,22 +449,26 @@ |
| loop = self.newBlock() |
| else_ = self.newBlock() |
| - |
| + body = self.newBlock() |
| + tail = self.newBlock() |
| after = self.newBlock() |
| + |
| self.emit('SETUP_LOOP', after) |
| self.nextBlock(loop) |
| self.setups.push((LOOP, loop)) |
| + self.emit('JUMP_FORWARD', tail) |
| + self.startBlock(body) |
| self.set_lineno(node, force=True) |
| - self.visit(node.test) |
| - self.emit('POP_JUMP_IF_FALSE', else_ or after) |
| - self.nextBlock() |
| self.visit(node.body) |
| - self.emit('JUMP_ABSOLUTE', loop) |
| - self.startBlock(else_) # or just the POPs if not else clause |
| + self.nextBlock(tail) |
| + self.visit(node.test) |
| + self.emit('POP_JUMP_IF_TRUE', body) |
| + |
| + self.nextBlock(else_) # or just the POPs if not else clause |
| self.emit('POP_BLOCK') |
| self.setups.pop() |
| if node.else_: |
| @@ -459,6 +477,8 @@ |
| def visitFor(self, node): |
| start = self.newBlock() |
| + body = self.newBlock() |
| + tail = self.newBlock() |
| anchor = self.newBlock() |
| after = self.newBlock() |
| self.setups.push((LOOP, start)) |
| @@ -470,10 +490,12 @@ |
| self.nextBlock(start) |
| self.set_lineno(node, force=1) |
| - self.emit('FOR_ITER', anchor) |
| + self.emit('JUMP_FORWARD', tail) |
| + self.startBlock(body) |
| self.visit(node.assign) |
| self.visit(node.body) |
| - self.emit('JUMP_ABSOLUTE', start) |
| + self.nextBlock(tail) |
| + self.emit('FOR_ITER', body) |
| self.nextBlock(anchor) |
| self.emit('POP_BLOCK') |
| self.setups.pop() |
| @@ -571,42 +593,37 @@ |
| self.emit('BUILD_LIST', 0) |
| stack = [] |
| - for i, for_ in zip(range(len(node.quals)), node.quals): |
| - start, anchor = self.visit(for_) |
| - cont = None |
| + for for_ in node.quals: |
| + body, tail = self.visit(for_) |
| for if_ in for_.ifs: |
| - if cont is None: |
| - cont = self.newBlock() |
| - self.visit(if_, cont) |
| - stack.insert(0, (start, cont, anchor)) |
| + self.visit(if_, tail) |
| + stack.insert(0, (for_, body, tail)) |
| self.visit(node.expr) |
| self.emit('LIST_APPEND', len(node.quals) + 1) |
| - for start, cont, anchor in stack: |
| - if cont: |
| - self.nextBlock(cont) |
| - self.emit('JUMP_ABSOLUTE', start) |
| - self.startBlock(anchor) |
| + for for_, body, tail in stack: |
| + self.nextBlock(tail) |
| + self.set_lineno(for_, force=True) |
| + self.emit('FOR_ITER', body) |
| + self.nextBlock() |
| def visitListCompFor(self, node): |
| - start = self.newBlock() |
| - anchor = self.newBlock() |
| + body = self.newBlock() |
| + tail = self.newBlock() |
| self.visit(node.list) |
| self.emit('GET_ITER') |
| - self.nextBlock(start) |
| - self.set_lineno(node, force=True) |
| - self.emit('FOR_ITER', anchor) |
| self.nextBlock() |
| + self.emit('JUMP_FORWARD', tail) |
| + self.nextBlock(body) |
| self.visit(node.assign) |
| - return start, anchor |
| + return body, tail |
| def visitListCompIf(self, node, branch): |
| self.set_lineno(node, force=True) |
| self.visit(node.test) |
| self.emit('POP_JUMP_IF_FALSE', branch) |
| - self.newBlock() |
| def _makeClosure(self, gen, args): |
| frees = gen.scope.get_free_vars() |
| @@ -637,24 +654,21 @@ |
| # setup list |
| stack = [] |
| - for i, for_ in zip(range(len(node.quals)), node.quals): |
| - start, anchor, end = self.visit(for_) |
| - cont = None |
| + for for_ in node.quals: |
| + body, tail, end = self.visit(for_) |
| for if_ in for_.ifs: |
| - if cont is None: |
| - cont = self.newBlock() |
| - self.visit(if_, cont) |
| - stack.insert(0, (start, cont, anchor, end)) |
| + self.visit(if_, tail) |
| + stack.insert(0, (for_, body, tail, end)) |
| self.visit(node.expr) |
| self.emit('YIELD_VALUE') |
| self.emit('POP_TOP') |
| - for start, cont, anchor, end in stack: |
| - if cont: |
| - self.nextBlock(cont) |
| - self.emit('JUMP_ABSOLUTE', start) |
| - self.startBlock(anchor) |
| + for for_, body, tail, end in stack: |
| + self.nextBlock(tail) |
| + self.set_lineno(for_, force=True) |
| + self.emit('FOR_ITER', body) |
| + self.nextBlock() |
| self.emit('POP_BLOCK') |
| self.setups.pop() |
| self.nextBlock(end) |
| @@ -663,7 +677,8 @@ |
| def visitGenExprFor(self, node): |
| start = self.newBlock() |
| - anchor = self.newBlock() |
| + body = self.newBlock() |
| + tail = self.newBlock() |
| end = self.newBlock() |
| self.setups.push((LOOP, start)) |
| @@ -676,11 +691,10 @@ |
| self.emit('GET_ITER') |
| self.nextBlock(start) |
| - self.set_lineno(node, force=True) |
| - self.emit('FOR_ITER', anchor) |
| - self.nextBlock() |
| + self.emit('JUMP_FORWARD', tail) |
| + self.nextBlock(body) |
| self.visit(node.assign) |
| - return start, anchor, end |
| + return body, tail, end |
| def visitGenExprIf(self, node, branch): |
| self.set_lineno(node, force=True) |