Nimony

The road to Nim 3

linkedtok

nimony/src/nifler2/linkedtok.nim

The tree the parser builds, as links rather than as packed tokens.

nifcore.TokenBuf is the right shape for a tree that is read: a flat array of NifToken, a subtree spanned by a jump field, skip an O(1) pointer bump. It is the wrong shape for a tree that is still being rewritten, which is what a parser for Nim's grammar does on almost every node -- a + b has to put the operator in front of an operand that is already written, a declaration with three names fans out into three nodes, a trailing do block moves inside the call in front of it. Against a flat array each of those is a memmove of the region since the mark, and reading the region back means a Cursor, which mints a CursorOwner header for the buffer and frees it again on the next append.

Here a node is a cell: down is its first child, next its next sibling. Wrapping a run of siblings in a new tag, inserting an operator in front of one, moving the last child to the front -- all are pointer assignments that touch a constant number of cells, whatever the size of the subtree.

What does NOT change is the atoms. A payload is a nifcore.NifToken built by nifcore's own constructors, so a tag is still a TagId and a name is still a StrId interned in the same Pool: only the wiring is local to nifler2. The one thing that does not fit in a token's 28-bit payload is a numeric literal, which nifcore spreads over up to three chained tokens; a cell keeps the value in wide instead and flatten hands it back to nifcore's chaining writer untouched.

Cells come from a bump arena. Allocation is a pointer increment, and the whole tree is released by freeing the blocks -- there is nothing per-cell to run, which is what lets the rewrites drop subtrees on the floor instead of splicing them out.