From 908c4e41f4ac12aef130e59e88595164e03cde9a Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 9 Nov 2025 19:21:09 +0100 Subject: [PATCH] progress --- compiler/ast2nif.nim | 9 +- tests/icnif/tencode_node2node.nim | 398 ------------------------------ 2 files changed, 4 insertions(+), 403 deletions(-) delete mode 100644 tests/icnif/tencode_node2node.nim diff --git a/compiler/ast2nif.nim b/compiler/ast2nif.nim index 9bbc80ec34..a57bbd65af 100644 --- a/compiler/ast2nif.nim +++ b/compiler/ast2nif.nim @@ -555,7 +555,7 @@ proc cursorFromIndexEntry(c: var DecodeContext; module: int32; entry: NifIndexEn proc moduleId(c: var DecodeContext; suffix: string): int32 = # We don't know the "real" FileIndex due to our mapping to a short "Module suffix" - # This is not a problem, we use negative `ItemId.module` values here and then + # This is not a problem, we use negative `ItemId.module` values here and then # there is no interference with in-memory-modules. Modulegraphs.nim already uses -1 # so we start at -2 here. result = c.moduleIds.getOrDefault(suffix) @@ -573,7 +573,7 @@ proc getOffset(c: var DecodeContext; module: int32; nifName: string): NifIndexEn let ii = addr c.mods[index].index result = ii.public.getOrDefault(nifName) if result.offset == 0: - result = ii.private.getOrDefault(nifName) + result = ii.private.getOrDefault(nifName) if result.offset == 0: raiseAssert "symbol has no offset: " & nifName @@ -702,7 +702,7 @@ proc loadType*(c: var DecodeContext; t: PType) = t.typeInst = loadTypeStub(c, n) t.n = loadNode(c, n) - t.setOwner loadSymStub(c, n) + t.setOwner loadSymStub(c, n) t.sym = loadSymStub(c, n) loadLoc c, n, t.loc @@ -810,8 +810,7 @@ proc loadNode(c: var DecodeContext; n: var Cursor): PNode = skipParRi n of nkSym: c.withNode n, result, kind: - #result.sym = c.fromNifSymbol n - discard + result.sym = c.loadSymStub n of nkCharLit: c.withNode n, result, kind: expect n, CharLit diff --git a/tests/icnif/tencode_node2node.nim b/tests/icnif/tencode_node2node.nim deleted file mode 100644 index b1793ec6c2..0000000000 --- a/tests/icnif/tencode_node2node.nim +++ /dev/null @@ -1,398 +0,0 @@ -import std/[assertions, math, tables] -import "../../compiler/icnif" / [nifencoder, nifdecoder] -import "../../compiler" / [idents, ast, astalgo, options, pathutils, modulegraphs, modules, msgs, pipelines, syntaxes, sem, llstream, lineinfos] - -# This test generates PNode by semchecks test code. -# Then it is used to test icnif/nifencoder and nifdecoder. - -const TestCodeDir = currentSourcePath().AbsoluteFile.splitFile().dir / RelativeDir"testcode" - -proc newConfigRefForTest(): ConfigRef = - var conf = newConfigRef() - conf.setDefaultLibpath() - conf.searchPaths.add(conf.libpath) - excl(conf.notes, hintProcessing) - excl(conf.mainPackageNotes, hintProcessing) - result = conf - -proc newModuleGraphForSem(cache: IdentCache; conf: ConfigRef): ModuleGraph = - var graph = newModuleGraph(cache, conf) - graph.setPipeLinePass(SemPass) - # Make PNode from sem pass assigned to graph.systemModule.ast - let oldCmd = graph.config.cmd - graph.config.cmd = cmdIdeTools - graph.compilePipelineSystemModule() - graph.config.cmd = oldCmd - result = graph - -proc getSystemNif(graph: ModuleGraph): seq[string] = - result = newSeqOfCap[string](graph.ifaces.len) - for i, iface in graph.ifaces.mpairs: - if iface.module != nil: - let n = iface.module.ast - assert n != nil - # if nil is not assigned, it generates large NIF - iface.module.ast = nil - result.add saveNifToBuffer(n, graph.config, iface.module) - #writeFile(iface.module.name.s & ".nif", result[^1]) - -proc sem(graph: ModuleGraph; path: AbsoluteFile): (PNode, PSym) = - result = (nil, nil) - - let fileIdx = fileInfoIdx(graph.config, path) - var module = newModule(graph, fileIdx) - registerModule(graph, module) - - var idgen = idGeneratorFromModule(module) - let ctx = preparePContext(graph, module, idgen) - - var stream = llStreamOpen(path, fmRead) - if stream == nil: - rawMessage(graph.config, errCannotOpenFile, path.string) - return (nil, nil) - - var p: Parser = default(Parser) - syntaxes.openParser(p, fileIdx, stream, graph.cache, graph.config) - - checkFirstLineIndentation(p) - block processCode: - if graph.stopCompile(): break processCode - var n = parseTopLevelStmt(p) - if n.kind == nkEmpty: break processCode - # read everything, no streaming possible - var sl = newNodeI(nkStmtList, n.info) - sl.add n - while true: - var n = parseTopLevelStmt(p) - if n.kind == nkEmpty: break - sl.add n - - result = (semWithPContext(ctx, sl), module) - -type - # Nim's AST has cycles that causes infinite recursive loop in eql procs. - # this is used to prevent that happen. - EqlContext = object - nodeStack: seq[PNode] - checkedSyms: Table[ItemId, PSym] # used to check if each PSym has unique ItemId - # and also prevents inifinite loop - checkedTypes: Table[ItemId, PType]# used like checkedSyms - confX, confY: ConfigRef # used to print the line info when there is a mismatch - # and get path from FileIndex - -# Compare PType, PSym and PNode but ignores fields nifencoder and nifdecoder doesn't support -# `x` is generated by sem.nim and `y` is decoded by icnif/nifdecoder. -proc eql(x, y: PNode; c: var EqlContext): bool -proc eql(x, y: PType; c: var EqlContext): bool - -proc eql(x, y: TLoc): bool = - if x.k != y.k: - echo "loc kind mismatch: ", x.k, "/", y.k - result = false - elif x.snippet != y.snippet: - echo "loc snippet mismatch: ", x.snippet, "/", y.snippet - result = false - else: - result = true - -proc eqlFileIndex(x, y: int; c: EqlContext): bool = - let xpath = c.confX.toFullPath(x.FileIndex) - let ypath = c.confY.toFullPath(y.FileIndex) - if xpath != ypath: - echo "file index mismatch: ", xpath, "/", ypath - result = false - 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) - elif x.position != y.position: - echo "symbol position mismatch: ", x.position, "/", y.position - result = false - else: - result = true - -proc eqlItemId(x, y: ItemId; c: EqlContext): bool = - if x.item != y.item: - echo "itemId.item mismatch: ", x.item, "/", y.item - result = false - elif not eqlFileIndex(x.module, y.module, c): - result = false - else: - result = true - -proc eql(x, y: PSym; c: var EqlContext): bool = - if x == nil and y == nil: - result = true - elif x == nil or y == nil: - echo "symbol is missing" - result = false - elif not eqlItemId(x.itemId, y.itemId, c): - echo "symbol itemId mismatch" - result = false - elif c.checkedSyms.hasKeyOrPut(y.itemId, y): - if c.checkedSyms[y.itemId] == y: - result = true - else: - echo "detected duplicated symbol ItemId:" - debug(x) - debug(c.checkedSyms[y.itemId]) - debug(y) - result = false - elif x.name.s != y.name.s: - echo "symbol name mismatch: ", x.name.s, "/", y.name.s - result = false - elif x.kind != y.kind: - echo "symbol kind mismatch: ", x.kind, "/", y.kind - result = false - elif x.magic != y.magic: - echo "symbol magic mismatch: ", x.magic, "/", y.magic - result = false - elif x.kind != skPackage and not eql(x.info, y.info, c): - # fileIndex of info of skPackage is just a path of first semchecked module in the package - echo "symbol line info mismatch" - result = false - elif x.kind != skModule and x.flags != y.flags: - # TODO: check the flag of skModule - echo "symbol flag mismatch: ", x.flags, "/", y.flags - result = false - elif x.options != y.options: - echo "symbol options mismatch: ", x.options, "/", y.options - result = false - elif not eqlSymPos(x, y, c): - result = false - elif x.offset != y.offset: - echo "symbol offset mismatch: ", x.offset, "/", y.offset - result = false - elif x.disamb != y.disamb: - echo "symbol disamb mismatch: ", x.disamb, "/", y.disamb - result = false - elif not eql(x.loc, y.loc): - echo "symbol.loc mismatch" - result = false - else: - if not eql(x.typ, y.typ, c): - echo "symbol type mismatch:" - result = false - elif not eql(x.owner, y.owner, c): - echo "Symbol owner mismatch:" - debug(x.owner) - debug(y.owner) - result = false - elif not eql(x.ast, y.ast, c): - echo "symbol ast mismatch" - result = false - elif not eql(x.constraint, y.constraint, c): - echo "symbol constraint mismatch" - result = false - elif not eql(x.instantiatedFrom, y.instantiatedFrom, c): - echo "symbol instantiatedFrom mismatch" - result = false - else: - if x.kind in {skLet, skVar, skField, skForVar}: - if not eql(x.guard, y.guard, c): - echo "symbol guard mismatch" - result = false - elif x.bitsize != y.bitsize: - echo "symbol bitsize mismatch: ", x.bitsize, "/", y.bitsize - result = false - elif x.alignment != y.alignment: - echo "symbol alignment mismatch: ", x.alignment, "/", y.alignment - result = false - else: - result = true - else: - result = true - -proc eql(x, y: PType; c: var EqlContext): bool = - if x == nil and y == nil: - result = true - elif x == nil or y == nil: - echo "type is missing" - result = false - elif not eqlItemId(x.itemId, y.itemId, c): - echo "type itemId mismatch" - result = false - elif c.checkedTypes.hasKeyOrPut(y.itemId, y): - result = true - #[ - if c.checkedTypes[y.itemId] == y: - result = true - else: - echo "detected duplicated type ItemId:" - debug(x) - debug(c.checkedTypes[y.itemId]) - debug(y) - result = false - ]# - elif x.kind != y.kind: - echo "type kind mismatch: ", x.kind, "/", y.kind - result = false - elif x.flags != y.flags: - echo "type flag mismatch: ", x.flags, "/", y.flags - result = false - else: - if not eql(x.n, y.n, c): - echo "type.n mismatch" - debug(x.n) - debug(y.n) - result = false - elif not eql(x.owner, y.owner, c): - echo "type owner mismatch: " - debug(x.owner) - debug(y.owner) - result = false - elif not eql(x.sym, y.sym, c): - echo "type sym mismatch:" - debug(x.sym) - debug(y.sym) - result = false - elif x.kidsLen != y.kidsLen: - echo "type kidsLen mismatch" - result = false - else: - result = true - for i in 0 ..< x.kidsLen: - if not eql(x[i], y[i], c): - echo "type kids mismatch: " - debug(x[i]) - debug(y[i]) - result = false - break - -proc eql(x, y: PNode; c: var EqlContext): bool = - if x == nil and y == nil: - result = true - elif x == nil or y == nil: - result = false - elif x.kind != y.kind: - echo "node kind mismatch: ", x.kind, "/", y.kind - result = false - elif x.flags != y.flags: - echo "node flag mismatch: ", x.flags, "/", y.flags, " at ", `$`(c.confX, x.info) - 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): - if x == c.nodeStack[i]: - # echo "cycle is detected in PNode" - return true - c.nodeStack.add x - if not eql(x.typ, y.typ, c): - echo "PNode type mismatch at ", `$`(c.confX, x.info), ":" - debug(x) - debug(y) - debug(x.typ) - debug(y.typ) - result = false - else: - case x.kind: - of nkIdent: - # these idents are generated from different IdentCache - result = x.ident.s == y.ident.s - if not result: - echo "PNode identifier mismatch: ", `$`(c.confX, x.info), x.ident.s, "/", y.ident.s - of nkSym: - result = eql(x.sym, y.sym, c) - if not result: - echo "Symbol mismatch:" - debug(x.sym) - if y.sym == nil: - echo "y.sym = nil" - else: - debug(y.sym) - debug(x.sym.typ) - debug(y.sym.typ) - of nkCharLit .. nkUInt64Lit, nkStrLit .. nkTripleStrLit: - result = sameValue(x, y) - of nkFloatLit .. nkFloat128Lit: - # want to know if x and y are identical float value. - # so x == y doesn't work if both x and y are NaN or x == 0 and y == -0. - let xc = classify(x.floatVal) - let yc = classify(y.floatVal) - if xc == yc: - if xc in {fcNormal, fcSubnormal}: - if x.floatVal != y.floatVal: - echo "float literal mismatch: ", x.floatVal, "/", y.floatVal - result = false - else: - result = true - else: - result = true - else: - echo "float literal mismatch: ", xc, "/", yc - result = false - else: - result = true - for i in 0 ..< x.safeLen: - if not eql(x[i], y[i], c): - result = false - break - discard c.nodeStack.pop - else: - echo "node length mismatch" - debug(x) - debug(y) - result = false - -proc testNifEncDec(graph: ModuleGraph; src: string; systemNif: openArray[string]) = - let fullPath = TestCodeDir / RelativeFile(src) - let (n, module) = sem(graph, fullPath) - assert n != nil, "failed to sem " & $fullPath - assert module.owner.kind == skPackage - - #debug(n) - let nif = saveNifToBuffer(n, graph.config, module) - #echo nif - #echo "NIF size of ", src, ": ", nif.len - #writeFile(src & ".nif", nif) - - # Don't reuse the ModuleGraph used for semcheck when load NIF. - var graphForLoad = newModuleGraph(newIdentCache(), newConfigRefForTest()) - var prog = NifProgram() - for sysNif in systemNif: - discard loadNifFromBuffer(sysNif, graphForLoad, prog) - let n2 = loadNifFromBuffer(nif, graphForLoad, prog) - #debug(n2) - var c = EqlContext(confX: graph.config, confY: graphForLoad.config) - assert eql(n, n2, c), "test failed: " & $fullPath - -var conf = newConfigRefForTest() -var cache = newIdentCache() -var graph = newModuleGraphForSem(cache, conf) -let systemNif = getSystemNif(graph) -testNifEncDec(graph, "modtest1.nim", systemNif) -testNifEncDec(graph, "modtestliterals.nim", systemNif) -testNifEncDec(graph, "modtesttypesections.nim", systemNif) -#testNifEncDec(graph, "modtestpragmas.nim", systemNif) -testNifEncDec(graph, "modtestprocs.nim", systemNif) -#testNifEncDec(graph, "modteststatements.nim", systemNif) -#testNifEncDec(graph, "modtestgenerics.nim", systemNif) -#testNifEncDec(graph, "modtestexprs.nim", systemNif)