Skip to content

Commit 2af70ae

Browse files
committed
pyassem: Capture line number of first (module) instruction.
And use this line number as first line number of module's code object. This is quite magic, but achieves (about) the same behavior as CPython has.
1 parent d4704ff commit 2af70ae

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

compiler/pyassem.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def __init__(self):
4848
# line numbers in the code block. (If it's not set, it will be
4949
# deduced).
5050
self.firstline = 0
51+
# Line number of first instruction output. Used to deduce .firstline
52+
# if it's not set explicitly.
53+
self.first_inst_lineno = 0
5154

5255
# Was replaced with ordered_blocks
5356
#self.blocks = misc.Set()
@@ -117,6 +120,8 @@ def emit(self, *inst):
117120
if len(inst) == 2 and isinstance(inst[1], Block):
118121
self.current.addOutEdge(inst[1])
119122
self.current.emit(inst)
123+
if inst[0] == "SET_LINENO" and not self.first_inst_lineno:
124+
self.first_inst_lineno = inst[1]
120125

121126
def getBlocksInOrder(self):
122127
"""Return the blocks in reverse postorder
@@ -545,7 +550,7 @@ def _convert_COMPARE_OP(self, arg):
545550
def makeByteCode(self):
546551
assert self.stage == CONV
547552
self.lnotab = lnotab = LineAddrTable()
548-
lnotab.setFirstLine(self.firstline or 1)
553+
lnotab.setFirstLine(self.firstline or self.first_inst_lineno or 1)
549554
for t in self.insts:
550555
opname = t[0]
551556
if len(t) == 1:
@@ -577,6 +582,11 @@ def newCodeObject(self):
577582
nlocals = len(self.varnames)
578583

579584
firstline = self.firstline
585+
# For module, .firstline is initially not set, and should be first
586+
# line with actual bytecode instruction (skipping docstring, optimized
587+
# out instructions, etc.)
588+
if not firstline:
589+
firstline = self.first_inst_lineno
580590
# If no real instruction, fallback to 1
581591
if not firstline:
582592
firstline = 1

compiler/pycodegen.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,12 @@ def visitModule(self, node):
382382
lnf = walk(node.body, self.NameFinder(), verbose=0)
383383
self.locals.push(lnf.getLocals())
384384
self.visit(self.skip_docstring(node.body))
385+
386+
# See if the was a live statement, to later set its line number as
387+
# module first line. If not, fall back to first line of 1.
388+
if not self.graph.first_inst_lineno:
389+
self.graph.first_inst_lineno = 1
390+
385391
self.emit('LOAD_CONST', None)
386392
self.emit('RETURN_VALUE')
387393

0 commit comments

Comments
 (0)