AST to NIF bridge.
Types
DecodeContext = object
- Source Edit
ModuleSuffix = distinct string
- Source Edit
ParsedSymName = object name*: string module*: string count*: int
- Source Edit
PrecompiledModule = object topLevel*: PNode deps*: seq[ModuleSuffix] logOps*: seq[LogEntry] module*: PSym reexportedModules*: seq[(string, string)] genericOffers*: seq[tuple[generic, inst: PSym, concreteTypes: seq[PType], genericParamsCount: int]] ## generic instances this module created; modulegraphs.nim rebuilds ## `procInstCache` from them so a consumer reuses the instance instead of ## re-instantiating it in its own (operator-blind) module scope.
- Source Edit
Consts
SysModuleSuffix = "@sys"
- Reserved module-suffix sentinel for module-less magic singleton types — the nil type is created via newSysType with the graph idgen, whose module can be -1 (e.g. during VM const-eval before a real module is current), so its uniqueId.module is unresolvable. Such a type has no fields and an identity that is fully captured by its kind, so we serialize it with this sentinel and reconstruct it on load (see createTypeStub) without ever touching a .nif file. A real moduleSuffix never starts with '@'. Source Edit
Procs
proc createDecodeContext(config: ConfigRef; cache: IdentCache): DecodeContext {. ...raises: [], tags: [], forbids: [].}
- Supposed to be a global variable Source Edit
proc getMainModuleSuffix(c: DecodeContext): string {.inline, ...raises: [], tags: [], forbids: [].}
- Source Edit
proc globalName(sym: PSym; config: ConfigRef): string {....raises: [], tags: [RootEffect], forbids: [].}
- Source Edit
proc icNifTypeName(typ: PType; config: ConfigRef): string {....raises: [], tags: [RootEffect], forbids: [].}
- The serialized NIF name of a type, recorded next to RTTI data definitions in the cnif artifact so a later run can re-demand the typeinfo when a reused TU still references it (the def-retention check). Backend-minted types have no NIF name. Source Edit
proc loadNifModule(c: var DecodeContext; f: FileIndex; interf, interfHidden: var TStrTable; flags: set[LoadFlag] = {}): PrecompiledModule {. ...raises: [OSError, ValueError, KeyError, Exception], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc loadNifModule(c: var DecodeContext; suffix: ModuleSuffix; interf, interfHidden: var TStrTable; flags: set[LoadFlag] = {}): PrecompiledModule {. ...raises: [OSError, ValueError, KeyError, Exception], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
- Source Edit
proc loadSym(c: var DecodeContext; s: PSym) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc loadType(c: var DecodeContext; t: PType) {. ...raises: [KeyError, ValueError, Exception, OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc moduleSymbolStubs(c: var DecodeContext; module: FileIndex): seq[PSym] {. ...raises: [KeyError, OSError, ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
-
Stubs for every non-type symbol serialized in module's NIF index. The per-module backend uses this to emit the routines a module OWNS: procs are serialized as (sd ...) symbol-defs and loaded lazily, never as nkProcDef statements in the top-level stmt list, so genTopLevelStmt alone never reaches them — without this, a routine called only from other modules would be emitted by nobody once the demanding module merely prototypes it.
Returns lazy stubs: the index table is moved out while iterating (loading a symbol can register new modules and invalidate the iterator), so the caller forces full load (.kind, .ast) and filters AFTER this returns, with the index back in place.
Source Edit proc parseSymName(s: string): ParsedSymName {....raises: [], tags: [], forbids: [].}
- Source Edit
proc registerNifAstTags() {....raises: [], tags: [], forbids: [].}
- (Re)registers ast2nif's NIF tags explicitly. The top-level registerTag initializers above depend on nifstreams.pool having been initialized FIRST (pool = createLiterals(TagData) in nifstreams' module init) — an inter-module init-order requirement. The IC-built compiler currently emits module init calls in a different order, so the initializers registered into a pool that was subsequently replaced: the tag ids then denoted builtin tags (replay came out as deref, repdestroy as pat, ...) and every written NIF was silently corrupted. Called from nim.nim before any command runs; idempotent (getOrIncl by name). Source Edit
proc resolveHookSym(c: var DecodeContext; symId: nifstreams.SymId): PSym {. ...raises: [OSError, ValueError, KeyError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
- Resolves a hook SymId to PSym. Hook symbols are often private (generated =destroy, =wasMoved, etc.) Source Edit
proc setMainModule(c: var DecodeContext; fileIdx: FileIndex) {....raises: [], tags: [RootEffect], forbids: [].}
- Records the module that is being compiled fresh so that re-exports of its own symbols by dependencies are not turned into duplicate stubs. Source Edit
proc toClassSymId(config: ConfigRef; typeId: ItemId): nifstreams.SymId {. ...raises: [], tags: [RootEffect], forbids: [].}
- Converts a type ItemId to its SymId for the class index. Source Edit
proc toConverterIndexEntry(config: ConfigRef; converterSym: PSym): ( nifstreams.SymId, nifstreams.SymId) {....raises: [], tags: [RootEffect], forbids: [].}
- Converts a converter symbol to an index entry (destType, converterSym). Returns the destination type's SymId and the converter's SymId. Source Edit
proc toMethodIndexEntry(config: ConfigRef; methodSym: PSym; signature: string): ( nifstreams.SymId, nifstreams.StrId) {....raises: [], tags: [RootEffect], forbids: [].}
- Converts a method symbol/signature to a method index entry. Source Edit
proc toNifFilename(conf: ConfigRef; f: FileIndex): string {....raises: [OSError], tags: [RootEffect, ReadEnvEffect, ReadIOEffect], forbids: [].}
- Source Edit
proc tryResolveCompilerProc(c: var DecodeContext; name: string; moduleFileIdx: FileIndex): PSym {. ...raises: [OSError, ValueError, KeyError, Exception], tags: [RootEffect, ReadEnvEffect, ReadIOEffect, ReadDirEffect], forbids: [].}
- Tries to resolve a compiler proc from a module by checking the NIF index. Returns nil if the symbol doesn't exist. The NIF disamb is mint order, so name.0. can be any of the overloads sharing the name — for newSeq it is the generic magic, not the RTL proc (a refc build then demands codegen of the generic and dies on seq[T]): enumerate the index entries with this basename and pick the one that carries sfCompilerProc. Source Edit
proc writeNifModule(config: ConfigRef; thisModule: int32; n: PNode; opsLog: seq[LogEntry]; replayActions: seq[PNode] = @[]; implDeps: seq[int] = @[]; reexportedModules: seq[(string, string)] = @[]; genericOffers: seq[tuple[generic, inst: PSym, concreteTypes: seq[PType], genericParamsCount: int]] = @[]; resolvedImportDeps: seq[FileIndex] = @[]) {. ...raises: [KeyError, Exception, OSError, IOError, ValueError], tags: [ RootEffect, ReadEnvEffect, ReadIOEffect, WriteDirEffect, ReadDirEffect], forbids: [].}
- Source Edit
proc writeSemDeps(config: ConfigRef; thisModule: int32; importPaths: seq[string]) {. ...raises: [OSError, Exception], tags: [RootEffect, ReadEnvEffect, ReadIOEffect], forbids: [].}
- The module's REAL direct imports as nim m sem resolved them — static plus any a macro generated — recorded as full source paths. nim ic reads this .s.deps.nif to re-derive the build graph: imports the static scanner missed become new nodes (replacing the old build-failure discovery loop), and when false imports the scanner over-included are pruned. Always written so it is current after every successful sem (like .edges). Source Edit