[Python-checkins] python/dist/src/Lib/compiler pyassem.py,1.30,1.31 pycodegen.py,1.62,1.63 symbols.py,1.11,1.12 transformer.py,1.34,1.35
jhylton@users.sourceforge.net
jhylton@users.sourceforge.net
2002年12月31日 10:18:16 -0800
Update of /cvsroot/python/python/dist/src/Lib/compiler
In directory sc8-pr-cvs1:/tmp/cvs-serv3342/Lib/compiler
Modified Files:
pyassem.py pycodegen.py symbols.py transformer.py
Log Message:
SF patch [ 597919 ] compiler package and SET_LINENO
A variety of changes from Michael Hudson to get the compiler working
with 2.3. The primary change is the handling of SET_LINENO:
# The set_lineno() function and the explicit emit() calls for
# SET_LINENO below are only used to generate the line number table.
# As of Python 2.3, the interpreter does not have a SET_LINENO
# instruction. pyassem treats SET_LINENO opcodes as a special case.
A few other small changes:
- Remove unused code from pycodegen and pyassem.
- Fix error handling in parsermodule. When PyParser_SimplerParseString()
fails, it sets an exception with detailed info. The parsermodule
was clobbering that exception and replacing it was a generic
"could not parse string" exception. Keep the original exception.
Index: pyassem.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/compiler/pyassem.py,v
retrieving revision 1.30
retrieving revision 1.31
diff -C2 -d -r1.30 -r1.31
*** pyassem.py 6 Jun 2002 18:30:10 -0000 1.30
--- pyassem.py 31 Dec 2002 18:17:42 -0000 1.31
***************
*** 7,19 ****
from compiler import misc
! from compiler.consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, \
! CO_VARKEYWORDS
!
! def xxx_sort(l):
! l = l[:]
! def sorter(a, b):
! return cmp(a.bid, b.bid)
! l.sort(sorter)
! return l
class FlowGraph:
--- 7,12 ----
from compiler import misc
! from compiler.consts \
! import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
class FlowGraph:
***************
*** 78,82 ****
if self._debug:
print "\t", inst
! if inst[0] == 'RETURN_VALUE':
self.current.addOutEdge(self.exit)
if len(inst) == 2 and isinstance(inst[1], Block):
--- 71,75 ----
if self._debug:
print "\t", inst
! if inst[0] in ['RETURN_VALUE', 'YIELD_VALUE']:
self.current.addOutEdge(self.exit)
if len(inst) == 2 and isinstance(inst[1], Block):
***************
*** 267,271 ****
assert len(self.next) == 1, map(str, self.next)
! _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS',
'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
--- 260,264 ----
assert len(self.next) == 1, map(str, self.next)
! _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE',
'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
***************
*** 444,448 ****
if len(inst) == 1:
pc = pc + 1
! else:
# arg takes 2 bytes
pc = pc + 3
--- 437,441 ----
if len(inst) == 1:
pc = pc + 1
! elif inst[0] != "SET_LINENO":
# arg takes 2 bytes
pc = pc + 3
***************
*** 453,457 ****
if len(inst) == 1:
pc = pc + 1
! else:
pc = pc + 3
opname = inst[0]
--- 446,450 ----
if len(inst) == 1:
pc = pc + 1
! elif inst[0] != "SET_LINENO":
pc = pc + 3
opname = inst[0]
***************
*** 581,584 ****
--- 574,578 ----
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
+ continue
hi, lo = twobyte(oparg)
try:
***************
*** 698,702 ****
# compiler because it only generates a SET_LINENO instruction
# for the assignment.
! if line > 0:
push = self.lnotab.append
while addr > 255:
--- 692,696 ----
# compiler because it only generates a SET_LINENO instruction
# for the assignment.
! if line >= 0:
push = self.lnotab.append
while addr > 255:
***************
*** 769,772 ****
--- 763,767 ----
'PRINT_ITEM': -1,
'RETURN_VALUE': -1,
+ 'YIELD_VALUE': -1,
'EXEC_STMT': -3,
'BUILD_CLASS': -2,
Index: pycodegen.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/compiler/pycodegen.py,v
retrieving revision 1.62
retrieving revision 1.63
diff -C2 -d -r1.62 -r1.63
*** pycodegen.py 16 Dec 2002 13:54:01 -0000 1.62
--- pycodegen.py 31 Dec 2002 18:17:42 -0000 1.63
***************
*** 14,17 ****
--- 14,18 ----
from compiler.pyassem import TupleArg
+ # XXX The version-specific code can go, since this code only works with 2.x.
# Do we have Python 1.x or Python 2.x?
try:
***************
*** 33,46 ****
END_FINALLY = 4
- # XXX this doesn't seem to be used
- class BlockStack(misc.Stack):
- __super_init = misc.Stack.__init__
-
- def __init__(self):
- self.__super_init(self)
- self.loop = None
-
def compileFile(filename, display=0):
! f = open(filename)
buf = f.read()
f.close()
--- 34,39 ----
END_FINALLY = 4
def compileFile(filename, display=0):
! f = open(filename, 'U')
buf = f.read()
f.close()
***************
*** 48,52 ****
try:
mod.compile(display)
! except SyntaxError, err:
raise
else:
--- 41,45 ----
try:
mod.compile(display)
! except SyntaxError:
raise
else:
***************
*** 135,139 ****
# same effect is to call marshal and then skip the code.
mtime = os.path.getmtime(self.filename)
! mtime = struct.pack('i', mtime)
return self.MAGIC + mtime
--- 128,132 ----
# same effect is to call marshal and then skip the code.
mtime = os.path.getmtime(self.filename)
! mtime = struct.pack('<i', mtime)
return self.MAGIC + mtime
***************
*** 311,317 ****
self.emit(prefix + '_NAME', name)
! def set_lineno(self, node, force=0):
! """Emit SET_LINENO if node has lineno attribute and it is
! different than the last lineno emitted.
Returns true if SET_LINENO was emitted.
--- 304,318 ----
self.emit(prefix + '_NAME', name)
! # The set_lineno() function and the explicit emit() calls for
! # SET_LINENO below are only used to generate the line number table.
! # As of Python 2.3, the interpreter does not have a SET_LINENO
! # instruction. pyassem treats SET_LINENO opcodes as a special case.
!
! def set_lineno(self, node, force=False):
! """Emit SET_LINENO if necessary.
!
! The instruction is considered necessary if the node has a
! lineno attribute and it is different than the last lineno
! emitted.
Returns true if SET_LINENO was emitted.
***************
*** 327,332 ****
self.emit('SET_LINENO', lineno)
self.last_lineno = lineno
! return 1
! return 0
# The first few visitor methods handle nodes that generator new
--- 328,333 ----
self.emit('SET_LINENO', lineno)
self.last_lineno = lineno
! return True
! return False
# The first few visitor methods handle nodes that generator new
***************
*** 388,394 ****
gen = self.ClassGen(node, self.scopes,
self.get_module())
- if node.doc:
- self.emit('LOAD_CONST', node.doc)
- self.storeName('__doc__')
walk(node.code, gen)
gen.finish()
--- 389,392 ----
***************
*** 448,452 ****
self.setups.push((LOOP, loop))
! self.set_lineno(node, force=1)
self.visit(node.test)
self.emit('JUMP_IF_FALSE', else_ or after)
--- 446,450 ----
self.setups.push((LOOP, loop))
! self.set_lineno(node, force=True)
self.visit(node.test)
self.emit('JUMP_IF_FALSE', else_ or after)
***************
*** 618,622 ****
def visitListCompIf(self, node, branch):
! self.set_lineno(node, force=1)
self.visit(node.test)
self.emit('JUMP_IF_FALSE', branch)
--- 616,620 ----
def visitListCompIf(self, node, branch):
! self.set_lineno(node, force=True)
self.visit(node.test)
self.emit('JUMP_IF_FALSE', branch)
***************
*** 976,980 ****
self.set_lineno(node)
self.visit(node.value)
! self.emit('YIELD_STMT')
# slice and subscript stuff
--- 974,978 ----
self.set_lineno(node)
self.visit(node.value)
! self.emit('YIELD_VALUE')
# slice and subscript stuff
***************
*** 1267,1273 ****
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
! if self.graph.checkFlag(CO_GENERATOR_ALLOWED):
! if self.scope.generator is not None:
! self.graph.setFlag(CO_GENERATOR)
class AbstractClassCode:
--- 1265,1270 ----
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
! if self.scope.generator is not None:
! self.graph.setFlag(CO_GENERATOR)
class AbstractClassCode:
***************
*** 1305,1308 ****
--- 1302,1311 ----
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
+ self.set_lineno(klass)
+ self.emit("LOAD_GLOBAL", "__name__")
+ self.storeName("__module__")
+ if klass.doc:
+ self.emit("LOAD_CONST", klass.doc)
+ self.storeName('__doc__')
def generateArgList(arglist):
***************
*** 1380,1385 ****
if __name__ == "__main__":
- import sys
-
for file in sys.argv[1:]:
compileFile(file)
--- 1383,1386 ----
Index: symbols.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/compiler/symbols.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** symbols.py 21 Dec 2001 20:03:35 -0000 1.11
--- symbols.py 31 Dec 2002 18:17:42 -0000 1.12
***************
*** 250,253 ****
--- 250,256 ----
if parent.nested or isinstance(parent, FunctionScope):
scope.nested = 1
+ if node.doc is not None:
+ scope.add_def('__doc__')
+ scope.add_def('__module__')
self.scopes[node] = scope
prev = self.klass
Index: transformer.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/compiler/transformer.py,v
retrieving revision 1.34
retrieving revision 1.35
diff -C2 -d -r1.34 -r1.35
*** transformer.py 6 Jun 2002 18:30:10 -0000 1.34
--- transformer.py 31 Dec 2002 18:17:42 -0000 1.35
***************
*** 38,42 ****
def parseFile(path):
f = open(path)
! src = f.read()
f.close()
return parse(src)
--- 38,46 ----
def parseFile(path):
f = open(path)
! # XXX The parser API tolerates files without a trailing newline,
! # but not strings without a trailing newline. Always add an extra
! # newline to the file contents, since we're going through the string
! # version of the API.
! src = f.read() + "\n"
f.close()
return parse(src)
***************
*** 101,104 ****
--- 105,109 ----
token.NAME: self.atom_name,
}
+ self.encoding = None
def transform(self, tree):
***************
*** 111,114 ****
--- 116,120 ----
"""Return a modified parse tree for the given suite text."""
# Hack for handling non-native line endings on non-DOS like OSs.
+ # this can go now we have universal newlines?
text = text.replace('\x0d', '')
return self.transform(parser.suite(text))
***************
*** 132,135 ****
--- 138,147 ----
### emit a line-number node?
n = node[0]
+
+ if n == symbol.encoding_decl:
+ self.encoding = node[2]
+ node = node[1]
+ n = node[0]
+
if n == symbol.single_input:
return self.single_input(node[1:])
***************
*** 520,523 ****
--- 532,536 ----
testlist_safe = testlist # XXX
+ testlist1 = testlist
exprlist = testlist
***************
*** 638,646 ****
--- 651,662 ----
elt = nodelist[0]
t = elt[0]
+ print "source", nodelist[-1]
node = self.com_node(nodelist[-1])
+ # need to handle (unary op)constant here...
if t == token.PLUS:
node = UnaryAdd(node)
node.lineno = elt[2]
elif t == token.MINUS:
+ print node
node = UnarySub(node)
node.lineno = elt[2]
***************
*** 700,708 ****
return n
def atom_string(self, nodelist):
- ### need to verify this matches compile.c
k = ''
for node in nodelist:
! k = k + eval(node[1])
n = Const(k)
n.lineno = nodelist[0][2]
--- 716,734 ----
return n
+ def decode_literal(self, lit):
+ if self.encoding:
+ # this is particularly fragile & a bit of a
+ # hack... changes in compile.c:parsestr and
+ # tokenizer.c must be reflected here.
+ if self.encoding not in ['utf-8', 'iso-8859-1']:
+ lit = unicode(lit, 'utf-8').encode(self.encoding)
+ return eval("# coding: %s\n%s" % (self.encoding, lit))
+ else:
+ return eval(lit)
+
def atom_string(self, nodelist):
k = ''
for node in nodelist:
! k += self.decode_literal(node[1])
n = Const(k)
n.lineno = nodelist[0][2]