types.rs defines the primitive vocabulary shared by every layer of the
pipeline: the token and node enumerations produced by the lexer, the concrete
Token / ParseNode / ASTNode structs consumed by the parser and evaluator,
and TryFrom<i32> impls that allow Python and serialised representations to
round-trip through integer discriminants.
Design rationale
repr(u8) on TokenKind
TokenKind carries #[repr(u8)] so its discriminants are stable integers in
serde round-trips. The fourteen variants fit in a single byte; the TryFrom<i32>
impl validates the range on deserialisation.
NodeKind::NotUsed = 0
Discriminant 0 is intentionally left empty. Python IntEnum defaults start
at 1, so keeping 0 unused means NodeKind::Text = 1 aligns with Python’s
NodeKind.Text = 1 without any manual offset arithmetic.
Token is Copy
Tokens carry only an index (src: u32), byte offset (pos: usize), and
length — no heap allocation. Copy lets the parser stash tokens freely in
ParseNode and ASTNode without clone overhead.
ParseNode vs ASTNode
ParseNode.parts stores indices into a flat arena (the parser’s Vec<ParseNode>).
ASTNode.parts stores owned child nodes — the AST is a proper tree. The
conversion pass in ast/mod.rs materialises the arena into the tree.
Token::synthetic
Some structural nodes (the root block, implicit first parameters) have no
corresponding source token. Token::synthetic(src, pos) creates a
zero-length placeholder so that end_pos computation remains correct.
File structure
// <<@file weaveback-macro/src/types.rs>>=
// <<types preamble>>
// <<token kind>>
// <<node kind>>
// <<token struct>>
// <<lexer error>>
// <<parse node>>
// <<ast node>>
// <<try from token kind>>
// <<try from node kind>>
// @
Preamble
// <<types preamble>>=
// crates/weaveback-macro/src/types.rs
use ;
use TryFrom;
// @
TokenKind
Fourteen token kinds produced by the lexer. See lexer for the state machine that emits them.
// <<token kind>>=
// @
NodeKind
Node kinds used in ParseNode and ASTNode. Discriminant 0 (NotUsed) is
reserved so that Python IntEnum discriminants (which start at 1 by default)
align without an offset.
// <<node kind>>=
// @
Token
A lightweight (all Copy) source reference. src is an index into the
evaluator’s SourceManager; pos and length are byte offsets into that
source string.
// <<token struct>>=
// @
LexerError
// <<lexer error>>=
// @
ParseNode
Produced by the parser; children are stored as indices into the parser’s flat
arena. Converted to ASTNode by the post-pass in ast/mod.rs.
// <<parse node>>=
// @
ASTNode
The materialised tree form. parts contains owned child nodes;
name carries the identifier token for Macro and Var nodes.
// <<ast node>>=
// @
TryFrom<i32> for TokenKind
// <<try from token kind>>=
// @
TryFrom<i32> for NodeKind
// <<try from node kind>>=
// @