Nimony

The road to Nim 3

json

nimony/lib/std/json.nim

json — a NIF-backed JSON model for the Nimony stdlib.

Built directly on nifcore, the same in-memory NIF representation the compiler's plugin API uses. A JSON document is not a tree of heap ref JsonNodes; it is a single flat nifcore.TokenBuf, navigated with a JsonNode — a thin wrapper over a nifcore.Cursor. The traversal verbs (into / hasMore / skip) and the builder verbs (openTag / addStrLit / …) are literally the same calls a plugin author uses on a compiler tree — so learning the JSON model and the NIF model is one act, not two. This is the unifying-stdlib idea: the concepts translate directly because the substrate is shared.

Encoding (a JSON value as a nifcore tag-stream)::

null → (null) # 1 TagLit, empty body <err> → (null "message") # parse error: a null carrying a diagnostic true → (true) false → (false) 42 → IntLit 42 # inline atom 3.14 → FloatLit 3.14 "hi" → StrLit "hi" [a,b] → (aconstr a b) {k:v} → (oconstr (kv "k" v))

Three layers, mirroring how nifply relates typed Nim to NIF:

  • parse / read — parseJson / parseFile build a JsonTree; navigate

with kind, getStr/getInt/…, len, items, pairs, {}.

  • typed map — toJson (typed Nim → JSON) and fromJson (JSON → typed

Nim), the JSON siblings of nifply's toNif/fromNif. Same reflection magics (internalFieldPairs / internalTypeName), same oconstr/kv/ aconstr tag vocabulary — differing only where idiomatic JSON differs (string keys, enums as name-strings, optional "type" discriminator).

  • line info — parseJson takes a LineInfoMode; under KeepLineInfo

each node carries a nifcore.LineInfoLit, the same cheap source-position token NIF uses. Building (toJson) carries none — there is no source.