summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2000-02-17 17:56:29 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2000-02-17 17:56:29 (GMT)
commit873bdc18e4c80d955244267effc2f11249c2b93d (patch)
treeeabcfabe7563c3d2e6765f663eb9b90e64d08574
parent1e862e8a37983800f7231a96c66b9b0479ca52bd (diff)
downloadcpython-873bdc18e4c80d955244267effc2f11249c2b93d.zip
cpython-873bdc18e4c80d955244267effc2f11249c2b93d.tar.gz
cpython-873bdc18e4c80d955244267effc2f11249c2b93d.tar.bz2
satisfy the tabnanny
fix broken references to filename var in generateXXX methods
-rw-r--r--Lib/compiler/pycodegen.py396
-rw-r--r--Tools/compiler/compiler/pycodegen.py396
2 files changed, 398 insertions, 394 deletions
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 9b9ee16..e9120cc 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -80,7 +80,7 @@ class ASTVisitor:
VERBOSE = 0
def __init__(self):
- self.node = None
+ self.node = None
def preorder(self, tree, visitor):
"""Do preorder walk of tree using visitor"""
@@ -163,27 +163,26 @@ class CodeGenerator:
# XXX should clean up initialization and generateXXX funcs
def __init__(self, filename="<?>"):
self.filename = filename
- self.code = PyAssembler()
+ self.code = PyAssembler()
self.code.setFlags(0)
- self.locals = misc.Stack()
+ self.locals = misc.Stack()
self.loops = misc.Stack()
self.namespace = 0
self.curStack = 0
self.maxStack = 0
def emit(self, *args):
- # XXX could just use self.emit = self.code.emit
- apply(self.code.emit, args)
+ # XXX could just use self.emit = self.code.emit
+ apply(self.code.emit, args)
def _generateFunctionOrLambdaCode(self, func):
self.name = func.name
- self.filename = filename
-
+
# keep a lookout for 'def foo((x,y)):'
args, hasTupleArg = self.generateArglist(func.argnames)
- self.code = PyAssembler(args=args, name=func.name,
- filename=filename)
+ self.code = PyAssembler(args=args, name=func.name,
+ filename=self.filename)
self.namespace = self.OPTIMIZED
if func.varargs:
self.code.setVarArgs()
@@ -191,8 +190,8 @@ class CodeGenerator:
self.code.setKWArgs()
lnf = walk(func.code, LocalNameFinder(args), 0)
self.locals.push(lnf.getLocals())
- self.emit('SET_LINENO', func.lineno)
- if hasTupleArg:
+ self.emit('SET_LINENO', func.lineno)
+ if hasTupleArg:
self.generateArgUnpack(func.argnames)
walk(func.code, self)
@@ -239,7 +238,7 @@ class CodeGenerator:
def generateClassCode(self, klass):
self.code = PyAssembler(name=klass.name,
- filename=filename)
+ filename=self.filename)
self.emit('SET_LINENO', klass.lineno)
lnf = walk(klass.code, LocalNameFinder(), 0)
self.locals.push(lnf.getLocals())
@@ -254,7 +253,7 @@ class CodeGenerator:
return self.code.makeCodeObject()
def isLocalName(self, name):
- return self.locals.top().has_elt(name)
+ return self.locals.top().has_elt(name)
def _nameOp(self, prefix, name):
if self.isLocalName(name):
@@ -290,8 +289,8 @@ class CodeGenerator:
self.emit('SET_LINENO', node.lineno)
def visitModule(self, node):
- lnf = walk(node.node, LocalNameFinder(), 0)
- self.locals.push(lnf.getLocals())
+ lnf = walk(node.node, LocalNameFinder(), 0)
+ self.locals.push(lnf.getLocals())
self.visit(node.node)
self.emit('LOAD_CONST', None)
self.emit('RETURN_VALUE')
@@ -353,15 +352,15 @@ class CodeGenerator:
kw = 0
if hasattr(node, 'lineno'):
self.emit('SET_LINENO', node.lineno)
- self.visit(node.node)
- for arg in node.args:
- self.visit(arg)
+ self.visit(node.node)
+ for arg in node.args:
+ self.visit(arg)
if isinstance(arg, ast.Keyword):
kw = kw + 1
else:
pos = pos + 1
- self.emit('CALL_FUNCTION', kw << 8 | pos)
- return 1
+ self.emit('CALL_FUNCTION', kw << 8 | pos)
+ return 1
def visitKeyword(self, node):
self.emit('LOAD_CONST', node.name)
@@ -369,24 +368,24 @@ class CodeGenerator:
return 1
def visitIf(self, node):
- after = StackRef()
- for test, suite in node.tests:
+ after = StackRef()
+ for test, suite in node.tests:
if hasattr(test, 'lineno'):
self.emit('SET_LINENO', test.lineno)
else:
print "warning", "no line number"
- self.visit(test)
- dest = StackRef()
- self.emit('JUMP_IF_FALSE', dest)
- self.emit('POP_TOP')
- self.visit(suite)
- self.emit('JUMP_FORWARD', after)
- dest.bind(self.code.getCurInst())
- self.emit('POP_TOP')
- if node.else_:
- self.visit(node.else_)
- after.bind(self.code.getCurInst())
- return 1
+ self.visit(test)
+ dest = StackRef()
+ self.emit('JUMP_IF_FALSE', dest)
+ self.emit('POP_TOP')
+ self.visit(suite)
+ self.emit('JUMP_FORWARD', after)
+ dest.bind(self.code.getCurInst())
+ self.emit('POP_TOP')
+ if node.else_:
+ self.visit(node.else_)
+ after.bind(self.code.getCurInst())
+ return 1
def startLoop(self):
l = Loop()
@@ -516,64 +515,64 @@ class CodeGenerator:
return 1
def visitCompare(self, node):
- """Comment from compile.c follows:
-
- The following code is generated for all but the last
- comparison in a chain:
-
- label: on stack: opcode: jump to:
-
- a <code to load b>
- a, b DUP_TOP
- a, b, b ROT_THREE
- b, a, b COMPARE_OP
- b, 0-or-1 JUMP_IF_FALSE L1
- b, 1 POP_TOP
- b
-
- We are now ready to repeat this sequence for the next
- comparison in the chain.
-
- For the last we generate:
-
- b <code to load c>
- b, c COMPARE_OP
- 0-or-1
-
- If there were any jumps to L1 (i.e., there was more than one
- comparison), we generate:
-
- 0-or-1 JUMP_FORWARD L2
- L1: b, 0 ROT_TWO
- 0, b POP_TOP
- 0
- L2: 0-or-1
- """
- self.visit(node.expr)
- # if refs are never emitted, subsequent bind call has no effect
- l1 = StackRef()
- l2 = StackRef()
- for op, code in node.ops[:-1]:
- # emit every comparison except the last
- self.visit(code)
- self.emit('DUP_TOP')
- self.emit('ROT_THREE')
- self.emit('COMPARE_OP', op)
+ """Comment from compile.c follows:
+
+ The following code is generated for all but the last
+ comparison in a chain:
+
+ label: on stack: opcode: jump to:
+
+ a <code to load b>
+ a, b DUP_TOP
+ a, b, b ROT_THREE
+ b, a, b COMPARE_OP
+ b, 0-or-1 JUMP_IF_FALSE L1
+ b, 1 POP_TOP
+ b
+
+ We are now ready to repeat this sequence for the next
+ comparison in the chain.
+
+ For the last we generate:
+
+ b <code to load c>
+ b, c COMPARE_OP
+ 0-or-1
+
+ If there were any jumps to L1 (i.e., there was more than one
+ comparison), we generate:
+
+ 0-or-1 JUMP_FORWARD L2
+ L1: b, 0 ROT_TWO
+ 0, b POP_TOP
+ 0
+ L2: 0-or-1
+ """
+ self.visit(node.expr)
+ # if refs are never emitted, subsequent bind call has no effect
+ l1 = StackRef()
+ l2 = StackRef()
+ for op, code in node.ops[:-1]:
+ # emit every comparison except the last
+ self.visit(code)
+ self.emit('DUP_TOP')
+ self.emit('ROT_THREE')
+ self.emit('COMPARE_OP', op)
# dupTop and compareOp cancel stack effect
- self.emit('JUMP_IF_FALSE', l1)
- self.emit('POP_TOP')
- if node.ops:
- # emit the last comparison
- op, code = node.ops[-1]
- self.visit(code)
- self.emit('COMPARE_OP', op)
- if len(node.ops) > 1:
- self.emit('JUMP_FORWARD', l2)
- l1.bind(self.code.getCurInst())
- self.emit('ROT_TWO')
- self.emit('POP_TOP')
- l2.bind(self.code.getCurInst())
- return 1
+ self.emit('JUMP_IF_FALSE', l1)
+ self.emit('POP_TOP')
+ if node.ops:
+ # emit the last comparison
+ op, code = node.ops[-1]
+ self.visit(code)
+ self.emit('COMPARE_OP', op)
+ if len(node.ops) > 1:
+ self.emit('JUMP_FORWARD', l2)
+ l1.bind(self.code.getCurInst())
+ self.emit('ROT_TWO')
+ self.emit('POP_TOP')
+ l2.bind(self.code.getCurInst())
+ return 1
def visitGetattr(self, node):
self.visit(node.expr)
@@ -590,7 +589,7 @@ class CodeGenerator:
self.emit('BINARY_SUBSCR')
elif node.flags == 'OP_ASSIGN':
self.emit('STORE_SUBSCR')
- elif node.flags == 'OP_DELETE':
+ elif node.flags == 'OP_DELETE':
self.emit('DELETE_SUBSCR')
return 1
@@ -624,11 +623,11 @@ class CodeGenerator:
def visitAssign(self, node):
self.emit('SET_LINENO', node.lineno)
self.visit(node.expr)
- dups = len(node.nodes) - 1
+ dups = len(node.nodes) - 1
for i in range(len(node.nodes)):
- elt = node.nodes[i]
- if i < dups:
- self.emit('DUP_TOP')
+ elt = node.nodes[i]
+ if i < dups:
+ self.emit('DUP_TOP')
if isinstance(elt, ast.Node):
self.visit(elt)
return 1
@@ -659,10 +658,10 @@ class CodeGenerator:
visitAssList = visitAssTuple
def binaryOp(self, node, op):
- self.visit(node.left)
- self.visit(node.right)
- self.emit(op)
- return 1
+ self.visit(node.left)
+ self.visit(node.right)
+ self.emit(op)
+ return 1
def unaryOp(self, node, op):
self.visit(node.expr)
@@ -670,28 +669,28 @@ class CodeGenerator:
return 1
def visitAdd(self, node):
- return self.binaryOp(node, 'BINARY_ADD')
+ return self.binaryOp(node, 'BINARY_ADD')
def visitSub(self, node):
- return self.binaryOp(node, 'BINARY_SUBTRACT')
+ return self.binaryOp(node, 'BINARY_SUBTRACT')
def visitMul(self, node):
- return self.binaryOp(node, 'BINARY_MULTIPLY')
+ return self.binaryOp(node, 'BINARY_MULTIPLY')
def visitDiv(self, node):
- return self.binaryOp(node, 'BINARY_DIVIDE')
+ return self.binaryOp(node, 'BINARY_DIVIDE')
def visitMod(self, node):
- return self.binaryOp(node, 'BINARY_MODULO')
+ return self.binaryOp(node, 'BINARY_MODULO')
def visitPower(self, node):
- return self.binaryOp(node, 'BINARY_POWER')
+ return self.binaryOp(node, 'BINARY_POWER')
def visitLeftShift(self, node):
- return self.binaryOp(node, 'BINARY_LSHIFT')
+ return self.binaryOp(node, 'BINARY_LSHIFT')
def visitRightShift(self, node):
- return self.binaryOp(node, 'BINARY_RSHIFT')
+ return self.binaryOp(node, 'BINARY_RSHIFT')
def visitInvert(self, node):
return self.unaryOp(node, 'UNARY_INVERT')
@@ -712,20 +711,20 @@ class CodeGenerator:
return self.unaryOp(node, 'UNARY_CONVERT')
def bitOp(self, nodes, op):
- self.visit(nodes[0])
- for node in nodes[1:]:
- self.visit(node)
- self.emit(op)
- return 1
+ self.visit(nodes[0])
+ for node in nodes[1:]:
+ self.visit(node)
+ self.emit(op)
+ return 1
def visitBitand(self, node):
- return self.bitOp(node.nodes, 'BINARY_AND')
+ return self.bitOp(node.nodes, 'BINARY_AND')
def visitBitor(self, node):
- return self.bitOp(node.nodes, 'BINARY_OR')
+ return self.bitOp(node.nodes, 'BINARY_OR')
def visitBitxor(self, node):
- return self.bitOp(node.nodes, 'BINARY_XOR')
+ return self.bitOp(node.nodes, 'BINARY_XOR')
def visitTest(self, node, jump):
end = StackRef()
@@ -738,22 +737,22 @@ class CodeGenerator:
return 1
def visitAssert(self, node):
- # XXX __debug__ and AssertionError appear to be special cases
- # -- they are always loaded as globals even if there are local
- # names. I guess this is a sort of renaming op.
- skip = StackRef()
- self.emit('SET_LINENO', node.lineno)
- self.emit('LOAD_GLOBAL', '__debug__')
- self.emit('JUMP_IF_FALSE', skip)
- self.emit('POP_TOP')
- self.visit(node.test)
- self.emit('JUMP_IF_TRUE', skip)
- self.emit('LOAD_GLOBAL', 'AssertionError')
- self.visit(node.fail)
- self.emit('RAISE_VARARGS', 2)
- skip.bind(self.code.getCurInst())
- self.emit('POP_TOP')
- return 1
+ # XXX __debug__ and AssertionError appear to be special cases
+ # -- they are always loaded as globals even if there are local
+ # names. I guess this is a sort of renaming op.
+ skip = StackRef()
+ self.emit('SET_LINENO', node.lineno)
+ self.emit('LOAD_GLOBAL', '__debug__')
+ self.emit('JUMP_IF_FALSE', skip)
+ self.emit('POP_TOP')
+ self.visit(node.test)
+ self.emit('JUMP_IF_TRUE', skip)
+ self.emit('LOAD_GLOBAL', 'AssertionError')
+ self.visit(node.fail)
+ self.emit('RAISE_VARARGS', 2)
+ skip.bind(self.code.getCurInst())
+ self.emit('POP_TOP')
+ return 1
def visitAnd(self, node):
return self.visitTest(node, 'JUMP_IF_FALSE')
@@ -765,12 +764,12 @@ class CodeGenerator:
self.loadName(node.name)
def visitConst(self, node):
- self.emit('LOAD_CONST', node.value)
+ self.emit('LOAD_CONST', node.value)
return 1
def visitEllipsis(self, node):
- self.emit('LOAD_CONST', Ellipsis)
- return 1
+ self.emit('LOAD_CONST', Ellipsis)
+ return 1
def visitTuple(self, node):
for elt in node.nodes:
@@ -785,76 +784,76 @@ class CodeGenerator:
return 1
def visitDict(self, node):
- self.emit('BUILD_MAP', 0)
- for k, v in node.items:
- # XXX need to add set lineno when there aren't constants
- self.emit('DUP_TOP')
- self.visit(v)
- self.emit('ROT_TWO')
- self.visit(k)
- self.emit('STORE_SUBSCR')
- return 1
+ self.emit('BUILD_MAP', 0)
+ for k, v in node.items:
+ # XXX need to add set lineno when there aren't constants
+ self.emit('DUP_TOP')
+ self.visit(v)
+ self.emit('ROT_TWO')
+ self.visit(k)
+ self.emit('STORE_SUBSCR')
+ return 1
def visitReturn(self, node):
- self.emit('SET_LINENO', node.lineno)
- self.visit(node.value)
- self.emit('RETURN_VALUE')
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ self.visit(node.value)
+ self.emit('RETURN_VALUE')
+ return 1
def visitRaise(self, node):
- self.emit('SET_LINENO', node.lineno)
- n = 0
- if node.expr1:
- self.visit(node.expr1)
- n = n + 1
- if node.expr2:
- self.visit(node.expr2)
- n = n + 1
- if node.expr3:
- self.visit(node.expr3)
- n = n + 1
- self.emit('RAISE_VARARGS', n)
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ n = 0
+ if node.expr1:
+ self.visit(node.expr1)
+ n = n + 1
+ if node.expr2:
+ self.visit(node.expr2)
+ n = n + 1
+ if node.expr3:
+ self.visit(node.expr3)
+ n = n + 1
+ self.emit('RAISE_VARARGS', n)
+ return 1
def visitPrint(self, node):
- self.emit('SET_LINENO', node.lineno)
- for child in node.nodes:
- self.visit(child)
- self.emit('PRINT_ITEM')
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ for child in node.nodes:
+ self.visit(child)
+ self.emit('PRINT_ITEM')
+ return 1
def visitPrintnl(self, node):
- self.visitPrint(node)
- self.emit('PRINT_NEWLINE')
- return 1
+ self.visitPrint(node)
+ self.emit('PRINT_NEWLINE')
+ return 1
def visitExec(self, node):
- self.visit(node.expr)
- if node.locals is None:
- self.emit('LOAD_CONST', None)
- else:
- self.visit(node.locals)
- if node.globals is None:
- self.emit('DUP_TOP')
- else:
- self.visit(node.globals)
- self.emit('EXEC_STMT')
+ self.visit(node.expr)
+ if node.locals is None:
+ self.emit('LOAD_CONST', None)
+ else:
+ self.visit(node.locals)
+ if node.globals is None:
+ self.emit('DUP_TOP')
+ else:
+ self.visit(node.globals)
+ self.emit('EXEC_STMT')
class LocalNameFinder:
def __init__(self, names=()):
- self.names = misc.Set()
+ self.names = misc.Set()
self.globals = misc.Set()
- for name in names:
- self.names.add(name)
+ for name in names:
+ self.names.add(name)
def getLocals(self):
for elt in self.globals.items():
if self.names.has_elt(elt):
self.names.remove(elt)
- return self.names
+ return self.names
def visitDict(self, node):
- return 1
+ return 1
def visitGlobal(self, node):
for name in node.names:
@@ -863,25 +862,25 @@ class LocalNameFinder:
def visitFunction(self, node):
self.names.add(node.name)
- return 1
+ return 1
def visitLambda(self, node):
return 1
def visitImport(self, node):
- for name in node.names:
- self.names.add(name)
+ for name in node.names:
+ self.names.add(name)
def visitFrom(self, node):
- for name in node.names:
- self.names.add(name)
+ for name in node.names:
+ self.names.add(name)
def visitClassdef(self, node):
- self.names.add(node.name)
- return 1
+ self.names.add(node.name)
+ return 1
def visitAssName(self, node):
- self.names.add(node.name)
+ self.names.add(node.name)
class Loop:
def __init__(self):
@@ -926,7 +925,13 @@ class CompiledModule:
mtime = os.stat(self.filename)[stat.ST_MTIME]
mtime = struct.pack('i', mtime)
return magic + mtime
-
+
+def compile(filename):
+ buf = open(filename).read()
+ mod = CompiledModule(buf, filename)
+ mod.compile()
+ mod.dump(filename + 'c')
+
if __name__ == "__main__":
import getopt
@@ -945,7 +950,4 @@ if __name__ == "__main__":
for filename in args:
if VERBOSE:
print filename
- buf = open(filename).read()
- mod = CompiledModule(buf, filename)
- mod.compile()
- mod.dump(filename + 'c')
+ compile(filename)
diff --git a/Tools/compiler/compiler/pycodegen.py b/Tools/compiler/compiler/pycodegen.py
index 9b9ee16..e9120cc 100644
--- a/Tools/compiler/compiler/pycodegen.py
+++ b/Tools/compiler/compiler/pycodegen.py
@@ -80,7 +80,7 @@ class ASTVisitor:
VERBOSE = 0
def __init__(self):
- self.node = None
+ self.node = None
def preorder(self, tree, visitor):
"""Do preorder walk of tree using visitor"""
@@ -163,27 +163,26 @@ class CodeGenerator:
# XXX should clean up initialization and generateXXX funcs
def __init__(self, filename="<?>"):
self.filename = filename
- self.code = PyAssembler()
+ self.code = PyAssembler()
self.code.setFlags(0)
- self.locals = misc.Stack()
+ self.locals = misc.Stack()
self.loops = misc.Stack()
self.namespace = 0
self.curStack = 0
self.maxStack = 0
def emit(self, *args):
- # XXX could just use self.emit = self.code.emit
- apply(self.code.emit, args)
+ # XXX could just use self.emit = self.code.emit
+ apply(self.code.emit, args)
def _generateFunctionOrLambdaCode(self, func):
self.name = func.name
- self.filename = filename
-
+
# keep a lookout for 'def foo((x,y)):'
args, hasTupleArg = self.generateArglist(func.argnames)
- self.code = PyAssembler(args=args, name=func.name,
- filename=filename)
+ self.code = PyAssembler(args=args, name=func.name,
+ filename=self.filename)
self.namespace = self.OPTIMIZED
if func.varargs:
self.code.setVarArgs()
@@ -191,8 +190,8 @@ class CodeGenerator:
self.code.setKWArgs()
lnf = walk(func.code, LocalNameFinder(args), 0)
self.locals.push(lnf.getLocals())
- self.emit('SET_LINENO', func.lineno)
- if hasTupleArg:
+ self.emit('SET_LINENO', func.lineno)
+ if hasTupleArg:
self.generateArgUnpack(func.argnames)
walk(func.code, self)
@@ -239,7 +238,7 @@ class CodeGenerator:
def generateClassCode(self, klass):
self.code = PyAssembler(name=klass.name,
- filename=filename)
+ filename=self.filename)
self.emit('SET_LINENO', klass.lineno)
lnf = walk(klass.code, LocalNameFinder(), 0)
self.locals.push(lnf.getLocals())
@@ -254,7 +253,7 @@ class CodeGenerator:
return self.code.makeCodeObject()
def isLocalName(self, name):
- return self.locals.top().has_elt(name)
+ return self.locals.top().has_elt(name)
def _nameOp(self, prefix, name):
if self.isLocalName(name):
@@ -290,8 +289,8 @@ class CodeGenerator:
self.emit('SET_LINENO', node.lineno)
def visitModule(self, node):
- lnf = walk(node.node, LocalNameFinder(), 0)
- self.locals.push(lnf.getLocals())
+ lnf = walk(node.node, LocalNameFinder(), 0)
+ self.locals.push(lnf.getLocals())
self.visit(node.node)
self.emit('LOAD_CONST', None)
self.emit('RETURN_VALUE')
@@ -353,15 +352,15 @@ class CodeGenerator:
kw = 0
if hasattr(node, 'lineno'):
self.emit('SET_LINENO', node.lineno)
- self.visit(node.node)
- for arg in node.args:
- self.visit(arg)
+ self.visit(node.node)
+ for arg in node.args:
+ self.visit(arg)
if isinstance(arg, ast.Keyword):
kw = kw + 1
else:
pos = pos + 1
- self.emit('CALL_FUNCTION', kw << 8 | pos)
- return 1
+ self.emit('CALL_FUNCTION', kw << 8 | pos)
+ return 1
def visitKeyword(self, node):
self.emit('LOAD_CONST', node.name)
@@ -369,24 +368,24 @@ class CodeGenerator:
return 1
def visitIf(self, node):
- after = StackRef()
- for test, suite in node.tests:
+ after = StackRef()
+ for test, suite in node.tests:
if hasattr(test, 'lineno'):
self.emit('SET_LINENO', test.lineno)
else:
print "warning", "no line number"
- self.visit(test)
- dest = StackRef()
- self.emit('JUMP_IF_FALSE', dest)
- self.emit('POP_TOP')
- self.visit(suite)
- self.emit('JUMP_FORWARD', after)
- dest.bind(self.code.getCurInst())
- self.emit('POP_TOP')
- if node.else_:
- self.visit(node.else_)
- after.bind(self.code.getCurInst())
- return 1
+ self.visit(test)
+ dest = StackRef()
+ self.emit('JUMP_IF_FALSE', dest)
+ self.emit('POP_TOP')
+ self.visit(suite)
+ self.emit('JUMP_FORWARD', after)
+ dest.bind(self.code.getCurInst())
+ self.emit('POP_TOP')
+ if node.else_:
+ self.visit(node.else_)
+ after.bind(self.code.getCurInst())
+ return 1
def startLoop(self):
l = Loop()
@@ -516,64 +515,64 @@ class CodeGenerator:
return 1
def visitCompare(self, node):
- """Comment from compile.c follows:
-
- The following code is generated for all but the last
- comparison in a chain:
-
- label: on stack: opcode: jump to:
-
- a <code to load b>
- a, b DUP_TOP
- a, b, b ROT_THREE
- b, a, b COMPARE_OP
- b, 0-or-1 JUMP_IF_FALSE L1
- b, 1 POP_TOP
- b
-
- We are now ready to repeat this sequence for the next
- comparison in the chain.
-
- For the last we generate:
-
- b <code to load c>
- b, c COMPARE_OP
- 0-or-1
-
- If there were any jumps to L1 (i.e., there was more than one
- comparison), we generate:
-
- 0-or-1 JUMP_FORWARD L2
- L1: b, 0 ROT_TWO
- 0, b POP_TOP
- 0
- L2: 0-or-1
- """
- self.visit(node.expr)
- # if refs are never emitted, subsequent bind call has no effect
- l1 = StackRef()
- l2 = StackRef()
- for op, code in node.ops[:-1]:
- # emit every comparison except the last
- self.visit(code)
- self.emit('DUP_TOP')
- self.emit('ROT_THREE')
- self.emit('COMPARE_OP', op)
+ """Comment from compile.c follows:
+
+ The following code is generated for all but the last
+ comparison in a chain:
+
+ label: on stack: opcode: jump to:
+
+ a <code to load b>
+ a, b DUP_TOP
+ a, b, b ROT_THREE
+ b, a, b COMPARE_OP
+ b, 0-or-1 JUMP_IF_FALSE L1
+ b, 1 POP_TOP
+ b
+
+ We are now ready to repeat this sequence for the next
+ comparison in the chain.
+
+ For the last we generate:
+
+ b <code to load c>
+ b, c COMPARE_OP
+ 0-or-1
+
+ If there were any jumps to L1 (i.e., there was more than one
+ comparison), we generate:
+
+ 0-or-1 JUMP_FORWARD L2
+ L1: b, 0 ROT_TWO
+ 0, b POP_TOP
+ 0
+ L2: 0-or-1
+ """
+ self.visit(node.expr)
+ # if refs are never emitted, subsequent bind call has no effect
+ l1 = StackRef()
+ l2 = StackRef()
+ for op, code in node.ops[:-1]:
+ # emit every comparison except the last
+ self.visit(code)
+ self.emit('DUP_TOP')
+ self.emit('ROT_THREE')
+ self.emit('COMPARE_OP', op)
# dupTop and compareOp cancel stack effect
- self.emit('JUMP_IF_FALSE', l1)
- self.emit('POP_TOP')
- if node.ops:
- # emit the last comparison
- op, code = node.ops[-1]
- self.visit(code)
- self.emit('COMPARE_OP', op)
- if len(node.ops) > 1:
- self.emit('JUMP_FORWARD', l2)
- l1.bind(self.code.getCurInst())
- self.emit('ROT_TWO')
- self.emit('POP_TOP')
- l2.bind(self.code.getCurInst())
- return 1
+ self.emit('JUMP_IF_FALSE', l1)
+ self.emit('POP_TOP')
+ if node.ops:
+ # emit the last comparison
+ op, code = node.ops[-1]
+ self.visit(code)
+ self.emit('COMPARE_OP', op)
+ if len(node.ops) > 1:
+ self.emit('JUMP_FORWARD', l2)
+ l1.bind(self.code.getCurInst())
+ self.emit('ROT_TWO')
+ self.emit('POP_TOP')
+ l2.bind(self.code.getCurInst())
+ return 1
def visitGetattr(self, node):
self.visit(node.expr)
@@ -590,7 +589,7 @@ class CodeGenerator:
self.emit('BINARY_SUBSCR')
elif node.flags == 'OP_ASSIGN':
self.emit('STORE_SUBSCR')
- elif node.flags == 'OP_DELETE':
+ elif node.flags == 'OP_DELETE':
self.emit('DELETE_SUBSCR')
return 1
@@ -624,11 +623,11 @@ class CodeGenerator:
def visitAssign(self, node):
self.emit('SET_LINENO', node.lineno)
self.visit(node.expr)
- dups = len(node.nodes) - 1
+ dups = len(node.nodes) - 1
for i in range(len(node.nodes)):
- elt = node.nodes[i]
- if i < dups:
- self.emit('DUP_TOP')
+ elt = node.nodes[i]
+ if i < dups:
+ self.emit('DUP_TOP')
if isinstance(elt, ast.Node):
self.visit(elt)
return 1
@@ -659,10 +658,10 @@ class CodeGenerator:
visitAssList = visitAssTuple
def binaryOp(self, node, op):
- self.visit(node.left)
- self.visit(node.right)
- self.emit(op)
- return 1
+ self.visit(node.left)
+ self.visit(node.right)
+ self.emit(op)
+ return 1
def unaryOp(self, node, op):
self.visit(node.expr)
@@ -670,28 +669,28 @@ class CodeGenerator:
return 1
def visitAdd(self, node):
- return self.binaryOp(node, 'BINARY_ADD')
+ return self.binaryOp(node, 'BINARY_ADD')
def visitSub(self, node):
- return self.binaryOp(node, 'BINARY_SUBTRACT')
+ return self.binaryOp(node, 'BINARY_SUBTRACT')
def visitMul(self, node):
- return self.binaryOp(node, 'BINARY_MULTIPLY')
+ return self.binaryOp(node, 'BINARY_MULTIPLY')
def visitDiv(self, node):
- return self.binaryOp(node, 'BINARY_DIVIDE')
+ return self.binaryOp(node, 'BINARY_DIVIDE')
def visitMod(self, node):
- return self.binaryOp(node, 'BINARY_MODULO')
+ return self.binaryOp(node, 'BINARY_MODULO')
def visitPower(self, node):
- return self.binaryOp(node, 'BINARY_POWER')
+ return self.binaryOp(node, 'BINARY_POWER')
def visitLeftShift(self, node):
- return self.binaryOp(node, 'BINARY_LSHIFT')
+ return self.binaryOp(node, 'BINARY_LSHIFT')
def visitRightShift(self, node):
- return self.binaryOp(node, 'BINARY_RSHIFT')
+ return self.binaryOp(node, 'BINARY_RSHIFT')
def visitInvert(self, node):
return self.unaryOp(node, 'UNARY_INVERT')
@@ -712,20 +711,20 @@ class CodeGenerator:
return self.unaryOp(node, 'UNARY_CONVERT')
def bitOp(self, nodes, op):
- self.visit(nodes[0])
- for node in nodes[1:]:
- self.visit(node)
- self.emit(op)
- return 1
+ self.visit(nodes[0])
+ for node in nodes[1:]:
+ self.visit(node)
+ self.emit(op)
+ return 1
def visitBitand(self, node):
- return self.bitOp(node.nodes, 'BINARY_AND')
+ return self.bitOp(node.nodes, 'BINARY_AND')
def visitBitor(self, node):
- return self.bitOp(node.nodes, 'BINARY_OR')
+ return self.bitOp(node.nodes, 'BINARY_OR')
def visitBitxor(self, node):
- return self.bitOp(node.nodes, 'BINARY_XOR')
+ return self.bitOp(node.nodes, 'BINARY_XOR')
def visitTest(self, node, jump):
end = StackRef()
@@ -738,22 +737,22 @@ class CodeGenerator:
return 1
def visitAssert(self, node):
- # XXX __debug__ and AssertionError appear to be special cases
- # -- they are always loaded as globals even if there are local
- # names. I guess this is a sort of renaming op.
- skip = StackRef()
- self.emit('SET_LINENO', node.lineno)
- self.emit('LOAD_GLOBAL', '__debug__')
- self.emit('JUMP_IF_FALSE', skip)
- self.emit('POP_TOP')
- self.visit(node.test)
- self.emit('JUMP_IF_TRUE', skip)
- self.emit('LOAD_GLOBAL', 'AssertionError')
- self.visit(node.fail)
- self.emit('RAISE_VARARGS', 2)
- skip.bind(self.code.getCurInst())
- self.emit('POP_TOP')
- return 1
+ # XXX __debug__ and AssertionError appear to be special cases
+ # -- they are always loaded as globals even if there are local
+ # names. I guess this is a sort of renaming op.
+ skip = StackRef()
+ self.emit('SET_LINENO', node.lineno)
+ self.emit('LOAD_GLOBAL', '__debug__')
+ self.emit('JUMP_IF_FALSE', skip)
+ self.emit('POP_TOP')
+ self.visit(node.test)
+ self.emit('JUMP_IF_TRUE', skip)
+ self.emit('LOAD_GLOBAL', 'AssertionError')
+ self.visit(node.fail)
+ self.emit('RAISE_VARARGS', 2)
+ skip.bind(self.code.getCurInst())
+ self.emit('POP_TOP')
+ return 1
def visitAnd(self, node):
return self.visitTest(node, 'JUMP_IF_FALSE')
@@ -765,12 +764,12 @@ class CodeGenerator:
self.loadName(node.name)
def visitConst(self, node):
- self.emit('LOAD_CONST', node.value)
+ self.emit('LOAD_CONST', node.value)
return 1
def visitEllipsis(self, node):
- self.emit('LOAD_CONST', Ellipsis)
- return 1
+ self.emit('LOAD_CONST', Ellipsis)
+ return 1
def visitTuple(self, node):
for elt in node.nodes:
@@ -785,76 +784,76 @@ class CodeGenerator:
return 1
def visitDict(self, node):
- self.emit('BUILD_MAP', 0)
- for k, v in node.items:
- # XXX need to add set lineno when there aren't constants
- self.emit('DUP_TOP')
- self.visit(v)
- self.emit('ROT_TWO')
- self.visit(k)
- self.emit('STORE_SUBSCR')
- return 1
+ self.emit('BUILD_MAP', 0)
+ for k, v in node.items:
+ # XXX need to add set lineno when there aren't constants
+ self.emit('DUP_TOP')
+ self.visit(v)
+ self.emit('ROT_TWO')
+ self.visit(k)
+ self.emit('STORE_SUBSCR')
+ return 1
def visitReturn(self, node):
- self.emit('SET_LINENO', node.lineno)
- self.visit(node.value)
- self.emit('RETURN_VALUE')
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ self.visit(node.value)
+ self.emit('RETURN_VALUE')
+ return 1
def visitRaise(self, node):
- self.emit('SET_LINENO', node.lineno)
- n = 0
- if node.expr1:
- self.visit(node.expr1)
- n = n + 1
- if node.expr2:
- self.visit(node.expr2)
- n = n + 1
- if node.expr3:
- self.visit(node.expr3)
- n = n + 1
- self.emit('RAISE_VARARGS', n)
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ n = 0
+ if node.expr1:
+ self.visit(node.expr1)
+ n = n + 1
+ if node.expr2:
+ self.visit(node.expr2)
+ n = n + 1
+ if node.expr3:
+ self.visit(node.expr3)
+ n = n + 1
+ self.emit('RAISE_VARARGS', n)
+ return 1
def visitPrint(self, node):
- self.emit('SET_LINENO', node.lineno)
- for child in node.nodes:
- self.visit(child)
- self.emit('PRINT_ITEM')
- return 1
+ self.emit('SET_LINENO', node.lineno)
+ for child in node.nodes:
+ self.visit(child)
+ self.emit('PRINT_ITEM')
+ return 1
def visitPrintnl(self, node):
- self.visitPrint(node)
- self.emit('PRINT_NEWLINE')
- return 1
+ self.visitPrint(node)
+ self.emit('PRINT_NEWLINE')
+ return 1
def visitExec(self, node):
- self.visit(node.expr)
- if node.locals is None:
- self.emit('LOAD_CONST', None)
- else:
- self.visit(node.locals)
- if node.globals is None:
- self.emit('DUP_TOP')
- else:
- self.visit(node.globals)
- self.emit('EXEC_STMT')
+ self.visit(node.expr)
+ if node.locals is None:
+ self.emit('LOAD_CONST', None)
+ else:
+ self.visit(node.locals)
+ if node.globals is None:
+ self.emit('DUP_TOP')
+ else:
+ self.visit(node.globals)
+ self.emit('EXEC_STMT')
class LocalNameFinder:
def __init__(self, names=()):
- self.names = misc.Set()
+ self.names = misc.Set()
self.globals = misc.Set()
- for name in names:
- self.names.add(name)
+ for name in names:
+ self.names.add(name)
def getLocals(self):
for elt in self.globals.items():
if self.names.has_elt(elt):
self.names.remove(elt)
- return self.names
+ return self.names
def visitDict(self, node):
- return 1
+ return 1
def visitGlobal(self, node):
for name in node.names:
@@ -863,25 +862,25 @@ class LocalNameFinder:
def visitFunction(self, node):
self.names.add(node.name)
- return 1
+ return 1
def visitLambda(self, node):
return 1
def visitImport(self, node):
- for name in node.names:
- self.names.add(name)
+ for name in node.names:
+ self.names.add(name)
def visitFrom(self, node):
- for name in node.names:
- self.names.add(name)
+ for name in node.names:
+ self.names.add(name)
def visitClassdef(self, node):
- self.names.add(node.name)
- return 1
+ self.names.add(node.name)
+ return 1
def visitAssName(self, node):
- self.names.add(node.name)
+ self.names.add(node.name)
class Loop:
def __init__(self):
@@ -926,7 +925,13 @@ class CompiledModule:
mtime = os.stat(self.filename)[stat.ST_MTIME]
mtime = struct.pack('i', mtime)
return magic + mtime
-
+
+def compile(filename):
+ buf = open(filename).read()
+ mod = CompiledModule(buf, filename)
+ mod.compile()
+ mod.dump(filename + 'c')
+
if __name__ == "__main__":
import getopt
@@ -945,7 +950,4 @@ if __name__ == "__main__":
for filename in args:
if VERBOSE:
print filename
- buf = open(filename).read()
- mod = CompiledModule(buf, filename)
- mod.compile()
- mod.dump(filename + 'c')
+ compile(filename)