# # # The Nim Compiler # (c) Copyright 2025 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## Based on sighashes.nim but works on astdef directly as we need it in ast2nif.nim. ## Also produces more readable names thanks to treemangler. import std/assertions import "../dist/nimony/src/lib" / [treemangler] import "../dist/nimony/src/gear2" / modnames import astdef, idents, options, lineinfos, msgs import ic / [enum2nif] # -------------- Module name handling -------------------------------------------- proc cachedModuleSuffix*(config: ConfigRef; fileIdx: FileIndex): string = ## Gets or computes the module suffix for a FileIndex. ## For NIF modules, the suffix is already stored in the file info. ## For source files, computes it from the path. let fullPath = toFullPath(config, fileIdx) if fileInfoKind(config, fileIdx) == fikNifModule: result = fullPath # Already a suffix else: result = moduleSuffix(fullPath, cast[seq[string]](config.searchPaths)) proc modname*(module: int; conf: ConfigRef): string = cachedModuleSuffix(conf, module.FileIndex) proc modname*(module: PSym; conf: ConfigRef): string = assert module.kindImpl == skModule modname(module.positionImpl, conf) # --------------- Type key generation -------------------------------------------- type ConsiderFlag = enum CoProc CoType CoIgnoreRange CoConsiderOwned CoDistinct CoHashTypeInsideNode TypeLoader* = proc (t: PType) {.nimcall.} SymLoader* = proc (s: PSym) {.nimcall.} Context = object m: Mangler tl: TypeLoader sl: SymLoader proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) proc symKey(c: var Context; s: PSym; conf: ConfigRef) = if s.state == Partial: assert c.sl != nil c.sl(s) if sfAnon in s.flagsImpl or s.kindImpl == skGenericParam: c.m.addIdent("´anon") else: var name = s.name.s name.add '.' name.addInt s.disamb let it = if s.kindImpl == skModule: s elif s.kindImpl in skProcKinds and sfFromGeneric in s.flagsImpl and s.ownerFieldImpl.kindImpl != skModule: s.ownerFieldImpl.ownerFieldImpl else: s.ownerFieldImpl if it.kindImpl == skModule: name.add '.' name.add modname(it, conf) c.m.addSymbol(name) proc treeKey(c: var Context; n: PNode; flags: set[ConsiderFlag]; conf: ConfigRef) = if n == nil: c.m.addEmpty() return let k = n.kind case k of nkEmpty, nkNilLit, nkType: discard of nkIdent: c.m.addIdent(n.ident.s) of nkSym: symKey(c, n.sym, conf) if CoHashTypeInsideNode in flags and n.sym.typImpl != nil: typeKey(c, n.sym.typImpl, flags, conf) of nkCharLit..nkUInt64Lit: let v = n.intVal c.m.addIntLit v of nkFloatLit..nkFloat64Lit: let v = n.floatVal c.m.addFloatLit v of nkStrLit..nkTripleStrLit: c.m.addStrLit n.strVal else: withTree c.m, toNifTag(k): for i in 0.. 0: c.typeKey(t.skipModifierB, flags, conf) of tyProc: withTree c.m, (if tfIterator in t.flagsImpl: "itertype" else: "proctype"): if CoProc in flags and t.nImpl != nil: let params = t.nImpl for i in 1.. 0: c.typeKey(t.sonsImpl[0], flags, conf) c.m.addIdent toNifTag(t.callConvImpl) if tfVarargs in t.flagsImpl: c.m.addIdent "´varargs" of tyArray: withTree c.m, toNifTag(t.kind): c.typeKey(t.sonsImpl[^1], flags-{CoIgnoreRange}, conf) c.typeKey(t.sonsImpl[0], flags-{CoIgnoreRange}, conf) else: withTree c.m, toNifTag(t.kind): for i in 1..