From 8a4d921d6bb018fed0db3c5f67fa828fd5eb473e Mon Sep 17 00:00:00 2001 From: demotomohiro Date: Wed, 29 Oct 2025 10:42:19 +0900 Subject: [PATCH] saves/loads PNode and PSym line info --- compiler/icnif/nifdecoder.nim | 18 +++++++--- compiler/icnif/nifencoder.nim | 58 ++++++++++++++++++------------- tests/icnif/tencode_node2node.nim | 27 ++++++++++++++ 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/compiler/icnif/nifdecoder.nim b/compiler/icnif/nifdecoder.nim index 8ec3d19a0d..aca9ac47dd 100644 --- a/compiler/icnif/nifdecoder.nim +++ b/compiler/icnif/nifdecoder.nim @@ -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: diff --git a/compiler/icnif/nifencoder.nim b/compiler/icnif/nifencoder.nim index bd35c988e2..6a91064ac8 100644 --- a/compiler/icnif/nifencoder.nim +++ b/compiler/icnif/nifencoder.nim @@ -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: diff --git a/tests/icnif/tencode_node2node.nim b/tests/icnif/tencode_node2node.nim index 2fb35785ef..b688542717 100644 --- a/tests/icnif/tencode_node2node.nim +++ b/tests/icnif/tencode_node2node.nim @@ -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):