icnifcore

Search:
Group by:
Source   Edit  

nifcore-based IC serialization helpers — Stage 1 of porting the IC backend from the old nifstreams/nifcursors NIF stack to nifcore (see doc/ic_nifcore_port.md).

It hosts:

  • the process-wide shared Pool/TagPool that stands in for the old global nifstreams.pool,
  • writeFileStable, the content-stable file writer mirroring nifcursors.writeFile(..., OnlyIfChanged),
  • the first ported writer (writeSemDeps), used as the migration spike.

No nifstreams/nifcursors types cross this module's boundary: callers pass plain Nim values (config, ids, string lists), so it can coexist with the still-old-API ast2nif.nim during the migration.

Types

CookieKind = enum
  ckParLe, ckParRi, ckSym, ckSymDef, ckIdent, ckStr, ckInt, ckUInt, ckFloat,
  ckChar, ckDot
Source   Edit  
CookieTok = object
  kind*: CookieKind
  tag*: string
  name*: string
  sym*: uint32
  str*: string
  ival*: int64
  uval*: uint64
  fval*: float64
  cval*: uint32
Source   Edit  
IcBuilder = object
  buf*: TokenBuf
A thin nifcore TokenBuf builder whose surface is primitive types only (strings/ints/floats). It lets the still-old-API ast2nif.nim drive a nifcore buffer without any nifcore type crossing the module boundary — the bridge that routes IC output onto the nifcore serializer (Stage 2). Source   Edit  

Lets

icPool = newPool()
Source   Edit  
icTags = newTagPool()
Source   Edit  

Procs

proc addAll(dest: var IcBuilder; src: var IcBuilder) {....raises: [], tags: [],
    forbids: [].}
Append every top-level subtree of src into dest — the nifcore analogue of the old dest.add wholeBuffer splice. Source   Edit  
proc addCharLit(b: var IcBuilder; c: char) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addDotToken(b: var IcBuilder) {.inline, ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc addFloatLit(b: var IcBuilder; v: float64) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addIdent(b: var IcBuilder; s: string) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addIntLit(b: var IcBuilder; v: int64) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addStmtsBody(dest: var IcBuilder; src: var IcBuilder) {....raises: [],
    tags: [], forbids: [].}
Append the BODY of a (stmts . . <body> ) builder into dest, dropping the wrapper tag and its two leading dot slots (flags/type) — the nifcore analogue of the old for i in 3 ..< content.len-1: dest.add content[i]. Source   Edit  
proc addStrLit(b: var IcBuilder; s: string) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addSymDef(b: var IcBuilder; s: string) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addSymUse(b: var IcBuilder; s: string) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc addUIntLit(b: var IcBuilder; v: uint64) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc closeTag(b: var IcBuilder) {.inline, ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc collectBifStrLits(path: string): seq[string] {....raises: [IOError],
    tags: [ReadIOEffect], forbids: [].}

Read a small (tag "s" "s" …) bif sidecar (semdeps/edges) and return every string literal it holds, in order — the binary analogue of the old nifstreams scan that collected StrLits. Keeps nifcore types out of deps.nim, which only needs the recorded string list.

Uses loadFromFile (a full read into owned memory) rather than the mmap-backed bif.load, then CLOSES the handle. bif.load intentionally leaves the mapping resident for the process lifetime; for the nim ic driver that reads these sidecars while nim m children rewrite them, a lingering read mapping is a Windows sharing violation: the child's open(path, fmWrite) fails with IOError: cannot open. These sidecars are tiny, so the zero-copy mmap buys nothing here anyway.

Source   Edit  
proc createIcBuf(cap = 16): TokenBuf {.inline, ...raises: [], tags: [], forbids: [].}
A TokenBuf bound to the shared IC pools. Source   Edit  
proc cursorPool(c: Cursor): Pool {.inline, ...raises: [], tags: [], forbids: [].}
The literals pool the cursor's buffer was built against. ast2nif.nim imports nifcore with except pool (to keep nifstreams' global pool var the writer uses), so the reader reaches a cursor's pool through here — needed once bif-loaded buffers carry their OWN fresh pool rather than the shared icPool. Source   Edit  
proc flattenForCookie(b: var IcBuilder): seq[CookieTok] {....raises: [], tags: [],
    forbids: [].}
Flatten the nifcore module buffer to the cookie hashers' flat token list. Source   Edit  
proc lineInfo(b: var IcBuilder; file: string; line, col: int32; comment = "") {.
    ...raises: [], tags: [], forbids: [].}
Attach line info (+ optional #comment#) to the head just emitted. No-op when file is empty (matches the old "emit only when info is valid"). Strings are interned in the shared pools; the file/comment ids reproduce the old pool.files/pool.strings entries by string value. Source   Edit  
proc newIcBuilder(cap = 16): IcBuilder {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc openTag(b: var IcBuilder; tag: string) {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc storeBif(b: var IcBuilder; path: string; dottedSuffix: string) {.
    ...raises: [IOError], tags: [WriteIOEffect], forbids: [].}
Persist the buffer as a compact, self-contained binary NIF (.bif). Source   Edit  
proc storeBifStable(b: var IcBuilder; path: string; dottedSuffix: string) {.
    ...raises: [IOError, OSError, Exception],
    tags: [WriteIOEffect, ReadIOEffect, WriteDirEffect, ReadDirEffect],
    forbids: [].}
Content-stable bif write — the binary analogue of writeFileStable's onlyIfChanged: only replace path when the encoded bytes differ, so an unchanged sidecar keeps its mtime and nifmake prunes the dependent rebuild cascade. Used for the iface/impl cookies + dep sidecars whose byte-stability gates incremental builds. (bif encoding is deterministic for a given buffer under fresh pools, so equal content ⇒ equal bytes.) Source   Edit  
proc tagId(s: string): TagId {.inline, ...raises: [], tags: [], forbids: [].}
Intern a tag name in the shared tag pool. Source   Edit  
proc writeFileStable(b: var TokenBuf; path: string; onlyIfChanged = false) {.
    ...raises: [Exception, IOError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect], forbids: [].}
Serialize b to canonical module NIF text and write it. Mirrors nifcursors.writeFile: the module suffix is derived from path ("." & extractModuleSuffix), and onlyIfChanged skips the write when the on-disk bytes already match — the content-stability nifmake's incremental rebuild depends on. Source   Edit  
proc writeSemDeps(config: ConfigRef; thisModule: int32; importPaths: seq[string]) {.
    ...raises: [OSError, IOError, Exception], tags: [ReadEnvEffect, ReadIOEffect,
    WriteIOEffect, WriteDirEffect, ReadDirEffect], forbids: [].}
Stage 1 spike: the nifcore port of ast2nif.writeSemDeps. Serializes the module's resolved direct imports as (semdeps "path" ...). Byte-identical to the old writer (verified), so nim ic build graphs are unaffected. Source   Edit  
proc writeStable(b: var IcBuilder; path: string; onlyIfChanged = false) {.
    inline, ...raises: [Exception, IOError],
    tags: [RootEffect, ReadIOEffect, WriteIOEffect], forbids: [].}
Source   Edit