Commit 92f39720 authored by Jeremy Hylton's avatar Jeremy Hylton

patch by Neil Schemenauer to improve (fix?) line number generation

parent 3620857d
...@@ -419,21 +419,32 @@ class LineAddrTable: ...@@ -419,21 +419,32 @@ class LineAddrTable:
# compute deltas # compute deltas
addr = self.codeOffset - self.lastoff addr = self.codeOffset - self.lastoff
line = lineno - self.lastline line = lineno - self.lastline
while addr > 0 or line > 0: # Python assumes that lineno always increases with
# write the values in 1-byte chunks that sum # increasing bytecode address (lnotab is unsigned char).
# to desired value # Depending on when SET_LINENO instructions are emitted
trunc_addr = addr # this is not always true. Consider the code:
trunc_line = line # a = (1,
if trunc_addr > 255: # b)
trunc_addr = 255 # In the bytecode stream, the assignment to "a" occurs
if trunc_line > 255: # after the loading of "b". This works with the C Python
trunc_line = 255 # compiler because it only generates a SET_LINENO instruction
self.lnotab.append(trunc_addr) # for the assignment.
self.lnotab.append(trunc_line) if line > 0:
addr = addr - trunc_addr while addr > 0 or line > 0:
line = line - trunc_line # write the values in 1-byte chunks that sum
self.lastline = lineno # to desired value
self.lastoff = self.codeOffset trunc_addr = addr
trunc_line = line
if trunc_addr > 255:
trunc_addr = 255
if trunc_line > 255:
trunc_line = 255
self.lnotab.append(trunc_addr)
self.lnotab.append(trunc_line)
addr = addr - trunc_addr
line = line - trunc_line
self.lastline = lineno
self.lastoff = self.codeOffset
def getCode(self): def getCode(self):
return string.join(self.code, '') return string.join(self.code, '')
......
...@@ -70,6 +70,7 @@ class CodeGenerator: ...@@ -70,6 +70,7 @@ class CodeGenerator:
self.loops = misc.Stack() self.loops = misc.Stack()
self.curStack = 0 self.curStack = 0
self.maxStack = 0 self.maxStack = 0
self.last_lineno = None
self._setupGraphDelegation() self._setupGraphDelegation()
def _setupGraphDelegation(self): def _setupGraphDelegation(self):
...@@ -107,7 +108,8 @@ class CodeGenerator: ...@@ -107,7 +108,8 @@ class CodeGenerator:
self.emit(prefix + '_GLOBAL', name) self.emit(prefix + '_GLOBAL', name)
def set_lineno(self, node): def set_lineno(self, node):
"""Emit SET_LINENO if node has lineno attribute """Emit SET_LINENO if node has lineno attribute and it is
different than the last lineno emitted.
Returns true if SET_LINENO was emitted. Returns true if SET_LINENO was emitted.
...@@ -117,8 +119,9 @@ class CodeGenerator: ...@@ -117,8 +119,9 @@ class CodeGenerator:
then, this method works around missing line numbers. then, this method works around missing line numbers.
""" """
lineno = getattr(node, 'lineno', None) lineno = getattr(node, 'lineno', None)
if lineno is not None: if lineno is not None and lineno != self.last_lineno:
self.emit('SET_LINENO', lineno) self.emit('SET_LINENO', lineno)
self.last_lineno = lineno
return 1 return 1
return 0 return 0
...@@ -414,6 +417,7 @@ class CodeGenerator: ...@@ -414,6 +417,7 @@ class CodeGenerator:
pass pass
def visitName(self, node): def visitName(self, node):
self.set_lineno(node)
self.loadName(node.name) self.loadName(node.name)
def visitPass(self, node): def visitPass(self, node):
......
...@@ -419,21 +419,32 @@ class LineAddrTable: ...@@ -419,21 +419,32 @@ class LineAddrTable:
# compute deltas # compute deltas
addr = self.codeOffset - self.lastoff addr = self.codeOffset - self.lastoff
line = lineno - self.lastline line = lineno - self.lastline
while addr > 0 or line > 0: # Python assumes that lineno always increases with
# write the values in 1-byte chunks that sum # increasing bytecode address (lnotab is unsigned char).
# to desired value # Depending on when SET_LINENO instructions are emitted
trunc_addr = addr # this is not always true. Consider the code:
trunc_line = line # a = (1,
if trunc_addr > 255: # b)
trunc_addr = 255 # In the bytecode stream, the assignment to "a" occurs
if trunc_line > 255: # after the loading of "b". This works with the C Python
trunc_line = 255 # compiler because it only generates a SET_LINENO instruction
self.lnotab.append(trunc_addr) # for the assignment.
self.lnotab.append(trunc_line) if line > 0:
addr = addr - trunc_addr while addr > 0 or line > 0:
line = line - trunc_line # write the values in 1-byte chunks that sum
self.lastline = lineno # to desired value
self.lastoff = self.codeOffset trunc_addr = addr
trunc_line = line
if trunc_addr > 255:
trunc_addr = 255
if trunc_line > 255:
trunc_line = 255
self.lnotab.append(trunc_addr)
self.lnotab.append(trunc_line)
addr = addr - trunc_addr
line = line - trunc_line
self.lastline = lineno
self.lastoff = self.codeOffset
def getCode(self): def getCode(self):
return string.join(self.code, '') return string.join(self.code, '')
......
...@@ -70,6 +70,7 @@ class CodeGenerator: ...@@ -70,6 +70,7 @@ class CodeGenerator:
self.loops = misc.Stack() self.loops = misc.Stack()
self.curStack = 0 self.curStack = 0
self.maxStack = 0 self.maxStack = 0
self.last_lineno = None
self._setupGraphDelegation() self._setupGraphDelegation()
def _setupGraphDelegation(self): def _setupGraphDelegation(self):
...@@ -107,7 +108,8 @@ class CodeGenerator: ...@@ -107,7 +108,8 @@ class CodeGenerator:
self.emit(prefix + '_GLOBAL', name) self.emit(prefix + '_GLOBAL', name)
def set_lineno(self, node): def set_lineno(self, node):
"""Emit SET_LINENO if node has lineno attribute """Emit SET_LINENO if node has lineno attribute and it is
different than the last lineno emitted.
Returns true if SET_LINENO was emitted. Returns true if SET_LINENO was emitted.
...@@ -117,8 +119,9 @@ class CodeGenerator: ...@@ -117,8 +119,9 @@ class CodeGenerator:
then, this method works around missing line numbers. then, this method works around missing line numbers.
""" """
lineno = getattr(node, 'lineno', None) lineno = getattr(node, 'lineno', None)
if lineno is not None: if lineno is not None and lineno != self.last_lineno:
self.emit('SET_LINENO', lineno) self.emit('SET_LINENO', lineno)
self.last_lineno = lineno
return 1 return 1
return 0 return 0
...@@ -414,6 +417,7 @@ class CodeGenerator: ...@@ -414,6 +417,7 @@ class CodeGenerator:
pass pass
def visitName(self, node): def visitName(self, node):
self.set_lineno(node)
self.loadName(node.name) self.loadName(node.name)
def visitPass(self, node): def visitPass(self, node):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment