aoughwl/nimony

An opinionated fork of Nimony — the NIF-based reimplementation of the Nim compiler — that tracks upstream master daily and ships a standard library built to our taste. Same compiler core; fewer opinions imposed on you, more of ours baked in.

Repo → github.com/aoughwl/nimony

This page is the canonical record of what our tree fixes and adds over stock upstream nim-lang/nimony. Our master is the branch we use internally and share: it stays current with upstream and carries our own fixes and features on top.

Contents

What’s different

  • Fewer bugs, more frontline features. All Nimony work ships here first, and we aggressively push lagging features.
  • Stays current. We pull from nim-lang/nimony master ~daily — upstream’s compiler progress with none of the lag. A fork that keeps up, not one that drifts.
  • A fuller, opinionated stdlib. 60+ modules and counting — batteries the official tree doesn’t ship yet, or ships grudgingly: terminal (fluent, npm-colors-style string styling), base64, md5, sha1, bitops, complex, deques, heapqueue, editdistance, sequtils, options, random, wordwrap, and more. Ergonomics first.

The convention: every time we fix an issue or add a feature, it gets a row below (and in doc/CHANGES.md in the repo). This is the ledger — kept current.


Features Added

Compiler support that makes nimony’s {.passive.} CPS coroutines usable as a real async library. Each links to its full writeup in the Changelog.

# Feature Files Verified by
F1 Cross-module .passive coro_transform.nim cps.nim tsleep3 tgather2
F2 delay <call> inside generics sem.nim tgenrace
F3 suspend() in a generic .passive proc sem.nim cps suite
F4 Proc-pragma macros ({.async.}) macros_nif.nim semcall.nim macro_plugin.nim tasyncsugar

The async runtime — aoughwl/nimony-web

A complete cooperative-async runtime over these coroutines, driven by the host event loop — 46/46 under Node. Each row is documented on the async runtime page.

Feature What it gives you Docs
Future[T] + await value-returning async, importable across modules async
Dispatcher callSoon / drainReady / runForever, reentrancy-guarded FIFO async
Importable sleepAsync reusable {.passive.} sleep, called cross-module async
Generic gather / all await many futures, importable & generic async
Generic race[T] / any first-to-finish wins, returns the real T async
{.async.} proc sugar write {.async.} instead of {.passive.} async

Incremental compilation & the tooling backend

Nimony’s design already leans on cached, typed NIF artifacts per module — which makes it a natural fit for fast re-checks. This tree pushes that further so that interactive tooling (the nimony-lsp language server’s live as-you-type diagnostics, in particular) has a compile path that stays warm and cheap. These are the concrete wins, most user-visible first.

Win What it does Measured
Parallel dependency discovery A breadth-first pre-pass (preNifle) runs nifler over the whole import closure in parallel before the DFS, which then does only cheap in-memory work. Self-healing serial fallback. discovery wall 0.43s → 0.24s (1.77×)
Incremental cursor traversal nimsem walks the module structure with an incremental cursor instead of re-materializing it (toward #2064).
Warm-worker daemon (nimsem serve) Persistent semcheck worker; keeps the interner, interface cache and indexes warm across requests. JSONL protocol with a dirty-buffer seam. Foundation for interactive rebuilds. system interned 1× / session
Batch-intern ceiling + proof Measured the re-intern cost a daemon removes (system.s.idx.nif re-interned 107× on tall.nim) and proved batching 20 modules in one process fixes it. index intern 91.6ms → 8.6ms

Why this matters for editors. A whole-project nimony check is ~1.1s cold but only ~10–25ms on an incremental warm re-check. That gap is exactly what lets nimony-lsp publish diagnostics on every keystroke (against the unsaved buffer, in an isolated nimcache) without a background daemon — see the nimony-lsp page. The nimsem serve daemon above is the next-tier backend for when cross-module query latency (go-to-def / references on huge trees) needs to be warm too; it’s wired into nimony-lsp as an opt-in path.


Issues Fixed

Eight compiler fixes over stock upstream. Each row opens its own writeup — symptom, root cause, the fix, files, and the verifying test.


Known limits (not yet fixed)

  • Raise-across-await — the .raises error-tuple ABI was never threaded through the coroutine lowering (coro_transform types the lifted result as raw ptr T, not ptr (ErrorCode, T)). The crash is gone (issue #4), but real cross-await exception propagation is a deferred feature; the nimony-web library propagates errors via Future.err.
  • Dispatcher shutdown — a coroutine that finishes after the entry coroutine returns crashes the dispatcher; keep the entry main last.
  • WASM async glue — the runtime core is portable; only the timer/pump seam is JS-specific today.

Relationship to upstream

This mirrors and stays in sync with nim-lang/nimony. Compiler fixes are meant to be portable both ways; the standard-library direction is ours to steer. Pull requests are welcome — no BDFL, just taste. See AGENTS.md in the repo for the full toolchain, phase pipeline, and test workflow.


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.