nifbuilder
nimony/src/lib/nifbuilder.nim
Support code for generating NIF code.
func dollar`.Mode(e: Mode): stringtype Builder = object buffer: string raw: ptr UncheckedArray[char] cap: int64 mode: Mode writeMode: FileWriteMode compact: bool filename: string nesting: int64 offs: int64
proc open(filename: string; compact: bool; writeMode: FileWriteMode): BuilderOpens a new builder attached to some output path. Writes are buffered in memory and flushed via
vfsWriteatclose(). WithwriteMode = OnlyIfChangedthe close compares the buffered bytes to the existing file and skips the write (preserving mtime) when they match — useful for tools whose output should not bump downstream mtimes when nothing actually changed (e.g. nifler).proc open(sizeHint: int64; compact: bool): BuilderOpens a new builder with the intent to keep the produced code in memory.
proc attachedToFile(b: Builder): boolproc extract(b: sink Builder): stringExtracts the buffer from the builder. The builder should not be used afterwards.
proc close(b: var Builder)const ControlChars: set[char]proc addRaw(b: var Builder; s: string)proc addNumber(b: var Builder; s: string)proc addIdent(b: var Builder; s: string)proc addSymbol(b: var Builder; s: string)proc addSymbolDef(b: var Builder; s: string)proc addSymbol(b: var Builder; s: string; dottedSuffix: string)proc addSymbolDefRetIsGlobal(b: var Builder; s: string; dottedSuffix: string): boolReturns true if the symbol is global.
proc addStrLit(b: var Builder; s: string)proc addEmpty(b: var Builder; count: int64)proc addCharLit(b: var Builder; c: char)proc addIntLit(b: var Builder; i: int64)proc addUIntLit(b: var Builder; u: uint64)proc addFloatLit(b: var Builder; f: float64; col: int32; line: int32; file: string)Emit a float literal. Special values (
inf,nan,neginf) are emitted as compounds; for those,(col, line, file)if non-zero is attached as a suffix on the inner tag (the only place a NIF27 line-info suffix can go). For finite values the caller is expected to callattachLineInfoseparately; the args here are honored as a convenience.proc attachLineInfo(b: var Builder; col: int32; line: int32; file: string)Append a NIF27 line-information suffix to the most recently emitted atom or tag name. There must be no whitespace between the atom/tag and this call (do not call
addSep,addEmpty, or anyadd*Litbetween them). A no-op when all components are zero/empty.template addLineInfo(b: var Builder; col: int32; line: int32; file: string)Backwards-compatible alias for
attachLineInfo. Callers must invoke this after the atom or tag whose info they want to record — there is no buffering, no "pending" state.proc attachComment(b: var Builder; s: string)Append a NIF27 comment suffix
#<s>#to the most recently emitted atom or tag name (or directly after a precedingattachLineInfo). No whitespace allowed before the#.proc addKeyw(b: var Builder; keyw: string)Adds a complete compound node that has no children like
(nil).proc addTree(b: var Builder; kind: string)Starts a new compound node. Must be closed with
endTree. See alsowithTree.kindis allowed to start with a dot. This emits a directive then.proc endTree(b: var Builder)template withTree(b: var Builder; kind: string; body: untyped)Convenience template that wraps
bodyaroundaddTreeandendTreecalls.proc addUIntLit(b: var Builder; u: uint64; suffix: string; col: int32; line: int32; file: string)proc addStrLit(b: var Builder; s: string; suffix: string; col: int32; line: int32; file: string)proc addHeader(b: var Builder; vendor: string; dialect: string)proc addHeader27(b: var Builder): int64Returns the patch position for the indexat overwrite.
proc patchIndexAt(b: var Builder; patchPos: int64; indexAt: int64)proc offset(b: Builder): int64Returns the current offset for index generation. The produced value might point to whitespace that must first be skipped before the desired element is reached but the nifreader will skip the whitespace automatically, so no harm is done.