Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7daf04d

Browse files
committed
replace most calls to emit 'SET_LINENO' will call to method set_lineno
based on bug report by Neil Schemenauer
1 parent 8612f1c commit 7daf04d

2 files changed

Lines changed: 84 additions & 62 deletions

File tree

Lib/compiler/pycodegen.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ def _nameOp(self, prefix, name):
105105
else:
106106
self.emit(prefix + '_GLOBAL', name)
107107

108+
def set_lineno(self, node):
109+
"""Emit SET_LINENO if node has lineno attribute
110+
111+
Returns true if SET_LINENO was emitted.
112+
113+
There are no rules for when an AST node should have a lineno
114+
attribute. The transformer and AST code need to be reviewed
115+
and a consistent policy implemented and documented. Until
116+
then, this method works around missing line numbers.
117+
"""
118+
lineno = getattr(node, 'lineno', None)
119+
if lineno is not None:
120+
self.emit('SET_LINENO', lineno)
121+
return 1
122+
return 0
123+
108124
# The first few visitor methods handle nodes that generator new
109125
# code objects
110126

@@ -128,7 +144,7 @@ def _visitFuncOrLambda(self, node, isLambda):
128144
gen = FunctionCodeGenerator(node, self.filename, isLambda)
129145
walk(node.code, gen)
130146
gen.finish()
131-
self.emit('SET_LINENO', node.lineno)
147+
self.set_lineno(node)
132148
for default in node.defaults:
133149
self.visit(default)
134150
self.emit('LOAD_CONST', gen.getCode())
@@ -138,7 +154,7 @@ def visitClass(self, node):
138154
gen = ClassCodeGenerator(node, self.filename)
139155
walk(node.code, gen)
140156
gen.finish()
141-
self.emit('SET_LINENO', node.lineno)
157+
self.set_lineno(node)
142158
self.emit('LOAD_CONST', node.name)
143159
for base in node.bases:
144160
self.visit(base)
@@ -158,8 +174,7 @@ def visitIf(self, node):
158174
numtests = len(node.tests)
159175
for i in range(numtests):
160176
test, suite = node.tests[i]
161-
if hasattr(test, 'lineno'):
162-
self.emit('SET_LINENO', test.lineno)
177+
self.set_lineno(test)
163178
self.visit(test)
164179
## if i == numtests - 1 and not node.else_:
165180
## nextTest = end
@@ -178,7 +193,7 @@ def visitIf(self, node):
178193
self.nextBlock(end)
179194

180195
def visitWhile(self, node):
181-
self.emit('SET_LINENO', node.lineno)
196+
self.set_lineno(node)
182197

183198
loop = self.newBlock()
184199
else_ = self.newBlock()
@@ -189,7 +204,7 @@ def visitWhile(self, node):
189204
self.nextBlock(loop)
190205
self.loops.push(loop)
191206

192-
self.emit('SET_LINENO', node.lineno)
207+
self.set_lineno(node)
193208
self.visit(node.test)
194209
self.emit('JUMP_IF_FALSE', else_ or after)
195210

@@ -212,12 +227,12 @@ def visitFor(self, node):
212227
after = self.newBlock()
213228
self.loops.push(start)
214229

215-
self.emit('SET_LINENO', node.lineno)
230+
self.set_lineno(node)
216231
self.emit('SETUP_LOOP', after)
217232
self.visit(node.list)
218233
self.visit(ast.Const(0))
219234
self.nextBlock(start)
220-
self.emit('SET_LINENO', node.lineno)
235+
self.set_lineno(node)
221236
self.emit('FOR_LOOP', anchor)
222237
self.visit(node.assign)
223238
self.visit(node.body)
@@ -233,15 +248,15 @@ def visitBreak(self, node):
233248
if not self.loops:
234249
raise SyntaxError, "'break' outside loop (%s, %d)" % \
235250
(self.filename, node.lineno)
236-
self.emit('SET_LINENO', node.lineno)
251+
self.set_lineno(node)
237252
self.emit('BREAK_LOOP')
238253

239254
def visitContinue(self, node):
240255
if not self.loops:
241256
raise SyntaxError, "'continue' outside loop (%s, %d)" % \
242257
(self.filename, node.lineno)
243258
l = self.loops.top()
244-
self.emit('SET_LINENO', node.lineno)
259+
self.set_lineno(node)
245260
self.emit('JUMP_ABSOLUTE', l)
246261
self.nextBlock()
247262

@@ -291,7 +306,7 @@ def visitAssert(self, node):
291306
# XXX would be interesting to implement this via a
292307
# transformation of the AST before this stage
293308
end = self.newBlock()
294-
self.emit('SET_LINENO', node.lineno)
309+
self.set_lineno(node)
295310
# XXX __debug__ and AssertionError appear to be special cases
296311
# -- they are always loaded as globals even if there are local
297312
# names. I guess this is a sort of renaming op.
@@ -309,7 +324,7 @@ def visitAssert(self, node):
309324
self.emit('POP_TOP')
310325

