saves/loads PNode and PSym line info

This commit is contained in:
demotomohiro
2025-10-29 10:42:19 +09:00
parent 51eccea910
commit 8a4d921d6b
3 changed files with 75 additions and 28 deletions

View File

@@ -1,5 +1,5 @@
import std / [assertions, tables]
import "../../dist/nimony/src/lib" / [bitabs, nifreader, nifstreams, nifcursors]
import "../../dist/nimony/src/lib" / [bitabs, nifreader, nifstreams, nifcursors, lineinfos]
import ".." / [ast, idents, lineinfos, options, modules, modulegraphs, msgs, pathutils]
import enum2nif, icniftags
@@ -59,6 +59,13 @@ when false:
else:
expectTag(n, id)
proc fromNifLineInfo(c: var DecodeContext; n: Cursor): TLineInfo =
if n.info == NoLineInfo:
unknownLineInfo
else:
let info = pool.man.unpack(n.info)
c.graph.config.newLineInfo(pool.files[info.file].AbsoluteFile, info.line, info.col)
proc fromNifModuleId(c: var DecodeContext; n: var Cursor): (FileIndex, int32) =
expect n, {ParLe, IntLit}
if n.kind == ParLe:
@@ -83,6 +90,7 @@ proc fromNif(c: var DecodeContext; n: var Cursor): PNode
proc fromNifSymDef(c: var DecodeContext; n: var Cursor): PSym =
expectTag n, symIdTag
let info = c.fromNifLineInfo n
inc n
let (itemIdModule, nifModId) = c.fromNifModuleId(n)
expect n, IntLit
@@ -100,6 +108,7 @@ proc fromNifSymDef(c: var DecodeContext; n: var Cursor): PSym =
result = PSym(itemId: ItemId(module: itemIdModule.int32, item: itemId),
kind: kind,
name: ident,
info: info,
flags: flags,
disamb: disamb)
@@ -223,9 +232,10 @@ proc fromNifType(c: var DecodeContext; n: var Cursor): PType =
assert false, "expected type tag but got " & pool.tags[n.tagId]
template withNode(c: var DecodeContext; n: var Cursor; result: PNode; kind: TNodeKind; body: untyped) =
let info = c.fromNifLineInfo(n)
incExpect n, {DotToken, Ident}
let flags = fromNifNodeFlags n
result = newNode(kind)
result = newNodeI(kind, info)
result.flags = flags
result.typ = c.fromNifType n
body
@@ -241,12 +251,12 @@ proc fromNif(c: var DecodeContext; n: var Cursor): PNode =
let kind = n.nodeKind
case kind:
of nkEmpty:
result = newNode(nkEmpty)
result = newNodeI(nkEmpty, c.fromNifLineInfo(n))
inc n
skipParRi n
of nkIdent:
incExpect n, Ident
result = newIdentNode(c.graph.cache.getIdent(pool.strings[n.litId]), unknownLineInfo)
result = newIdentNode(c.graph.cache.getIdent(pool.strings[n.litId]), c.fromNifLineInfo(n))
inc n
skipParRi n
of nkSym:

View File

