summaryrefslogtreecommitdiffstats
path: root/Lib/compiler/pycodegen.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/compiler/pycodegen.py')
-rw-r--r--Lib/compiler/pycodegen.py123
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)