A typed view over the binary AST: `Node<'Tag>` instead of a bare `int`.
Three things are generated here, all from `ast.json`:
- **Tags**, one per node type, per node alias and per token instantiation. A tag is
an interface that nothing ever implements; it exists so that `Node` and
`Node` are different types over the same two fields. Tag inheritance is
kind-set inclusion, so `'Tag :> Expression` is the compile-time form of the runtime
claim `AstKind.isExpression`.
- **Accessors**, one module per node type, returning `Node<'Tag>` at the type the
schema declares for the slot. Unlike `AstNode`, these cannot be pointed at the
wrong kind of node, because the argument is typed.
- **Views**, in `Patterns`, narrowing any node to a tag by testing its kind. They are
`[]` partial active patterns rather than a union, so a match costs a
kind read and a two-word copy and allocates nothing.
Widening is `.ofNode`, one function per alias: F# rejects a constraint whose
right-hand side is a type variable, so a single generic `widen` is not expressible.
The tag every other tag inherits, and the type of a slot the schema does not narrow -
a member declared as a bare `Node` or as an inline union. Narrow it with a view.