mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +00:00
replace most calls to emit 'SET_LINENO' will call to method set_lineno
based on bug report by Neil Schemenauer
This commit is contained in:
parent
8612f1c152
commit
7daf04d9e0
2 changed files with 84 additions and 62 deletions
|
@ -105,6 +105,22 @@ class CodeGenerator:
|
||||||
else:
|
else:
|
||||||
self.emit(prefix + '_GLOBAL', name)
|
self.emit(prefix + '_GLOBAL', name)
|
||||||
|
|
||||||
|
def set_lineno(self, node):
|
||||||
|
"""Emit SET_LINENO if node has lineno attribute
|
||||||
|
|
||||||
|
Returns true if SET_LINENO was emitted.
|
||||||
|
|
||||||
|
There are no rules for when an AST node should have a lineno
|
||||||
|
attribute. The transformer and AST code need to be reviewed
|
||||||
|
and a consistent policy implemented and documented. Until
|
||||||
|
then, this method works around missing line numbers.
|
||||||
|
"""
|
||||||
|
lineno = getattr(node, 'lineno', None)
|
||||||
|
if lineno is not None:
|
||||||
|
self.emit('SET_LINENO', lineno)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
# The first few visitor methods handle nodes that generator new
|
# The first few visitor methods handle nodes that generator new
|
||||||
# code objects
|
# code objects
|
||||||
|
|
||||||
|
@ -128,7 +144,7 @@ class CodeGenerator:
|
||||||
gen = FunctionCodeGenerator(node, self.filename, isLambda)
|
gen = FunctionCodeGenerator(node, self.filename, isLambda)
|
||||||
walk(node.code, gen)
|
walk(node.code, gen)
|
||||||
gen.finish()
|
gen.finish()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for default in node.defaults:
|
for default in node.defaults:
|
||||||
self.visit(default)
|
self.visit(default)
|
||||||
self.emit('LOAD_CONST', gen.getCode())
|
self.emit('LOAD_CONST', gen.getCode())
|
||||||
|
@ -138,7 +154,7 @@ class CodeGenerator:
|
||||||
gen = ClassCodeGenerator(node, self.filename)
|
gen = ClassCodeGenerator(node, self.filename)
|
||||||
walk(node.code, gen)
|
walk(node.code, gen)
|
||||||
gen.finish()
|
gen.finish()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('LOAD_CONST', node.name)
|
self.emit('LOAD_CONST', node.name)
|
||||||
for base in node.bases:
|
for base in node.bases:
|
||||||
self.visit(base)
|
self.visit(base)
|
||||||
|
@ -158,8 +174,7 @@ class CodeGenerator:
|
||||||
numtests = len(node.tests)
|
numtests = len(node.tests)
|
||||||
for i in range(numtests):
|
for i in range(numtests):
|
||||||
test, suite = node.tests[i]
|
test, suite = node.tests[i]
|
||||||
if hasattr(test, 'lineno'):
|
self.set_lineno(test)
|
||||||
self.emit('SET_LINENO', test.lineno)
|
|
||||||
self.visit(test)
|
self.visit(test)
|
||||||
## if i == numtests - 1 and not node.else_:
|
## if i == numtests - 1 and not node.else_:
|
||||||
## nextTest = end
|
## nextTest = end
|
||||||
|
@ -178,7 +193,7 @@ class CodeGenerator:
|
||||||
self.nextBlock(end)
|
self.nextBlock(end)
|
||||||
|
|
||||||
def visitWhile(self, node):
|
def visitWhile(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
|
|
||||||
loop = self.newBlock()
|
loop = self.newBlock()
|
||||||
else_ = self.newBlock()
|
else_ = self.newBlock()
|
||||||
|
@ -189,7 +204,7 @@ class CodeGenerator:
|
||||||
self.nextBlock(loop)
|
self.nextBlock(loop)
|
||||||
self.loops.push(loop)
|
self.loops.push(loop)
|
||||||
|
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.test)
|
self.visit(node.test)
|
||||||
self.emit('JUMP_IF_FALSE', else_ or after)
|
self.emit('JUMP_IF_FALSE', else_ or after)
|
||||||
|
|
||||||
|
@ -212,12 +227,12 @@ class CodeGenerator:
|
||||||
after = self.newBlock()
|
after = self.newBlock()
|
||||||
self.loops.push(start)
|
self.loops.push(start)
|
||||||
|
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_LOOP', after)
|
self.emit('SETUP_LOOP', after)
|
||||||
self.visit(node.list)
|
self.visit(node.list)
|
||||||
self.visit(ast.Const(0))
|
self.visit(ast.Const(0))
|
||||||
self.nextBlock(start)
|
self.nextBlock(start)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('FOR_LOOP', anchor)
|
self.emit('FOR_LOOP', anchor)
|
||||||
self.visit(node.assign)
|
self.visit(node.assign)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
|
@ -233,7 +248,7 @@ class CodeGenerator:
|
||||||
if not self.loops:
|
if not self.loops:
|
||||||
raise SyntaxError, "'break' outside loop (%s, %d)" % \
|
raise SyntaxError, "'break' outside loop (%s, %d)" % \
|
||||||
(self.filename, node.lineno)
|
(self.filename, node.lineno)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('BREAK_LOOP')
|
self.emit('BREAK_LOOP')
|
||||||
|
|
||||||
def visitContinue(self, node):
|
def visitContinue(self, node):
|
||||||
|
@ -241,7 +256,7 @@ class CodeGenerator:
|
||||||
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
|
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
|
||||||
(self.filename, node.lineno)
|
(self.filename, node.lineno)
|
||||||
l = self.loops.top()
|
l = self.loops.top()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('JUMP_ABSOLUTE', l)
|
self.emit('JUMP_ABSOLUTE', l)
|
||||||
self.nextBlock()
|
self.nextBlock()
|
||||||
|
|
||||||
|
@ -291,7 +306,7 @@ class CodeGenerator:
|
||||||
# XXX would be interesting to implement this via a
|
# XXX would be interesting to implement this via a
|
||||||
# transformation of the AST before this stage
|
# transformation of the AST before this stage
|
||||||
end = self.newBlock()
|
end = self.newBlock()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
# XXX __debug__ and AssertionError appear to be special cases
|
# XXX __debug__ and AssertionError appear to be special cases
|
||||||
# -- they are always loaded as globals even if there are local
|
# -- they are always loaded as globals even if there are local
|
||||||
# names. I guess this is a sort of renaming op.
|
# names. I guess this is a sort of renaming op.
|
||||||
|
@ -309,7 +324,7 @@ class CodeGenerator:
|
||||||
self.emit('POP_TOP')
|
self.emit('POP_TOP')
|
||||||
|
|
||||||
def visitRaise(self, node):
|
def visitRaise(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
n = 0
|
n = 0
|
||||||
if node.expr1:
|
if node.expr1:
|
||||||
self.visit(node.expr1)
|
self.visit(node.expr1)
|
||||||
|
@ -329,7 +344,7 @@ class CodeGenerator:
|
||||||
lElse = self.newBlock()
|
lElse = self.newBlock()
|
||||||
else:
|
else:
|
||||||
lElse = end
|
lElse = end
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_EXCEPT', handlers)
|
self.emit('SETUP_EXCEPT', handlers)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
self.emit('POP_BLOCK')
|
self.emit('POP_BLOCK')
|
||||||
|
@ -339,8 +354,7 @@ class CodeGenerator:
|
||||||
last = len(node.handlers) - 1
|
last = len(node.handlers) - 1
|
||||||
for i in range(len(node.handlers)):
|
for i in range(len(node.handlers)):
|
||||||
expr, target, body = node.handlers[i]
|
expr, target, body = node.handlers[i]
|
||||||
if hasattr(expr, 'lineno'):
|
self.set_lineno(expr)
|
||||||
self.emit('SET_LINENO', expr.lineno)
|
|
||||||
if expr:
|
if expr:
|
||||||
self.emit('DUP_TOP')
|
self.emit('DUP_TOP')
|
||||||
self.visit(expr)
|
self.visit(expr)
|
||||||
|
@ -368,7 +382,7 @@ class CodeGenerator:
|
||||||
|
|
||||||
def visitTryFinally(self, node):
|
def visitTryFinally(self, node):
|
||||||
final = self.newBlock()
|
final = self.newBlock()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_FINALLY', final)
|
self.emit('SETUP_FINALLY', final)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
self.emit('POP_BLOCK')
|
self.emit('POP_BLOCK')
|
||||||
|
@ -402,16 +416,16 @@ class CodeGenerator:
|
||||||
self.loadName(node.name)
|
self.loadName(node.name)
|
||||||
|
|
||||||
def visitPass(self, node):
|
def visitPass(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
|
|
||||||
def visitImport(self, node):
|
def visitImport(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for name in node.names:
|
for name in node.names:
|
||||||
self.emit('IMPORT_NAME', name)
|
self.emit('IMPORT_NAME', name)
|
||||||
self.storeName(name)
|
self.storeName(name)
|
||||||
|
|
||||||
def visitFrom(self, node):
|
def visitFrom(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('IMPORT_NAME', node.modname)
|
self.emit('IMPORT_NAME', node.modname)
|
||||||
for name in node.names:
|
for name in node.names:
|
||||||
if name == '*':
|
if name == '*':
|
||||||
|
@ -426,7 +440,7 @@ class CodeGenerator:
|
||||||
# next five implement assignments
|
# next five implement assignments
|
||||||
|
|
||||||
def visitAssign(self, node):
|
def visitAssign(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.expr)
|
self.visit(node.expr)
|
||||||
dups = len(node.nodes) - 1
|
dups = len(node.nodes) - 1
|
||||||
for i in range(len(node.nodes)):
|
for i in range(len(node.nodes)):
|
||||||
|
@ -477,8 +491,7 @@ class CodeGenerator:
|
||||||
def visitCallFunc(self, node):
|
def visitCallFunc(self, node):
|
||||||
pos = 0
|
pos = 0
|
||||||
kw = 0
|
kw = 0
|
||||||
if hasattr(node, 'lineno'):
|
self.set_lineno(node)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
|
||||||
self.visit(node.node)
|
self.visit(node.node)
|
||||||
for arg in node.args:
|
for arg in node.args:
|
||||||
self.visit(arg)
|
self.visit(arg)
|
||||||
|
@ -496,7 +509,7 @@ class CodeGenerator:
|
||||||
self.emit(opcode, kw << 8 | pos)
|
self.emit(opcode, kw << 8 | pos)
|
||||||
|
|
||||||
def visitPrint(self, node):
|
def visitPrint(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for child in node.nodes:
|
for child in node.nodes:
|
||||||
self.visit(child)
|
self.visit(child)
|
||||||
self.emit('PRINT_ITEM')
|
self.emit('PRINT_ITEM')
|
||||||
|
@ -506,7 +519,7 @@ class CodeGenerator:
|
||||||
self.emit('PRINT_NEWLINE')
|
self.emit('PRINT_NEWLINE')
|
||||||
|
|
||||||
def visitReturn(self, node):
|
def visitReturn(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.value)
|
self.visit(node.value)
|
||||||
self.emit('RETURN_VALUE')
|
self.emit('RETURN_VALUE')
|
||||||
|
|
||||||
|
@ -637,15 +650,13 @@ class CodeGenerator:
|
||||||
self.emit('BUILD_SLICE', len(node.nodes))
|
self.emit('BUILD_SLICE', len(node.nodes))
|
||||||
|
|
||||||
def visitDict(self, node):
|
def visitDict(self, node):
|
||||||
# XXX is this a good general strategy? could it be done
|
lineno = getattr(node, 'lineno', None)
|
||||||
# separately from the general visitor
|
if lineno:
|
||||||
lineno = getattr(node, 'lineno', None)
|
set.emit('SET_LINENO', lineno)
|
||||||
if lineno:
|
|
||||||
self.emit('SET_LINENO', lineno)
|
|
||||||
self.emit('BUILD_MAP', 0)
|
self.emit('BUILD_MAP', 0)
|
||||||
for k, v in node.items:
|
for k, v in node.items:
|
||||||
lineno2 = getattr(node, 'lineno', None)
|
lineno2 = getattr(node, 'lineno', None)
|
||||||
if lineno != lineno2:
|
if lineno2 is not None and lineno != lineno2:
|
||||||
self.emit('SET_LINENO', lineno2)
|
self.emit('SET_LINENO', lineno2)
|
||||||
lineno = lineno2
|
lineno = lineno2
|
||||||
self.emit('DUP_TOP')
|
self.emit('DUP_TOP')
|
||||||
|
@ -687,7 +698,7 @@ class FunctionCodeGenerator(CodeGenerator):
|
||||||
self.graph.setFlag(CO_VARARGS)
|
self.graph.setFlag(CO_VARARGS)
|
||||||
if func.kwargs:
|
if func.kwargs:
|
||||||
self.graph.setFlag(CO_VARKEYWORDS)
|
self.graph.setFlag(CO_VARKEYWORDS)
|
||||||
self.emit('SET_LINENO', func.lineno)
|
self.set_lineno(func)
|
||||||
if hasTupleArg:
|
if hasTupleArg:
|
||||||
self.generateArgUnpack(func.argnames)
|
self.generateArgUnpack(func.argnames)
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,22 @@ class CodeGenerator:
|
||||||
else:
|
else:
|
||||||
self.emit(prefix + '_GLOBAL', name)
|
self.emit(prefix + '_GLOBAL', name)
|
||||||
|
|
||||||
|
def set_lineno(self, node):
|
||||||
|
"""Emit SET_LINENO if node has lineno attribute
|
||||||
|
|
||||||
|
Returns true if SET_LINENO was emitted.
|
||||||
|
|
||||||
|
There are no rules for when an AST node should have a lineno
|
||||||
|
attribute. The transformer and AST code need to be reviewed
|
||||||
|
and a consistent policy implemented and documented. Until
|
||||||
|
then, this method works around missing line numbers.
|
||||||
|
"""
|
||||||
|
lineno = getattr(node, 'lineno', None)
|
||||||
|
if lineno is not None:
|
||||||
|
self.emit('SET_LINENO', lineno)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
# The first few visitor methods handle nodes that generator new
|
# The first few visitor methods handle nodes that generator new
|
||||||
# code objects
|
# code objects
|
||||||
|
|
||||||
|
@ -128,7 +144,7 @@ class CodeGenerator:
|
||||||
gen = FunctionCodeGenerator(node, self.filename, isLambda)
|
gen = FunctionCodeGenerator(node, self.filename, isLambda)
|
||||||
walk(node.code, gen)
|
walk(node.code, gen)
|
||||||
gen.finish()
|
gen.finish()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for default in node.defaults:
|
for default in node.defaults:
|
||||||
self.visit(default)
|
self.visit(default)
|
||||||
self.emit('LOAD_CONST', gen.getCode())
|
self.emit('LOAD_CONST', gen.getCode())
|
||||||
|
@ -138,7 +154,7 @@ class CodeGenerator:
|
||||||
gen = ClassCodeGenerator(node, self.filename)
|
gen = ClassCodeGenerator(node, self.filename)
|
||||||
walk(node.code, gen)
|
walk(node.code, gen)
|
||||||
gen.finish()
|
gen.finish()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('LOAD_CONST', node.name)
|
self.emit('LOAD_CONST', node.name)
|
||||||
for base in node.bases:
|
for base in node.bases:
|
||||||
self.visit(base)
|
self.visit(base)
|
||||||
|
@ -158,8 +174,7 @@ class CodeGenerator:
|
||||||
numtests = len(node.tests)
|
numtests = len(node.tests)
|
||||||
for i in range(numtests):
|
for i in range(numtests):
|
||||||
test, suite = node.tests[i]
|
test, suite = node.tests[i]
|
||||||
if hasattr(test, 'lineno'):
|
self.set_lineno(test)
|
||||||
self.emit('SET_LINENO', test.lineno)
|
|
||||||
self.visit(test)
|
self.visit(test)
|
||||||
## if i == numtests - 1 and not node.else_:
|
## if i == numtests - 1 and not node.else_:
|
||||||
## nextTest = end
|
## nextTest = end
|
||||||
|
@ -178,7 +193,7 @@ class CodeGenerator:
|
||||||
self.nextBlock(end)
|
self.nextBlock(end)
|
||||||
|
|
||||||
def visitWhile(self, node):
|
def visitWhile(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
|
|
||||||
loop = self.newBlock()
|
loop = self.newBlock()
|
||||||
else_ = self.newBlock()
|
else_ = self.newBlock()
|
||||||
|
@ -189,7 +204,7 @@ class CodeGenerator:
|
||||||
self.nextBlock(loop)
|
self.nextBlock(loop)
|
||||||
self.loops.push(loop)
|
self.loops.push(loop)
|
||||||
|
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.test)
|
self.visit(node.test)
|
||||||
self.emit('JUMP_IF_FALSE', else_ or after)
|
self.emit('JUMP_IF_FALSE', else_ or after)
|
||||||
|
|
||||||
|
@ -212,12 +227,12 @@ class CodeGenerator:
|
||||||
after = self.newBlock()
|
after = self.newBlock()
|
||||||
self.loops.push(start)
|
self.loops.push(start)
|
||||||
|
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_LOOP', after)
|
self.emit('SETUP_LOOP', after)
|
||||||
self.visit(node.list)
|
self.visit(node.list)
|
||||||
self.visit(ast.Const(0))
|
self.visit(ast.Const(0))
|
||||||
self.nextBlock(start)
|
self.nextBlock(start)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('FOR_LOOP', anchor)
|
self.emit('FOR_LOOP', anchor)
|
||||||
self.visit(node.assign)
|
self.visit(node.assign)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
|
@ -233,7 +248,7 @@ class CodeGenerator:
|
||||||
if not self.loops:
|
if not self.loops:
|
||||||
raise SyntaxError, "'break' outside loop (%s, %d)" % \
|
raise SyntaxError, "'break' outside loop (%s, %d)" % \
|
||||||
(self.filename, node.lineno)
|
(self.filename, node.lineno)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('BREAK_LOOP')
|
self.emit('BREAK_LOOP')
|
||||||
|
|
||||||
def visitContinue(self, node):
|
def visitContinue(self, node):
|
||||||
|
@ -241,7 +256,7 @@ class CodeGenerator:
|
||||||
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
|
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
|
||||||
(self.filename, node.lineno)
|
(self.filename, node.lineno)
|
||||||
l = self.loops.top()
|
l = self.loops.top()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('JUMP_ABSOLUTE', l)
|
self.emit('JUMP_ABSOLUTE', l)
|
||||||
self.nextBlock()
|
self.nextBlock()
|
||||||
|
|
||||||
|
@ -291,7 +306,7 @@ class CodeGenerator:
|
||||||
# XXX would be interesting to implement this via a
|
# XXX would be interesting to implement this via a
|
||||||
# transformation of the AST before this stage
|
# transformation of the AST before this stage
|
||||||
end = self.newBlock()
|
end = self.newBlock()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
# XXX __debug__ and AssertionError appear to be special cases
|
# XXX __debug__ and AssertionError appear to be special cases
|
||||||
# -- they are always loaded as globals even if there are local
|
# -- they are always loaded as globals even if there are local
|
||||||
# names. I guess this is a sort of renaming op.
|
# names. I guess this is a sort of renaming op.
|
||||||
|
@ -309,7 +324,7 @@ class CodeGenerator:
|
||||||
self.emit('POP_TOP')
|
self.emit('POP_TOP')
|
||||||
|
|
||||||
def visitRaise(self, node):
|
def visitRaise(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
n = 0
|
n = 0
|
||||||
if node.expr1:
|
if node.expr1:
|
||||||
self.visit(node.expr1)
|
self.visit(node.expr1)
|
||||||
|
@ -329,7 +344,7 @@ class CodeGenerator:
|
||||||
lElse = self.newBlock()
|
lElse = self.newBlock()
|
||||||
else:
|
else:
|
||||||
lElse = end
|
lElse = end
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_EXCEPT', handlers)
|
self.emit('SETUP_EXCEPT', handlers)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
self.emit('POP_BLOCK')
|
self.emit('POP_BLOCK')
|
||||||
|
@ -339,8 +354,7 @@ class CodeGenerator:
|
||||||
last = len(node.handlers) - 1
|
last = len(node.handlers) - 1
|
||||||
for i in range(len(node.handlers)):
|
for i in range(len(node.handlers)):
|
||||||
expr, target, body = node.handlers[i]
|
expr, target, body = node.handlers[i]
|
||||||
if hasattr(expr, 'lineno'):
|
self.set_lineno(expr)
|
||||||
self.emit('SET_LINENO', expr.lineno)
|
|
||||||
if expr:
|
if expr:
|
||||||
self.emit('DUP_TOP')
|
self.emit('DUP_TOP')
|
||||||
self.visit(expr)
|
self.visit(expr)
|
||||||
|
@ -368,7 +382,7 @@ class CodeGenerator:
|
||||||
|
|
||||||
def visitTryFinally(self, node):
|
def visitTryFinally(self, node):
|
||||||
final = self.newBlock()
|
final = self.newBlock()
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('SETUP_FINALLY', final)
|
self.emit('SETUP_FINALLY', final)
|
||||||
self.visit(node.body)
|
self.visit(node.body)
|
||||||
self.emit('POP_BLOCK')
|
self.emit('POP_BLOCK')
|
||||||
|
@ -402,16 +416,16 @@ class CodeGenerator:
|
||||||
self.loadName(node.name)
|
self.loadName(node.name)
|
||||||
|
|
||||||
def visitPass(self, node):
|
def visitPass(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
|
|
||||||
def visitImport(self, node):
|
def visitImport(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for name in node.names:
|
for name in node.names:
|
||||||
self.emit('IMPORT_NAME', name)
|
self.emit('IMPORT_NAME', name)
|
||||||
self.storeName(name)
|
self.storeName(name)
|
||||||
|
|
||||||
def visitFrom(self, node):
|
def visitFrom(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.emit('IMPORT_NAME', node.modname)
|
self.emit('IMPORT_NAME', node.modname)
|
||||||
for name in node.names:
|
for name in node.names:
|
||||||
if name == '*':
|
if name == '*':
|
||||||
|
@ -426,7 +440,7 @@ class CodeGenerator:
|
||||||
# next five implement assignments
|
# next five implement assignments
|
||||||
|
|
||||||
def visitAssign(self, node):
|
def visitAssign(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.expr)
|
self.visit(node.expr)
|
||||||
dups = len(node.nodes) - 1
|
dups = len(node.nodes) - 1
|
||||||
for i in range(len(node.nodes)):
|
for i in range(len(node.nodes)):
|
||||||
|
@ -477,8 +491,7 @@ class CodeGenerator:
|
||||||
def visitCallFunc(self, node):
|
def visitCallFunc(self, node):
|
||||||
pos = 0
|
pos = 0
|
||||||
kw = 0
|
kw = 0
|
||||||
if hasattr(node, 'lineno'):
|
self.set_lineno(node)
|
||||||
self.emit('SET_LINENO', node.lineno)
|
|
||||||
self.visit(node.node)
|
self.visit(node.node)
|
||||||
for arg in node.args:
|
for arg in node.args:
|
||||||
self.visit(arg)
|
self.visit(arg)
|
||||||
|
@ -496,7 +509,7 @@ class CodeGenerator:
|
||||||
self.emit(opcode, kw << 8 | pos)
|
self.emit(opcode, kw << 8 | pos)
|
||||||
|
|
||||||
def visitPrint(self, node):
|
def visitPrint(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
for child in node.nodes:
|
for child in node.nodes:
|
||||||
self.visit(child)
|
self.visit(child)
|
||||||
self.emit('PRINT_ITEM')
|
self.emit('PRINT_ITEM')
|
||||||
|
@ -506,7 +519,7 @@ class CodeGenerator:
|
||||||
self.emit('PRINT_NEWLINE')
|
self.emit('PRINT_NEWLINE')
|
||||||
|
|
||||||
def visitReturn(self, node):
|
def visitReturn(self, node):
|
||||||
self.emit('SET_LINENO', node.lineno)
|
self.set_lineno(node)
|
||||||
self.visit(node.value)
|
self.visit(node.value)
|
||||||
self.emit('RETURN_VALUE')
|
self.emit('RETURN_VALUE')
|
||||||
|
|
||||||
|
@ -637,15 +650,13 @@ class CodeGenerator:
|
||||||
self.emit('BUILD_SLICE', len(node.nodes))
|
self.emit('BUILD_SLICE', len(node.nodes))
|
||||||
|
|
||||||
def visitDict(self, node):
|
def visitDict(self, node):
|
||||||
# XXX is this a good general strategy? could it be done
|
lineno = getattr(node, 'lineno', None)
|
||||||
# separately from the general visitor
|
if lineno:
|
||||||
lineno = getattr(node, 'lineno', None)
|
set.emit('SET_LINENO', lineno)
|
||||||
if lineno:
|
|
||||||
self.emit('SET_LINENO', lineno)
|
|
||||||
self.emit('BUILD_MAP', 0)
|
self.emit('BUILD_MAP', 0)
|
||||||
for k, v in node.items:
|
for k, v in node.items:
|
||||||
lineno2 = getattr(node, 'lineno', None)
|
lineno2 = getattr(node, 'lineno', None)
|
||||||
if lineno != lineno2:
|
if lineno2 is not None and lineno != lineno2:
|
||||||
self.emit('SET_LINENO', lineno2)
|
self.emit('SET_LINENO', lineno2)
|
||||||
lineno = lineno2
|
lineno = lineno2
|
||||||
self.emit('DUP_TOP')
|
self.emit('DUP_TOP')
|
||||||
|
@ -687,7 +698,7 @@ class FunctionCodeGenerator(CodeGenerator):
|
||||||
self.graph.setFlag(CO_VARARGS)
|
self.graph.setFlag(CO_VARARGS)
|
||||||
if func.kwargs:
|
if func.kwargs:
|
||||||
self.graph.setFlag(CO_VARKEYWORDS)
|
self.graph.setFlag(CO_VARKEYWORDS)
|
||||||
self.emit('SET_LINENO', func.lineno)
|
self.set_lineno(func)
|
||||||
if hasTupleArg:
|
if hasTupleArg:
|
||||||
self.generateArgUnpack(func.argnames)
|
self.generateArgUnpack(func.argnames)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue