diff options
Diffstat (limited to 'Lib/compiler/pycodegen.py')
| -rw-r--r-- | Lib/compiler/pycodegen.py | 123 |
1 files changed, 74 insertions, 49 deletions
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index 17a8f4a..4f2ecf2 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -7,7 +7,8 @@ from cStringIO import StringIO from compiler import ast, parse, walk, syntax from compiler import pyassem, misc, future, symbols -from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL +from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \ + SC_FREE, SC_CELL from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION, CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION) @@ -282,7 +283,9 @@ class CodeGenerator: self.emit(prefix + '_NAME', name) else: self.emit(prefix + '_FAST', name) - elif scope == SC_GLOBAL: + elif scope == SC_GLOBAL_EXPLICT: + self.emit(prefix + '_GLOBAL', name) + elif scope == SC_GLOBAL_IMPLICIT: if not self.optimized: self.emit(prefix + '_NAME', name) else: @@ -418,13 +421,11 @@ class CodeGenerator: self.set_lineno(test) self.visit(test) nextTest = self.newBlock() - self.emit('JUMP_IF_FALSE', nextTest) + self.emit('POP_JUMP_IF_FALSE', nextTest) self.nextBlock() - self.emit('POP_TOP') self.visit(suite) self.emit('JUMP_FORWARD', end) self.startBlock(nextTest) - self.emit('POP_TOP') if node.else_: self.visit(node.else_) self.nextBlock(end) @@ -443,15 +444,13 @@ class CodeGenerator: self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', else_ or after) + self.emit('POP_JUMP_IF_FALSE', else_ or after) self.nextBlock() - self.emit('POP_TOP') self.visit(node.body) self.emit('JUMP_ABSOLUTE', loop) self.startBlock(else_) # or just the POPs if not else clause - self.emit('POP_TOP') self.emit('POP_BLOCK') self.setups.pop() if node.else_: @@ -522,26 +521,23 @@ class CodeGenerator: self.visit(child) self.emit(jump, end) self.nextBlock() - self.emit('POP_TOP') self.visit(node.nodes[-1]) self.nextBlock(end) def visitAnd(self, node): - self.visitTest(node, 'JUMP_IF_FALSE') + self.visitTest(node, 'JUMP_IF_FALSE_OR_POP') def visitOr(self, node): - self.visitTest(node, 'JUMP_IF_TRUE') + self.visitTest(node, 'JUMP_IF_TRUE_OR_POP') def visitIfExp(self, node): endblock = self.newBlock() elseblock = self.newBlock() self.visit(node.test) - self.emit('JUMP_IF_FALSE', elseblock) - self.emit('POP_TOP') + self.emit('POP_JUMP_IF_FALSE', elseblock) self.visit(node.then) self.emit('JUMP_FORWARD', endblock) self.nextBlock(elseblock) - self.emit('POP_TOP') self.visit(node.else_) self.nextBlock(endblock) @@ -553,9 +549,8 @@ class CodeGenerator: self.emit('DUP_TOP') self.emit('ROT_THREE') self.emit('COMPARE_OP', op) - self.emit('JUMP_IF_FALSE', cleanup) + self.emit('JUMP_IF_FALSE_OR_POP', cleanup) self.nextBlock() - self.emit('POP_TOP') # now do the last comparison if node.ops: op, code = node.ops[-1] @@ -570,16 +565,10 @@ class CodeGenerator: self.nextBlock(end) # list comprehensions - __list_count = 0 - def visitListComp(self, node): self.set_lineno(node) # setup list - tmpname = "$list%d" % self.__list_count - self.__list_count = self.__list_count + 1 self.emit('BUILD_LIST', 0) - self.emit('DUP_TOP') - self._implicitNameOp('STORE', tmpname) stack = [] for i, for_ in zip(range(len(node.quals)), node.quals): @@ -591,22 +580,63 @@ class CodeGenerator: self.visit(if_, cont) stack.insert(0, (start, cont, anchor)) - self._implicitNameOp('LOAD', tmpname) self.visit(node.expr) - self.emit('LIST_APPEND') + self.emit('LIST_APPEND', len(node.quals) + 1) for start, cont, anchor in stack: if cont: - skip_one = self.newBlock() - self.emit('JUMP_FORWARD', skip_one) - self.startBlock(cont) - self.emit('POP_TOP') - self.nextBlock(skip_one) + self.nextBlock(cont) self.emit('JUMP_ABSOLUTE', start) self.startBlock(anchor) - self._implicitNameOp('DELETE', tmpname) - self.__list_count = self.__list_count - 1 + def visitSetComp(self, node): + self.set_lineno(node) + # setup list + self.emit('BUILD_SET', 0) + + stack = [] + for i, for_ in zip(range(len(node.quals)), node.quals): + start, anchor = self.visit(for_) + cont = None + for if_ in for_.ifs: + if cont is None: + cont = self.newBlock() + self.visit(if_, cont) + stack.insert(0, (start, cont, anchor)) + + self.visit(node.expr) + self.emit('SET_ADD', len(node.quals) + 1) + + for start, cont, anchor in stack: + if cont: + self.nextBlock(cont) + self.emit('JUMP_ABSOLUTE', start) + self.startBlock(anchor) + + def visitDictComp(self, node): + self.set_lineno(node) + # setup list + self.emit('BUILD_MAP', 0) + + stack = [] + for i, for_ in zip(range(len(node.quals)), node.quals): + start, anchor = self.visit(for_) + cont = None + for if_ in for_.ifs: + if cont is None: + cont = self.newBlock() + self.visit(if_, cont) + stack.insert(0, (start, cont, anchor)) + + self.visit(node.value) + self.visit(node.key) + self.emit('MAP_ADD', len(node.quals) + 1) + + for start, cont, anchor in stack: + if cont: + self.nextBlock(cont) + self.emit('JUMP_ABSOLUTE', start) + self.startBlock(anchor) def visitListCompFor(self, node): start = self.newBlock() @@ -624,9 +654,8 @@ class CodeGenerator: def visitListCompIf(self, node, branch): self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', branch) + self.emit('POP_JUMP_IF_FALSE', branch) self.newBlock() - self.emit('POP_TOP') def _makeClosure(self, gen, args): frees = gen.scope.get_free_vars() @@ -672,16 +701,12 @@ class CodeGenerator: for start, cont, anchor, end in stack: if cont: - skip_one = self.newBlock() - self.emit('JUMP_FORWARD', skip_one) - self.startBlock(cont) - self.emit('POP_TOP') - self.nextBlock(skip_one) + self.nextBlock(cont) self.emit('JUMP_ABSOLUTE', start) self.startBlock(anchor) self.emit('POP_BLOCK') self.setups.pop() - self.startBlock(end) + self.nextBlock(end) self.emit('LOAD_CONST', None) @@ -709,9 +734,8 @@ class CodeGenerator: def visitGenExprIf(self, node, branch): self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', branch) + self.emit('POP_JUMP_IF_FALSE', branch) self.newBlock() - self.emit('POP_TOP') # exception related @@ -726,9 +750,8 @@ class CodeGenerator: # is a sort of renaming op. self.nextBlock() self.visit(node.test) - self.emit('JUMP_IF_TRUE', end) + self.emit('POP_JUMP_IF_TRUE', end) self.nextBlock() - self.emit('POP_TOP') self.emit('LOAD_GLOBAL', 'AssertionError') if node.fail: self.visit(node.fail) @@ -736,7 +759,6 @@ class CodeGenerator: else: self.emit('RAISE_VARARGS', 1) self.nextBlock(end) - self.emit('POP_TOP') def visitRaise(self, node): self.set_lineno(node) @@ -779,9 +801,8 @@ class CodeGenerator: self.visit(expr) self.emit('COMPARE_OP', 'exception match') next = self.newBlock() - self.emit('JUMP_IF_FALSE', next) + self.emit('POP_JUMP_IF_FALSE', next) self.nextBlock() - self.emit('POP_TOP') self.emit('POP_TOP') if target: self.visit(target) @@ -794,8 +815,6 @@ class CodeGenerator: self.nextBlock(next) else: self.nextBlock() - if expr: # XXX - self.emit('POP_TOP') self.emit('END_FINALLY') if node.else_: self.nextBlock(lElse) @@ -824,8 +843,8 @@ class CodeGenerator: def visitWith(self, node): body = self.newBlock() final = self.newBlock() - valuevar = "$value%d" % self.__with_count self.__with_count += 1 + valuevar = "_[%d]" % self.__with_count self.set_lineno(node) self.visit(node.expr) self.emit('DUP_TOP') @@ -1245,6 +1264,12 @@ class CodeGenerator: self.visit(elt) self.emit('BUILD_LIST', len(node.nodes)) + def visitSet(self, node): + self.set_lineno(node) + for elt in node.nodes: + self.visit(elt) + self.emit('BUILD_SET', len(node.nodes)) + def visitSliceobj(self, node): for child in node.nodes: self.visit(child) |
