[Python-checkins] CVS: python/dist/src/Tools/compiler/compiler pycodegen.py,1.39,1.39.2.1
Jeremy Hylton
jhylton@users.sourceforge.net
Mon, 17 Dec 2001 16:06:05 -0800
Update of /cvsroot/python/python/dist/src/Tools/compiler/compiler
In directory usw-pr-cvs1:/tmp/cvs-serv31507
Modified Files:
Tag: release21-maint
pycodegen.py
Log Message:
Backport bugfixes since rev 1.39 from the trunk.
Add is_constant_false(), rev 1.41.
Fixed print handling, rev. 1.41.
Handle private names, 1.42.
Make sure JUMP_ABS and POP_BLOCK blocks are contiguous, rev. 1.44.
Make sure class object has no co_varnames, rev. 1.45.
Fix typo in visitDict(), rev. 1.46.
Generate correct code for continue in try/except, rev. 1.47.
Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Tools/compiler/compiler/Attic/pycodegen.py,v
retrieving revision 1.39
retrieving revision 1.39.2.1
diff -C2 -d -r1.39 -r1.39.2.1
*** pycodegen.py 2001/04/12 21:54:41 1.39
--- pycodegen.py 2001/12/18 00:06:03 1.39.2.1
***************
*** 12,17 ****
from compiler import pyassem, misc, future, symbols
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
! from compiler.pyassem import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
! CO_NESTED, TupleArg
# Do we have Python 1.x or Python 2.x?
--- 12,18 ----
from compiler import pyassem, misc, future, symbols
from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
! from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
! CO_NESTED
! from compiler.pyassem import TupleArg
# Do we have Python 1.x or Python 2.x?
***************
*** 29,32 ****
--- 30,38 ----
}
+ LOOP = 1
+ EXCEPT = 2
+ TRY_FINALLY = 3
+ END_FINALLY = 4
+
def compile(filename, display=0):
f = open(filename)
***************
*** 34,41 ****
f.close()
mod = Module(buf, filename)
! mod.compile(display)
! f = open(filename + "c", "wb")
! mod.dump(f)
! f.close()
class Module:
--- 40,51 ----
f.close()
mod = Module(buf, filename)
! try:
! mod.compile(display)
! except SyntaxError:
! raise
! else:
! f = open(filename + "c", "wb")
! mod.dump(f)
! f.close()
class Module:
***************
*** 116,119 ****
--- 126,135 ----
self.names.add(node.name)
+ def is_constant_false(node):
+ if isinstance(node, ast.Const):
+ if not node.value:
+ return 1
+ return 0
+
class CodeGenerator:
"""Defines basic code generator for Python bytecode
***************
*** 132,135 ****
--- 148,152 ----
optimized = 0 # is namespace access optimized?
__initialized = None
+ class_name = None # provide default for instance variable
def __init__(self, filename):
***************
*** 140,144 ****
self.filename = filename
self.locals = misc.Stack()
! self.loops = misc.Stack()
self.curStack = 0
self.maxStack = 0
--- 157,161 ----
self.filename = filename
self.locals = misc.Stack()
! self.setups = misc.Stack()
self.curStack = 0
self.maxStack = 0
***************
*** 171,174 ****
--- 188,202 ----
return self.graph.getCode()
+ def mangle(self, name):
+ if self.class_name is not None:
+ return misc.mangle(name, self.class_name)
+ else:
+ return name
+
+ def parseSymbols(self, tree):
+ s = symbols.SymbolVisitor()
+ walk(tree, s)
+ return s.scopes
+
# Next five methods handle name access
***************
*** 186,196 ****
def _nameOp(self, prefix, name):
! if not self.optimized:
! self.emit(prefix + '_NAME', name)
! return
! if self.isLocalName(name):
! self.emit(prefix + '_FAST', name)
else:
! self.emit(prefix + '_GLOBAL', name)
def _implicitNameOp(self, prefix, name):
--- 214,234 ----
def _nameOp(self, prefix, name):
! name = self.mangle(name)
! scope = self.scope.check_name(name)
! if scope == SC_LOCAL:
! if not self.optimized:
! self.emit(prefix + '_NAME', name)
! else:
! self.emit(prefix + '_FAST', name)
! elif scope == SC_GLOBAL:
! if not self.optimized:
! self.emit(prefix + '_NAME', name)
! else:
! self.emit(prefix + '_GLOBAL', name)
! elif scope == SC_FREE or scope == SC_CELL:
! self.emit(prefix + '_DEREF', name)
else:
! raise RuntimeError, "unsupported scope for var %s: %d" % \
! (name, scope)
def _implicitNameOp(self, prefix, name):
***************
*** 234,242 ****
def visitModule(self, node):
self.emit('SET_LINENO', 0)
- lnf = walk(node.node, self.NameFinder(), 0)
- self.locals.push(lnf.getLocals())
if node.doc:
! self.fixDocstring(node.node)
self.visit(node.node)
self.emit('LOAD_CONST', None)
--- 272,283 ----
def visitModule(self, node):
+ self.scopes = self.parseSymbols(node)
+ self.scope = self.scopes[node]
self.emit('SET_LINENO', 0)
if node.doc:
! self.emit('LOAD_CONST', node.doc)
! self.storeName('__doc__')
! lnf = walk(node.node, self.NameFinder(), verbose=0)
! self.locals.push(lnf.getLocals())
self.visit(node.node)
self.emit('LOAD_CONST', None)
***************
*** 253,257 ****
def _visitFuncOrLambda(self, node, isLambda=0):
! gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
walk(node.code, gen)
gen.finish()
--- 294,299 ----
def _visitFuncOrLambda(self, node, isLambda=0):
! gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
! self.class_name)
walk(node.code, gen)
gen.finish()
***************
*** 263,269 ****
def visitClass(self, node):
! gen = self.ClassGen(node, self.filename, self.scopes)
! if node.doc:
! self.fixDocstring(node.code)
walk(node.code, gen)
gen.finish()
--- 305,309 ----
def visitClass(self, node):
! gen = self.ClassGen(node, self.scopes, self.filename)
walk(node.code, gen)
gen.finish()
***************
*** 279,295 ****
self.storeName(node.name)
- def fixDocstring(self, node):
- """Rewrite the ast for a class with a docstring.
-
- The AST includes a Discard(Const(docstring)) node. Replace
- this with an Assign([AssName('__doc__', ...])
- """
- assert isinstance(node, ast.Stmt)
- stmts = node.nodes
- discard = stmts[0]
- assert isinstance(discard, ast.Discard)
- stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
- discard.expr)
- stmts[0].lineno = discard.lineno
# The rest are standard visitor methods
--- 319,322 ----
***************
*** 301,304 ****
--- 328,333 ----
for i in range(numtests):
test, suite = node.tests[i]
+ if is_constant_false(test):
+ continue
self.set_lineno(test)
self.visit(test)
***************
*** 325,329 ****
self.nextBlock(loop)
! self.loops.push(loop)
self.set_lineno(node, force=1)
--- 354,358 ----
self.nextBlock(loop)
! self.setups.push((LOOP, loop))
self.set_lineno(node, force=1)
***************
*** 339,343 ****
self.emit('POP_TOP')
self.emit('POP_BLOCK')
! self.loops.pop()
if node.else_:
self.visit(node.else_)
--- 368,372 ----
self.emit('POP_TOP')
self.emit('POP_BLOCK')
! self.setups.pop()
if node.else_:
self.visit(node.else_)
***************
*** 348,352 ****
anchor = self.newBlock()
after = self.newBlock()
! self.loops.push(start)
self.set_lineno(node)
--- 377,381 ----
anchor = self.newBlock()
after = self.newBlock()
! self.setups.push((LOOP, start))
self.set_lineno(node)
***************
*** 357,367 ****
self.set_lineno(node, force=1)
self.emit('FOR_LOOP', anchor)
! self.nextBlock()
self.visit(node.assign)
self.visit(node.body)
self.emit('JUMP_ABSOLUTE', start)
! self.startBlock(anchor)
self.emit('POP_BLOCK')
! self.loops.pop()
if node.else_:
self.visit(node.else_)
--- 386,397 ----
self.set_lineno(node, force=1)
self.emit('FOR_LOOP', anchor)
! ## self.nextBlock()
self.visit(node.assign)
self.visit(node.body)
self.emit('JUMP_ABSOLUTE', start)
! ## self.startBlock(anchor)
! self.nextBlock(anchor)
self.emit('POP_BLOCK')
! self.setups.pop()
if node.else_:
self.visit(node.else_)
***************
*** 369,373 ****
def visitBreak(self, node):
! if not self.loops:
raise SyntaxError, "'break' outside loop (%s, %d)" % \
(self.filename, node.lineno)
--- 399,403 ----
def visitBreak(self, node):
! if not self.setups:
raise SyntaxError, "'break' outside loop (%s, %d)" % \
(self.filename, node.lineno)
***************
*** 376,386 ****
def visitContinue(self, node):
! if not self.loops:
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
(self.filename, node.lineno)
! l = self.loops.top()
! self.set_lineno(node)
! self.emit('JUMP_ABSOLUTE', l)
! self.nextBlock()
def visitTest(self, node, jump):
--- 406,435 ----
def visitContinue(self, node):
! # XXX test_grammar.py, line 351
! if not self.setups:
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
(self.filename, node.lineno)
! kind, block = self.setups.top()
! if kind == LOOP:
! self.set_lineno(node)
! self.emit('JUMP_ABSOLUTE', block)
! self.nextBlock()
! elif kind == EXCEPT or kind == TRY_FINALLY:
! self.set_lineno(node)
! # find the block that starts the loop
! top = len(self.setups)
! while top > 0:
! top = top - 1
! kind, loop_block = self.setups[top]
! if kind == LOOP:
! break
! if kind != LOOP:
! raise SyntaxError, "'continue' outside loop (%s, %d)" % \
! (self.filename, node.lineno)
! self.emit('CONTINUE_LOOP', loop_block)
! self.nextBlock()
! elif kind == END_FINALLY:
! msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
! raise SyntaxError, msg % (self.filename, node.lineno)
def visitTest(self, node, jump):
***************
*** 527,530 ****
--- 576,580 ----
def visitTryExcept(self, node):
+ body = self.newBlock()
handlers = self.newBlock()
end = self.newBlock()
***************
*** 535,541 ****
self.set_lineno(node)
self.emit('SETUP_EXCEPT', handlers)
! self.nextBlock()
self.visit(node.body)
self.emit('POP_BLOCK')
self.emit('JUMP_FORWARD', lElse)
self.startBlock(handlers)
--- 585,593 ----
self.set_lineno(node)
self.emit('SETUP_EXCEPT', handlers)
! self.nextBlock(body)
! self.setups.push((EXCEPT, body))
self.visit(node.body)
self.emit('POP_BLOCK')
+ self.setups.pop()
self.emit('JUMP_FORWARD', lElse)
self.startBlock(handlers)
***************
*** 573,586 ****
def visitTryFinally(self, node):
final = self.newBlock()
self.set_lineno(node)
self.emit('SETUP_FINALLY', final)
! self.nextBlock()
self.visit(node.body)
self.emit('POP_BLOCK')
self.emit('LOAD_CONST', None)
self.nextBlock(final)
self.visit(node.final)
self.emit('END_FINALLY')
# misc
--- 625,643 ----
def visitTryFinally(self, node):
+ body = self.newBlock()
final = self.newBlock()
self.set_lineno(node)
self.emit('SETUP_FINALLY', final)
! self.nextBlock(body)
! self.setups.push((TRY_FINALLY, body))
self.visit(node.body)
self.emit('POP_BLOCK')
+ self.setups.pop()
self.emit('LOAD_CONST', None)
self.nextBlock(final)
+ self.setups.push((END_FINALLY, final))
self.visit(node.final)
self.emit('END_FINALLY')
+ self.setups.pop()
# misc
***************
*** 649,653 ****
def visitGetattr(self, node):
self.visit(node.expr)
! self.emit('LOAD_ATTR', node.attrname)
# next five implement assignments
--- 706,710 ----
def visitGetattr(self, node):
self.visit(node.expr)
! self.emit('LOAD_ATTR', self.mangle(node.attrname))
# next five implement assignments
***************
*** 668,671 ****
--- 725,729 ----
self.storeName(node.name)
elif node.flags == 'OP_DELETE':
+ self.set_lineno(node)
self.delName(node.name)
else:
***************
*** 675,681 ****
self.visit(node.expr)
if node.flags == 'OP_ASSIGN':
! self.emit('STORE_ATTR', node.attrname)
elif node.flags == 'OP_DELETE':
! self.emit('DELETE_ATTR', node.attrname)
else:
print "warning: unexpected flags:", node.flags
--- 733,739 ----
self.visit(node.expr)
if node.flags == 'OP_ASSIGN':
! self.emit('STORE_ATTR', self.mangle(node.attrname))
elif node.flags == 'OP_DELETE':
! self.emit('DELETE_ATTR', self.mangle(node.attrname))
else:
print "warning: unexpected flags:", node.flags
***************
*** 701,704 ****
--- 759,763 ----
def visitAugAssign(self, node):
+ self.set_lineno(node)
aug_node = wrap_aug(node.node)
self.visit(aug_node, "load")
***************
*** 731,738 ****
self.visit(node.expr)
self.emit('DUP_TOP')
! self.emit('LOAD_ATTR', node.attrname)
elif mode == "store":
self.emit('ROT_TWO')
! self.emit('STORE_ATTR', node.attrname)
def visitAugSlice(self, node, mode):
--- 790,797 ----
self.visit(node.expr)
self.emit('DUP_TOP')
! self.emit('LOAD_ATTR', self.mangle(node.attrname))
elif mode == "store":
self.emit('ROT_TWO')
! self.emit('STORE_ATTR', self.mangle(node.attrname))
def visitAugSlice(self, node, mode):
***************
*** 794,798 ****
self.emit(opcode, kw << 8 | pos)
! def visitPrint(self, node):
self.set_lineno(node)
if node.dest:
--- 853,857 ----
self.emit(opcode, kw << 8 | pos)
! def visitPrint(self, node, newline=0):
self.set_lineno(node)
if node.dest:
***************
*** 807,813 ****
else:
self.emit('PRINT_ITEM')
def visitPrintnl(self, node):
! self.visitPrint(node)
if node.dest:
self.emit('PRINT_NEWLINE_TO')
--- 866,874 ----
else:
self.emit('PRINT_ITEM')
+ if node.dest and not newline:
+ self.emit('POP_TOP')
def visitPrintnl(self, node):
! self.visitPrint(node, newline=1)
if node.dest:
self.emit('PRINT_NEWLINE_TO')
***************
*** 942,945 ****
--- 1003,1007 ----
def visitTuple(self, node):
+ self.set_lineno(node)
for elt in node.nodes:
self.visit(elt)
***************
*** 947,950 ****
--- 1009,1013 ----
def visitList(self, node):
+ self.set_lineno(node)
for elt in node.nodes:
self.visit(elt)
***************
*** 959,963 ****
lineno = getattr(node, 'lineno', None)
if lineno:
! set.emit('SET_LINENO', lineno)
self.emit('BUILD_MAP', 0)
for k, v in node.items:
--- 1022,1026 ----
lineno = getattr(node, 'lineno', None)
if lineno:
! self.emit('SET_LINENO', lineno)
self.emit('BUILD_MAP', 0)
for k, v in node.items:
***************
*** 988,991 ****
--- 1051,1055 ----
def _nameOp(self, prefix, name):
+ name = self.mangle(name)
scope = self.scope.check_name(name)
if scope == SC_LOCAL:
***************
*** 1003,1007 ****
def _visitFuncOrLambda(self, node, isLambda=0):
! gen = self.FunctionGen(node, self.filename, self.scopes, isLambda)
walk(node.code, gen)
gen.finish()
--- 1067,1072 ----
def _visitFuncOrLambda(self, node, isLambda=0):
! gen = self.FunctionGen(node, self.filename, self.scopes, isLambda,
! self.class_name)
walk(node.code, gen)
gen.finish()
***************
*** 1020,1026 ****
def visitClass(self, node):
! gen = self.ClassGen(node, self.filename, self.scopes)
! if node.doc:
! self.fixDocstring(node.code)
walk(node.code, gen)
gen.finish()
--- 1085,1089 ----
def visitClass(self, node):
! gen = self.ClassGen(node, self.scopes, self.filename)
walk(node.code, gen)
gen.finish()
***************
*** 1079,1083 ****
lambdaCount = 0
! def __init__(self, func, filename, scopes, isLambda):
if isLambda:
klass = FunctionCodeGenerator
--- 1142,1149 ----
lambdaCount = 0
! def __init__(self, func, filename, scopes, isLambda, class_name):
! self.scopes = scopes
! self.scope = scopes[func]
! self.class_name = class_name
if isLambda:
klass = FunctionCodeGenerator
***************
*** 1095,1099 ****
self.setDocstring(func.doc)
! lnf = walk(func.code, self.NameFinder(args), 0)
self.locals.push(lnf.getLocals())
if func.varargs:
--- 1161,1165 ----
self.setDocstring(func.doc)
! lnf = walk(func.code, self.NameFinder(args), verbose=0)
self.locals.push(lnf.getLocals())
if func.varargs:
***************
*** 1142,1149 ****
__super_init = AbstractFunctionCode.__init__
! def __init__(self, func, filename, scopes, isLambda):
self.scopes = scopes
self.scope = scopes[func]
! self.__super_init(func, filename, scopes, isLambda)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
--- 1208,1215 ----
__super_init = AbstractFunctionCode.__init__
! def __init__(self, func, filename, scopes, isLambda, class_name):
self.scopes = scopes
self.scope = scopes[func]
! self.__super_init(func, filename, scopes, isLambda, class_name)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
***************
*** 1152,1156 ****
class AbstractClassCode:
! def __init__(self, klass, filename, scopes):
self.graph = pyassem.PyFlowGraph(klass.name, filename,
optimized=0)
--- 1218,1224 ----
class AbstractClassCode:
! def __init__(self, klass, scopes, filename):
! assert isinstance(filename, types.StringType)
! assert isinstance(scopes, types.DictType)
self.graph = pyassem.PyFlowGraph(klass.name, filename,
optimized=0)
***************
*** 1175,1178 ****
--- 1243,1255 ----
scopes = None
+ __super_init = AbstractClassCode.__init__
+
+ def __init__(self, klass, scopes, filename):
+ self.scopes = scopes
+ self.scope = scopes[klass]
+ self.__super_init(klass, scopes, filename)
+ self.graph.setFreeVars(self.scope.get_free_vars())
+ self.graph.setCellVars(self.scope.get_cell_vars())
+
class NestedClassCodeGenerator(AbstractClassCode,
NestedScopeMixin,
***************
*** 1181,1188 ****
__super_init = AbstractClassCode.__init__
! def __init__(self, klass, filename, scopes):
self.scopes = scopes
self.scope = scopes[klass]
! self.__super_init(klass, filename, scopes)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
--- 1258,1266 ----
__super_init = AbstractClassCode.__init__
! def __init__(self, klass, scopes, filename):
! assert isinstance(filename, types.StringType)
self.scopes = scopes
self.scope = scopes[klass]
! self.__super_init(klass, scopes, filename)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
***************
*** 1209,1213 ****
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
v = OpFinder()
! walk(node, v, 0)
return v.op
--- 1287,1291 ----
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
v = OpFinder()
! walk(node, v, verbose=0)
return v.op
***************
*** 1221,1224 ****
--- 1299,1303 ----
raise ValueError, "mixed ops in stmt"
visitAssAttr = visitAssName
+ visitSubscript = visitAssName
class Delegator:
***************
*** 1250,1253 ****
--- 1329,1333 ----
class AugSubscript(Delegator):
pass
+
wrapper = {