311326
def visitRaise(self, node):
312-
self.emit('SET_LINENO', node.lineno)
327+
self.set_lineno(node)
313328
n = 0
314329
if node.expr1:
315330
self.visit(node.expr1)
@@ -329,7 +344,7 @@ def visitTryExcept(self, node):
329344
lElse = self.newBlock()
330345
else:
331346
lElse = end
332-
self.emit('SET_LINENO', node.lineno)
347+
self.set_lineno(node)
333348
self.emit('SETUP_EXCEPT', handlers)
334349
self.visit(node.body)
335350
self.emit('POP_BLOCK')
@@ -339,8 +354,7 @@ def visitTryExcept(self, node):
339354
last = len(node.handlers) - 1
340355
for i in range(len(node.handlers)):
341356
expr, target, body = node.handlers[i]
342-
if hasattr(expr, 'lineno'):
343-
self.emit('SET_LINENO', expr.lineno)
357+
self.set_lineno(expr)
344358
if expr:
345359
self.emit('DUP_TOP')
346360
self.visit(expr)
@@ -368,7 +382,7 @@ def visitTryExcept(self, node):
368382

369383
def visitTryFinally(self, node):
370384
final = self.newBlock()
371-
self.emit('SET_LINENO', node.lineno)
385+
self.set_lineno(node)
372386
self.emit('SETUP_FINALLY', final)
373387
self.visit(node.body)
374388
self.emit('POP_BLOCK')
@@ -402,16 +416,16 @@ def visitName(self, node):
402416
self.loadName(node.name)
403417

404418
def visitPass(self, node):
405-
self.emit('SET_LINENO', node.lineno)
419+
self.set_lineno(node)
406420

407421
def visitImport(self, node):
408-
self.emit('SET_LINENO', node.lineno)
422+
self.set_lineno(node)
409423
for name in node.names:
410424
self.emit('IMPORT_NAME', name)
411425
self.storeName(name)
412426

413427
def visitFrom(self, node):
414-
self.emit('SET_LINENO', node.lineno)
428+
self.set_lineno(node)
415429
self.emit('IMPORT_NAME', node.modname)
416430
for name in node.names:
417431
if name == '*':
@@ -426,7 +440,7 @@ def visitGetattr(self, node):
426440
# next five implement assignments
427441

428442
def visitAssign(self, node):
429-
self.emit('SET_LINENO', node.lineno)
443+
self.set_lineno(node)
430444
self.visit(node.expr)
431445
dups = len(node.nodes) - 1
432446
for i in range(len(node.nodes)):
@@ -477,8 +491,7 @@ def visitExec(self, node):
477491
def visitCallFunc(self, node):
478492
pos = 0
479493
kw = 0
480-
if hasattr(node, 'lineno'):
481-
self.emit('SET_LINENO', node.lineno)
494+
self.set_lineno(node)
482495
self.visit(node.node)
483496
for arg in node.args:
484497
self.visit(arg)
@@ -496,7 +509,7 @@ def visitCallFunc(self, node):
496509
self.emit(opcode, kw << 8 | pos)
497510

498511
def visitPrint(self, node):
499-
self.emit('SET_LINENO', node.lineno)
512+
self.set_lineno(node)
500513
for child in node.nodes:
501514
self.visit(child)
502515
self.emit('PRINT_ITEM')
@@ -506,7 +519,7 @@ def visitPrintnl(self, node):
506519
self.emit('PRINT_NEWLINE')
507520

508521
def visitReturn(self, node):
509-
self.emit('SET_LINENO', node.lineno)
522+
self.set_lineno(node)
510523
self.visit(node.value)
511524
self.emit('RETURN_VALUE')
512525

@@ -637,15 +650,13 @@ def visitSliceobj(self, node):
637650
self.emit('BUILD_SLICE', len(node.nodes))
638651

639652
def visitDict(self, node):
640-
# XXX is this a good general strategy? could it be done
641-
# separately from the general visitor
642-
lineno = getattr(node, 'lineno', None)
643-
if lineno:
644-
self.emit('SET_LINENO', lineno)
653+
lineno = getattr(node, 'lineno', None)
654+
if lineno:
655+
set.emit('SET_LINENO', lineno)
645656
self.emit('BUILD_MAP', 0)
646657
for k, v in node.items:
647658
lineno2 = getattr(node, 'lineno', None)
648-
if lineno != lineno2:
659+
if lineno2 is not None and lineno != lineno2:
649660
self.emit('SET_LINENO', lineno2)
650661
lineno = lineno2
651662
self.emit('DUP_TOP')
@@ -687,7 +698,7 @@ def __init__(self, func, filename, isLambda=0):
687698
self.graph.setFlag(CO_VARARGS)
688699
if func.kwargs:
689700
self.graph.setFlag(CO_VARKEYWORDS)
690-
self.emit('SET_LINENO', func.lineno)
701+
self.set_lineno(func)
691702
if hasTupleArg:
692703
self.generateArgUnpack(func.argnames)
693704

0 commit comments

Comments
 (0)