Commits

Antonio Cuni  committed 9c146d1

(antocuni, arigo around): be more clever to detect which lines to display in
blue: we want to display only those for which we execute their *first opcode*,
not one in the middle (because e.g. when we have a non-taken "if", we might
execute the POP_TOP that belongs to the last line of the "then" branch)

  • Participants
  • Parent commits 11d152e

Comments (0)

Files changed (3)

File disassembler.py

         self.pos = pos
         self.arg = arg
         self.lineno = lineno
+        self.line_starts_here = False
 
     def __repr__(self):
         if self.arg is None:
     def __init__(self, opcodes, source):
         self.opcodes = opcodes
         self.map = {}
+        current_lineno = None
         for opcode in opcodes:
             self.map[opcode.pos] = opcode
+            if opcode.lineno != current_lineno:
+                opcode.line_starts_here = True
+            current_lineno = opcode.lineno
         self.source = source.split("\n")
 
 def _setup():
         return code.map[self.bytecode_no].lineno
     lineno = property(getlineno)
 
+    def getline_starts_here(self):
+        code = self.getcode()
+        return code.map[self.bytecode_no].line_starts_here
+    line_starts_here = property(getline_starts_here)
+
     def __repr__(self):
         return "[%s]" % ", ".join([repr(op) for op in self.operations])
 
                 lineno = chunk.lineno
                 minline = min(minline, lineno)
                 maxline = max(maxline, lineno)
-                self._lineset.add(lineno)
+                if chunk.line_starts_here:
+                    self._lineset.add(lineno)
         if minline == sys.maxint:
             minline = 0
             maxline = 0

File test/test_disassembler.py

 def f(a, b):
     return a + b
 
+def g(a, b):
+    c = a+b
+    return c
+
 def test_disassembler():
     res = disassembler.dis(f)
     if sys.version_info[:2] != (2, 6):
     for i in range(4):
         assert res.opcodes[i].lineno == f.func_code.co_firstlineno + 1
     
+
+def test_line_starting_opcodes():
+    if sys.version_info[:2] != (2, 6):
+        py.test.skip("2.6 only test")
+    res = disassembler.dis(g)
+    assert len(res.opcodes) == 6
+    for i, opcode in enumerate(res.opcodes):
+        if i in (0, 4):
+            assert opcode.__class__.__name__ == 'LOAD_FAST'
+            assert opcode.line_starts_here
+        else:
+            assert not opcode.line_starts_here