niflens — a NIF lens for tooling

A thin CLI over Nimony’s own NIF libraries (nifreader / nifstreams / nifcursors / nifindexes). It reads nimcache/*.nif artifacts with the real parser and emits compact JSON for a host tool to consume.

Repo → github.com/aoughwl/niflens

Why

Tools that inspect NIF — an LSP, the nim-code plugin, a formatter — otherwise re-implement a NIF reader (usually a regex/hand-rolled scanner) and inherit a class of bugs: approximate line-info decoding, mishandled escapes, a stale tag vocabulary, no real index reading. Because niflens links the compiler’s libraries, its output always matches the toolchain that produced the file, and it tracks NIF format bumps (nif26nif27 → …) for free.

Versus a regex reimplementation, niflens decls returns the name glyph position (not the enclosing keyword), the full module-qualified symId (add.0.<module>, not a truncated add.0.), and the complete symbol table — all with the compiler’s own line info.

Design

niflens is the CLI/daemon frontend of a shared NIF core intended to back both the nim-code plugin and a Nimony LSP. The host shells out to niflens (the same subprocess pattern it uses for nimony / nimsem) and falls back to its own reader if the binary is absent. Subprocess (not FFI) keeps crash isolation, avoids an ABI/GC boundary, and needs no per-platform shared library.

Build & use

niflens links Nimony’s src/lib NIF modules — a source dependency, not a nimble package. Point NIMONY_SRC at a Nimony checkout:

NIMONY_SRC=/path/to/nimony nimble build      # -> bin/niflens
niflens decls <file.s.nif> [symbol]   # declaration sites -> JSON array
niflens version

decls emits one object per SymbolDef: {sym, name, kind, file, line, col} (col is 0-based, idetools convention). An optional symbol filters by full symId (exact / prefix) or human base name.

[{"sym":"addup.0.mwsmvs","name":"addup","kind":"proc","file":"m.nim","line":1,"col":5}]

Commands

Command What it returns
decls declaration sites (SymbolDef walk)
render pseudo-Nim per top-level decl
index .s.idx.nif contents via nifindexes (checksum, converters, re-exports)
outline top-level declarations with positions
query subtrees matching a needle → canonical NIF snippet
serve line-oriented stdio daemon (one process across requests)

Status & roadmap: the serve daemon and the shared NIF core both exist. The remaining convergence step — having nimony-lsp link niflens’s core directly (instead of its own in-process NIF readers) — is deliberately deferred: it wants a real extraction with tests, not a blind cross-repo restructure. Next for serve itself: cache parsed TokenBufs of hot modules across requests, the persistent-index win that benefits both consumers.


Back to top

aoughwl — next-gen self-hosted platform for things n stuff. Reach out on Discord (timbuktu_guy) for access to the private backends.

This site uses Just the Docs, a documentation theme for Jekyll.