@@ -31,6 +31,13 @@ proc writeFlags[E](dest: var TokenBuf; flags: set[E]) =
else:
dest.addDotToken
proc toNif(c: var EncodeContext; info: TLineInfo): PackedLineInfo =
if info == unknownLineInfo:
NoLineInfo
else:
let fileId = pool.files.getOrIncl(c.conf.toFullPath(info.fileIndex))
pack(pool.man, fileId, info.line.int32, info.col)
proc toNifModuleId(c: var EncodeContext; moduleId: int) =
# `ItemId.module` in PType and PSym (and `PSym.position` when it is skModule) are module's FileIndex
# but it cannot be directly encoded as the uniqueness of it can broke
@@ -48,28 +55,29 @@ proc toNif(c: var EncodeContext; typ: PType)
proc toNif(c: var EncodeContext; n: PNode)
proc toNifDef(c: var EncodeContext; sym: PSym) =
c.dest.buildTree symIdTag:
c.toNifModuleId sym.itemId.module
c.dest.addIntLit sym.itemId.item
c.dest.addIdent sym.name.s
c.dest.writeFlags sym.flags
c.dest.addIntLit sym.disamb
c.dest.buildTree sym.kind.toNifTag:
case sym.kind
of skLet, skVar, skField, skForVar:
c.toNif sym.guard
c.dest.addIntLit sym.bitsize
c.dest.addIntLit sym.alignment
else:
discard
if sym.kind == skModule:
c.toNifModuleId sym.position
c.dest.addParLe symIdTag, c.toNif sym.info
c.toNifModuleId sym.itemId.module
c.dest.addIntLit sym.itemId.item
c.dest.addIdent sym.name.s
c.dest.writeFlags sym.flags
c.dest.addIntLit sym.disamb
c.dest.buildTree sym.kind.toNifTag:
case sym.kind
of skLet, skVar, skField, skForVar:
c.toNif sym.guard
c.dest.addIntLit sym.bitsize
c.dest.addIntLit sym.alignment
else:
c.dest.addIntLit sym.position
c.toNif sym.typ
c.toNif sym.owner
c.dest.addIdent toNifTag(sym.loc.k)
c.dest.addStrLit sym.loc.snippet
discard
if sym.kind == skModule:
c.toNifModuleId sym.position
else:
c.dest.addIntLit sym.position
c.toNif sym.typ
c.toNif sym.owner
c.dest.addIdent toNifTag(sym.loc.k)
c.dest.addStrLit sym.loc.snippet
c.dest.addParRi
proc toNifDef(c: var EncodeContext; typ: PType) =
c.dest.buildTree typeIdTag:
@@ -115,7 +123,7 @@ proc writeNodeFlags(dest: var TokenBuf; flags: set[TNodeFlag]) {.inline.} =
writeFlags dest, flags
template withNode(c: var EncodeContext; n: PNode; body: untyped) =
c.dest.addParLe pool.tags.getOrIncl(toNifTag(n.kind))
c.dest.addParLe pool.tags.getOrIncl(toNifTag(n.kind)), c.toNif n.info
writeNodeFlags(c.dest, n.flags)
c.toNif n.typ
body
@@ -127,10 +135,12 @@ proc toNif(c: var EncodeContext; n: PNode) =
else:
case n.kind:
of nkEmpty:
c.dest.addParLe pool.tags.getOrIncl(toNifTag(nkEmpty))
let info = c.toNif n.info
c.dest.addParLe pool.tags.getOrIncl(toNifTag(nkEmpty)), info
c.dest.addParRi
of nkIdent:
c.dest.addParLe pool.tags.getOrIncl(toNifTag(nkIdent))
let info = c.toNif n.info
c.dest.addParLe pool.tags.getOrIncl(toNifTag(nkIdent)), info
c.dest.addIdent n.ident.s
c.dest.addParRi
of nkSym:

View File

@@ -90,6 +90,26 @@ proc eqlFileIndex(x, y: int; c: EqlContext): bool =
else:
result = true
proc eql(x, y: TLineInfo; c: EqlContext): bool =
# If parent PNode has a valid line info but it's child doesn't have one,
# cannot translate such a tree to NIF.
# Because in NIF, if a child node doesn't have line info,
# nifstream assign the parent's line info to it.
# So cannot have child node without line info if parent has a valid line info.
if x == unknownLineInfo:
result = true
elif x.line != y.line:
echo "line number mismatch: ", x.line, "/", y.line
result = false
elif x.col != y.col:
echo "column number mismatch: ", x.col, "/", y.col
result = false
elif not eqlFileIndex(x.fileIndex.int, y.fileIndex.int, c):
echo "file in line info mismatch"
result = false
else:
result = true
proc eqlSymPos(x, y: PSym; c: EqlContext): bool =
if x.kind == skModule:
result = eqlFileIndex(x.position, y.position, c)
@@ -123,6 +143,9 @@ proc eql(x, y: PSym; c: var EqlContext): bool =
elif x.kind != y.kind:
echo "symbol kind mismatch: ", x.kind, "/", y.kind
result = false
elif not eql(x.info, y.info, c):
echo "symbol line info mismatch"
result = false
elif x.flags != y.flags:
echo "symbol flag mismatch: ", x.flags, "/", y.flags
result = false
@@ -229,6 +252,10 @@ proc eql(x, y: PNode; c: var EqlContext): bool =
debug(x)
debug(y)
result = false
elif not eql(x.info, y. info, c):
echo "node lineinfo mismatch at ", `$`(c.confX, x.info)
debug(x)
result = false
elif x.safeLen == y.safeLen:
if c.nodeStack.len != 0:
for i in countDown(c.nodeStack.len - 1, 0):