This module implements the module graph data structure. The module graph represents a complete Nim project. Single modules can either be kept in RAM or stored in a rod-file.
Types
Iface = object module*: PSym ## module this "Iface" belongs to converters*: seq[PSym] patterns*: seq[PSym] pureEnums*: seq[PSym] uniqueName*: Rope
- data we don't want to store directly in the ast.PSym type for s.kind == skModule Source Edit
ModuleGraph {.acyclic.} = ref object ifaces*: seq[Iface] ## indexed by int32 fileIdx typeInstCache*: Table[ItemId, seq[PType]] procInstCache*: Table[ItemId, seq[PInstantiation]] attachedOps*: array[TTypeAttachedOp, Table[ItemId, PSym]] opsLog*: seq[LogEntry] methodsPerGenericType*: Table[ItemId, seq[(int, PSym)]] memberProcsPerType*: Table[ItemId, seq[PSym]] initializersPerType*: Table[ItemId, PNode] enumToStringProcs*: Table[ItemId, PSym] emittedTypeInfo*: Table[string, FileIndex] icCnifFiles*: seq[string] pendingMethodReplays*: seq[PSym] icImplDeps*: IntSet icQualIfaces*: IntSet inVMTransform*: int packageSyms*: TStrTable deps*: IntSet importDeps*: Table[FileIndex, seq[FileIndex]] suggestMode*: bool interactive*: bool withinSystem*: bool inclToMod*: Table[FileIndex, FileIndex] importStack*: seq[FileIndex] backend*: RootRef config*: ConfigRef cache*: IdentCache vm*: RootRef repl*: RootRef doStopCompile*: proc (): bool {.closure.} usageSym*: PSym owners*: seq[PSym] suggestSymbols*: SuggestSymbolDatabase suggestErrors*: Table[FileIndex, seq[Suggest]] methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] bucketTable*: CountTable[ItemId] objectTree*: Table[ItemId, seq[tuple[depth: int, value: PType]]] methodsPerType*: Table[ItemId, seq[PSym]] dispatchers*: seq[PSym] systemModule*: PSym sysTypes*: array[TTypeKind, PType] compilerprocs*: TStrTable exposed*: TStrTable packageTypes*: TStrTable emptyNode*: PNode canonTypes*: Table[SigHash, PType] symBodyHashes*: Table[int, SigHash] importModuleCallback*: proc (graph: ModuleGraph; m: PSym; fileIdx: FileIndex): PSym {. nimcall.} includeFileCallback*: proc (graph: ModuleGraph; m: PSym; fileIdx: FileIndex): PNode {. nimcall.} cacheSeqs*: Table[string, PNode] cacheCounters*: Table[string, BiggestInt] cacheTables*: Table[string, BTree[string, PNode]] transitiveReplayActions*: seq[PNode] passes*: seq[TPass] pipelinePass*: PipelinePass onDefinition*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.} onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.} onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.} globalDestructors*: seq[PNode] strongSemCheck*: proc (graph: ModuleGraph; owner: PSym; body: PNode) {.nimcall.} compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {. nimcall.} idgen*: IdGenerator operators*: Operators cachedFiles*: StringTableRef procGlobals*: seq[PNode] nifReplayActions*: Table[int32, seq[PNode]]
- Source Edit
ModuleIter = object
- Source Edit
Operators = object opNot*, opContains*, opLe*, opLt*, opAnd*, opOr*, opIsNil*, opEq*: PSym opAdd*, opSub*, opMul*, opDiv*, opLen*: PSym
- Source Edit
PipelinePass = enum NonePass, SemPass, JSgenPass, CgenPass, NifgenPass, EvalPass, InterpreterPass, GenDependPass, Docgen2TexPass, Docgen2JsonPass, Docgen2Pass
- Source Edit
PPassContext = ref TPassContext
- Source Edit
TPass = tuple[open: TPassOpen, process: TPassProcess, close: TPassClose, isFrontend: bool]
- Source Edit
TPassClose = proc (graph: ModuleGraph; p: PPassContext; n: PNode): PNode {. nimcall.}
- Source Edit
TPassContext = object of RootObj idgen*: IdGenerator
- Source Edit
TPassOpen = proc (graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {. nimcall.}
- Source Edit
TPassProcess = proc (p: PPassContext; topLevelStmt: PNode): PNode {.nimcall.}
- Source Edit
Consts
HookDisambBit = 0x20000000'i32
- Set in the disamb of synthesized type-bound operators and $enum procs whose value is content-derived (see setHookDisamb); disjoint from both the small counter range and the InstanceDisambBit range. Source Edit
InstanceDisambBit = 0x40000000'i32
- Set in the disamb of routine instances whose value is content-derived (see setInstanceDisamb); keeps them disjoint from the small counter range ordinary symbols draw from, so the NIF name name.disamb.module stays collision-free within a module. Source Edit
Procs
proc addDispatchers(g: ModuleGraph; value: PSym) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc addIncludeDep(g: ModuleGraph; module, includeFile: FileIndex) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc addMethodToGeneric(g: ModuleGraph; module: int; t: PType; col: int; m: PSym) {. ...raises: [Exception, KeyError, ValueError, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc addNifReplayAction(g: ModuleGraph; module: int32; n: PNode) {....raises: [], tags: [], forbids: [].}
- Stores a replay action for NIF-based incremental compilation. Source Edit
proc belongsToStdlib(graph: ModuleGraph; sym: PSym): bool {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Check if symbol belongs to the 'stdlib' package. Source Edit
proc completePartialOp(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) {.inline, ...raises: [], tags: [], forbids: [].}
- Source Edit
proc configComplete(g: ModuleGraph) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc copyTypeProps(g: ModuleGraph; module: int; dest, src: PType) {. ...raises: [KeyError, Exception], tags: [RootEffect], forbids: [].}
- Source Edit
proc createMagic(g: ModuleGraph; idgen: IdGenerator; name: string; m: TMagic): PSym {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc fileSymbols(graph: ModuleGraph; fileIdx: FileIndex): SuggestFileSymbolDatabase {. ...raises: [], tags: [], forbids: [].}
- Source Edit
proc flushMethodReplays(g: ModuleGraph) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Builds the dispatch buckets from the method registrations collected during module loading; called once every module of the program is loaded (nifbackend.generateCode). Source Edit
proc getAttachedOp(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym {. ...raises: [KeyError, Exception], tags: [RootEffect], forbids: [].}
- returns the requested attached operation for type t. Can return nil if no such operation exists. Source Edit
proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym {. ...raises: [KeyError], tags: [ReadDirEffect], forbids: [].}
- Returns a package symbol for yet to be defined module for fileIdx. The package symbol is added to the graph if it doesn't exist. Source Edit
proc getToStringProc(g: ModuleGraph; t: PType): PSym {....raises: [Exception], tags: [RootEffect], forbids: [].}
- Source Edit
proc hasDisabledAsgn(g: ModuleGraph; t: PType): bool {. ...raises: [KeyError, Exception, ValueError, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc initModuleIter(mi: var ModuleIter; g: ModuleGraph; m: PSym; name: PIdent): PSym {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc initOperators(g: ModuleGraph): Operators {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc initStrTables(g: ModuleGraph; m: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc isCachedModule(g: ModuleGraph; m: PSym): bool {.inline, ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc isDirty(g: ModuleGraph; m: PSym): bool {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc loadCompilerProc(g: ModuleGraph; name: string): PSym {. ...raises: [OSError, ValueError, KeyError, Exception], tags: [ReadDirEffect, RootEffect, ReadEnvEffect, ReadIOEffect], forbids: [].}
- Source Edit
proc logGenericInstance(g: ModuleGraph; inst: PSym) {....raises: [], tags: [], forbids: [].}
- Log a generic instance so it gets written to the NIF file. This is needed when generic instances are created during compile-time evaluation and may be referenced from other modules compiled in the same run. Source Edit
proc logMethodDef(g: ModuleGraph; s: PSym) {....raises: [], tags: [], forbids: [].}
- Log a method registration (cgmeth.methodDef) so that importers and the backend can rebuild the dispatch buckets (g.methods) from the NIF replay log — the serialized method ast carries its dispatcher sym at dispatcherPos, so replay reuses the original dispatcher that all call sites reference by name (see registerLoadedMethod). Source Edit
proc markClientsDirty(g: ModuleGraph; fileIdx: FileIndex) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc markDirty(g: ModuleGraph; fileIdx: FileIndex) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc moduleFromNifFile(g: ModuleGraph; fileIdx: FileIndex; flags: set[LoadFlag] = {}): PrecompiledModule {. ...raises: [OSError, KeyError, ValueError, Exception], tags: [ReadDirEffect, RootEffect, ReadEnvEffect, ReadIOEffect], forbids: [].}
- Returns 'nil' if the module needs to be recompiled. Loads module from NIF file when optCompress is enabled. When loadFullAst is true, loads the complete module AST for code generation. Source Edit
proc moduleOpenForCodegen(g: ModuleGraph; m: FileIndex): bool {.inline, ...raises: [], tags: [], forbids: [].}
- Source Edit
proc needsCompilation(g: ModuleGraph): bool {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc needsCompilation(g: ModuleGraph; fileIdx: FileIndex): bool {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc needsIncludeScan(g: ModuleGraph; fileIdx: FileIndex): bool {....raises: [], tags: [], forbids: [].}
- True when fileIdx is neither a known module of its own nor an already-known include file — i.e. a cold-opened file whose includer we must still discover via registerIncluderFromNif. Source Edit
proc newModuleGraph(cache: IdentCache; config: ConfigRef): ModuleGraph {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc nextModuleIter(mi: var ModuleIter; g: ModuleGraph): PSym {....raises: [], tags: [], forbids: [].}
- Source Edit
proc onProcessing(graph: ModuleGraph; fileIdx: FileIndex; moduleStatus: string; fromModule: PSym) {....raises: [ValueError, OSError, KeyError, Exception, IOError, ERecoverableError], tags: [RootEffect, ReadDirEffect, WriteIOEffect, ReadIOEffect, ReadEnvEffect], forbids: [].}
- Source Edit
proc parentModule(g: ModuleGraph; fileIdx: FileIndex): FileIndex {....raises: [], tags: [], forbids: [].}
- returns 'fileIdx' if the file belonging to this index is directly used as a module or else the module that first references this include file. Source Edit
proc recordIcImplDep(g: ModuleGraph; s: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- NeedsImpl edge tracking, see icImplDeps. Called from the compile-time body consumption sites (vmgen's proc compilation, the getImpl opcodes). Own-module and group-member entries are filtered out when the .edges sidecar is written. Source Edit
proc reexportedModuleSyms(g: ModuleGraph; m: PSym): seq[(string, string)] {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- (name, NIF module suffix) of MODULE syms in m's interface — these are re-exports (import x; export x, added by reexportSym) acting as qualifiers (m.x.sym). Consumed by the NIF writer; semExport does not put them into the nkExportStmt children, so the AST walk cannot see them. Source Edit
proc registerIncluderFromNif(g: ModuleGraph; fileIdx: FileIndex): bool {. ...raises: [OSError, ValueError, Exception, KeyError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
-
Targeted cold-include discovery for nimsuggest: scan the nimcache NIFs (scanIncludeGraph) for a module whose include-set contains this file and register only that single include->module edge in inclToMod, so a query inside the include file resolves its includer via parentModule.
Deliberately targeted: registering every include relationship (i.e. also system's own includes) eagerly assigns FileIndexes and pollutes inclToMod, which perturbs the NIF line-info decode of unrelated modules (system.string then resolves into excpt.nim). Touch nothing but the one edge we need.
Source Edit proc registerLoadedMethod(g: ModuleGraph; m: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Rebuild the dispatch buckets from a serialized method registration. Buckets group the methods sharing a dispatcher; the dispatcher's BODY does not exist in serialized form — generateIfMethodDispatchers synthesizes it in the backend from the complete bucket. Source Edit
proc registerModule(g: ModuleGraph; m: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc registerModuleById(g: ModuleGraph; m: FileIndex) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc resetAllModules(g: ModuleGraph) {....raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc resetForBackend(g: ModuleGraph) {....raises: [], tags: [], forbids: [].}
- Source Edit
proc setAttachedOp(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) {....raises: [Exception], tags: [RootEffect], forbids: [].}
- we also need to record this to the packed module. Source Edit
proc setAttachedOp(g: ModuleGraph; module: int; typeId: ItemId; op: TTypeAttachedOp; value: PSym) {....raises: [], tags: [], forbids: [].}
- Overload that takes ItemId directly, useful for registering hooks from NIF index. Source Edit
proc setAttachedOpPartial(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) {....raises: [], tags: [], forbids: [].}
- we also need to record this to the packed module. Source Edit
proc setHookDisamb(g: ModuleGraph; hook: PSym; opName: string; typ: PType) {. ...raises: [Exception, KeyError], tags: [RootEffect], forbids: [].}
- Under IC, replace a synthesized hook's counter-based disamb with a content-derived one: a hash of the operation name plus the typeKey of the type it is bound to. Counter disambs renumber whenever an earlier hook appears in a re-semmed module, so cached translation units keep calling the old _u<disamb> C name while the regenerated producer defines a new one — the hook flavor of the backend def-migration hole. With a content-derived value the hook's NIF name (and hence its C name) is stable as long as the type itself is unchanged. Source Edit
proc setInstanceDisamb(g: ModuleGraph; inst, generic: PSym; concreteTypes: openArray[PType]) {. ...raises: [Exception, KeyError], tags: [RootEffect], forbids: [].}
- Under IC, replace a fresh routine instance's counter-based disamb with a content-derived one: a hash of the generic's identity plus the typeKey of every concrete type argument — exactly the identity the instantiation cache compares. The instance's NIF name name.disamb.modsuffix then differs only in the module suffix when the same instantiation is made by different modules, which is the prerequisite for cross-module generic-instance merging (and gives the dce analysis its offers keys). The hash is computed once, here; it is never recomputed — the value travels in the serialized disamb field. Source Edit
proc setMethodsPerType(g: ModuleGraph; id: ItemId; methods: seq[PSym]) {. ...raises: [], tags: [], forbids: [].}
- Source Edit
proc setToStringProc(g: ModuleGraph; t: PType; value: PSym) {. ...raises: [Exception], tags: [RootEffect], forbids: [].}
- Source Edit
proc someSymAmb(g: ModuleGraph; m: PSym; name: PIdent; amb: var bool): PSym {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc stopCompile(g: ModuleGraph): bool {.inline, ...raises: [Exception], tags: [RootEffect], forbids: [].}
- Source Edit
proc strTableAdds(g: ModuleGraph; m: PSym; s: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc systemModuleSym(g: ModuleGraph; name: PIdent): PSym {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc uniqueModuleName(conf: ConfigRef; m: PSym): string {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- The unique module name is guaranteed to only contain {'A'..'Z', 'a'..'z', '0'..'9', '_'} so that it is useful as a C identifier snippet. Source Edit
proc unmarkAllDirty(g: ModuleGraph) {....raises: [], tags: [], forbids: [].}
- Source Edit
Iterators
iterator getDispatchers(g: ModuleGraph): PSym {....raises: [], tags: [], forbids: [].}
- Source Edit
iterator getMethodsPerType(g: ModuleGraph; t: PType): PSym {....raises: [KeyError], tags: [], forbids: [].}
- Source Edit
iterator methodsForGeneric(g: ModuleGraph; t: PType): (int, PSym) {. ...raises: [KeyError], tags: [], forbids: [].}
- Source Edit
iterator procInstCacheItems(g: ModuleGraph; s: PSym): PInstantiation {. ...raises: [KeyError], tags: [], forbids: [].}
- Source Edit
iterator suggestErrorsIter(g: ModuleGraph): Suggest {....raises: [], tags: [], forbids: [].}
- Source Edit
iterator suggestSymbolsIter(g: ModuleGraph): SymInfoPair {....raises: [], tags: [], forbids: [].}
- Source Edit
iterator systemModuleSyms(g: ModuleGraph; name: PIdent): PSym {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
iterator typeInstCacheItems(g: ModuleGraph; s: PSym): PType {. ...raises: [KeyError], tags: [], forbids: [].}
- Source Edit