Nimony

The road to Nim 3

nifroles

nimony/src/lib/nifroles.nim

What a NIF traversal/emission routine does to the cursor and the buffer, declared by the routine itself.

The validator has to know that skip n advances without emitting while takeTree dest, n does both, that takeLocal consumes a whole declaration and that copyInto opens a tree and closes it again. It used to know that from a table of ~50 names, which is knowledge kept at the wrong end: adding an operation to the API meant editing the validator, and a pass-local proc that happened to be called skip was indistinguishable from this one.

A custom pragma survives semchecking as (pragma <sym>), so the validator reads the role where it is declared, and reads a symbol rather than a spelling. Where the pragma goes depends on what the routine is:

  • a proc carries it on its declaration, and the validator reads it off

the callee symbol of each call;

  • a template carries it as the first statement of its body, so every

expansion of it opens with the marker. There is no call left to read at a call site — the template is gone by the time the validator sees the tree — and the marker stands at the head of exactly the region it describes.

The second form is what makes the roles work without --inlineframes:on: the validator needs no expansion provenance to tell which template produced a region, because the region says so itself. It relies on a template body being semchecked in the scope the template was declared in, so the marker arrives at the expansion site already bound — std/json wraps nifcore.into, and into's body is expanded inside modules that never imported nifroles.

Emission is deliberately not in this list. A routine whose first parameter is a var TokenBuf and which takes no cursor emits and nothing else; that is what its signature already says, and saying it again on each of the forty add* overloads would be noise that can drift.