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

Skip to content

Commit 92f3972

Browse files
committed
patch by Neil Schemenauer to improve (fix?) line number generation
1 parent 3620857 commit 92f3972

4 files changed

Lines changed: 64 additions & 34 deletions

File tree

Lib/compiler/pyassem.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -419,21 +419,32 @@ def nextLine(self, lineno):
419419
# compute deltas
420420
addr = self.codeOffset - self.lastoff
421421
line = lineno - self.lastline
422-
while addr > 0 or line > 0:
423-
# write the values in 1-byte chunks that sum
424-
# to desired value
425-
trunc_addr = addr
426-
trunc_line = line
427-
if trunc_addr > 255:
428-
trunc_addr = 255
429-
if trunc_line > 255:
430-
trunc_line = 255
431-
self.lnotab.append(trunc_addr)
432-
self.lnotab.append(trunc_line)
433-
addr = addr - trunc_addr
434-
line = line - trunc_line
435-
self.lastline = lineno
436-
self.lastoff = self.codeOffset
422+
# Python assumes that lineno always increases with
423+
# increasing bytecode address (lnotab is unsigned char).
424+
# Depending on when SET_LINENO instructions are emitted
425+
# this is not always true. Consider the code:
426+
# a = (1,
427+
# b)
428+
# In the bytecode stream, the assignment to "a" occurs
429+
# after the loading of "b". This works with the C Python
430+
# compiler because it only generates a SET_LINENO instruction
431+
# for the assignment.
432+
if line > 0:
433+
while addr > 0 or line > 0:
434+
# write the values in 1-byte chunks that sum
435+
# to desired value
436+
trunc_addr = addr
437+
trunc_line = line
438+
if trunc_addr > 255:
439+
trunc_addr = 255
440+
if trunc_line > 255:
441+
trunc_line = 255
442+
self.lnotab.append(trunc_addr)
443+
self.lnotab.append(trunc_line)
444+
addr = addr - trunc_addr
445+
line = line - trunc_line
446+
self.lastline = lineno
447+
self.lastoff = self.codeOffset
437448

438449
def getCode(self):
439450
return string.join(self.code, '')

Lib/compiler/pycodegen.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(self, filename):
7070
self.loops = misc.Stack()
7171
self.curStack = 0
7272
self.maxStack = 0
73+
self.last_lineno = None
7374
self._setupGraphDelegation()
7475

7576
def _setupGraphDelegation(self):
@@ -107,7 +108,8 @@ def _nameOp(self, prefix, name):
107108
self.emit(prefix + '_GLOBAL', name)
108109

109110
def set_lineno(self, node):
110-
"""Emit SET_LINENO if node has lineno attribute
111+
"""Emit SET_LINENO if node has lineno attribute and it is
112+
different than the last lineno emitted.
111113
112114
Returns true if SET_LINENO was emitted.
113115
@@ -117,8 +119,9 @@ def set_lineno(self, node):
117119
then, this method works around missing line numbers.
118120
"""
119121
lineno = getattr(node, 'lineno', None)
120-
if lineno is not None:
122+
if lineno is not None and lineno != self.last_lineno:
121123
self.emit('SET_LINENO', lineno)
124+
self.last_lineno = lineno
122125
return 1
123126
return 0
124127

@@ -414,6 +417,7 @@ def visitGlobal(self, node):
414417
pass
415418

416419
def visitName(self, node):
420+
self.set_lineno(node)
417421
self.loadName(node.name)
418422

419423
def visitPass(self, node):

Tools/compiler/compiler/pyassem.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -419,21 +419,32 @@ def nextLine(self, lineno):
419419
# compute deltas
420420
addr = self.codeOffset - self.lastoff
421421
line = lineno - self.lastline
422-
while addr > 0 or line > 0:
423-
# write the values in 1-byte chunks that sum
424-
# to desired value
425-
trunc_addr = addr
426-
trunc_line = line
427-
if trunc_addr > 255:
428-
trunc_addr = 255
429-
if trunc_line > 255:
430-
trunc_line = 255
431-
self.lnotab.append(trunc_addr)
432-
self.lnotab.append(trunc_line)
433-
addr = addr - trunc_addr
434-
line = line - trunc_line
435-
self.lastline = lineno
436-
self.lastoff = self.codeOffset
422+
# Python assumes that lineno always increases with
423+
# increasing bytecode address (lnotab is unsigned char).
424+
# Depending on when SET_LINENO instructions are emitted
425+
# this is not always true. Consider the code:
426+
# a = (1,
427+
# b)
428+
# In the bytecode stream, the assignment to "a" occurs
429+
# after the loading of "b". This works with the C Python
430+
# compiler because it only generates a SET_LINENO instruction
431+
# for the assignment.
432+
if line > 0:
433+
while addr > 0 or line > 0:
434+
# write the values in 1-byte chunks that sum
435+
# to desired value
436+
trunc_addr = addr
437+
trunc_line = line
438+
if trunc_addr > 255:
439+
trunc_addr = 255
440+
if trunc_line > 255:
441+
trunc_line = 255
442+
self.lnotab.append(trunc_addr)
443+
self.lnotab.append(trunc_line)
444+
addr = addr - trunc_addr
445+
line = line - trunc_line
446+
self.lastline = lineno
447+
self.lastoff = self.codeOffset
437448

438449
def getCode(self):
439450
return string.join(self.code, '')

Tools/compiler/compiler/pycodegen.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(self, filename):
7070
self.loops = misc.Stack()
7171
self.curStack = 0
7272
self.maxStack = 0
73+
self.last_lineno = None
7374
self._setupGraphDelegation()
7475

7576
def _setupGraphDelegation(self):
@@ -107,7 +108,8 @@ def _nameOp(self, prefix, name):
107108
self.emit(prefix + '_GLOBAL', name)
108109

109110
def set_lineno(self, node):
110-
"""Emit SET_LINENO if node has lineno attribute
111+
"""Emit SET_LINENO if node has lineno attribute and it is
112+
different than the last lineno emitted.
111113
112114
Returns true if SET_LINENO was emitted.
113115
@@ -117,8 +119,9 @@ def set_lineno(self, node):
117119
then, this method works around missing line numbers.
118120
"""
119121
lineno = getattr(node, 'lineno', None)
120-
if lineno is not None:
122+
if lineno is not None and lineno != self.last_lineno:
121123
self.emit('SET_LINENO', lineno)
124+
self.last_lineno = lineno
122125
return 1
123126
return 0
124127

@@ -414,6 +417,7 @@ def visitGlobal(self, node):
414417
pass
415418

416419
def visitName(self, node):
420+
self.set_lineno(node)
417421
self.loadName(node.name)
418422

419423
def visitPass(self, node):

0 commit comments

Comments
 (0)