19. Compile Pipeline

A reference pipeline; implementations may differ if the observable output matches.

Parse. Lex to tokens, then a single recursive-descent pass to the AST. The bracket-and-bars vocabulary (|…| identity, { } style, [ ] content) resolves every statement with one token of lookahead — no type-set prescan (SPEC 22).

Desugar. Lower all surface sugar to primitives + classes — the engine’s true input. The pass is idempotent; type-system errors (cycle, depth > 16, a define shadowing a built-in) surface here. What becomes explicit:

  • Types & rules: each template / define instance becomes its base primitive wearing a .lini-* class chain (derived → base → primitive, down to block for every rectangular type); a type’s defaults and any |type| { } element rule fold into a generated .lini-<type> { … } class; a |table| |box| { } descendant rule rewrites to .lini-table .lini-box { }, and |-| (the link type) to .lini-link — the class every link wears; define bodies inline per instance.
  • Scene config: the scene defaults (layout, padding, gap, font-size, clearance, routing, density) settle on the root; a drawing (or floorplan) scope’s unit: × the root density: fold into its one internal px-per-unit — its pixels per drawing unit at ratio 1, which the cascading scale: multiplies at layout — and a floorplan scope’s unit: is stamped for its types’ mm defaults to convert through where each is read (SPEC 15.1, SPEC 15.11).
  • Statements: the per-type smart label (text / caption / symbol / link label / chart title …); auto-along:; chain expansion (a -> b -> ca -> b; b -> c, auto-created ids included — fan-out & stays a resolve / routing concept; a schematic chain is the carve-out, SPEC 16.5); a tree’s branch links, .lini-level-N classes, and a mindmap’s palette-walk rules (SPEC 12); link auto-create (an undeclared endpoint x|box#x| "x"); and capsule hoisting (an endpoint capsule → a declaration at the statement’s position + a reference, anonymous ones under minted lini-cap-N ids — SPEC 9).
  • Schematic lowerings: pin rails, ref readouts and minted display refs, label-wire minting (U7.DIAG - "NSTDBY" → a |label| + its wire), and the scope’s look rules (SPEC 16).

Resolve (top-to-bottom):

  1. Variables, functions & rules: merge visual-var defaults ← --theme--name: value; build the function table; compile the stylesheet’s class / id / element / descendant rules. Parenthesized expressions and function calls fold to literal numbers / points (SPEC 10.7).
  2. Scene tree: each box is a primitive wearing .lini-* (type) and user classes; layer properties per the cascade; lift internal links; build the path index. A |table|/|entity|’s structure settles here, once its columns: has — the header band, the carried column alignment, an entity’s full-width spans (SPEC 8).
  3. Links: resolve endpoints by scoped path walk with suggestion errors; merge link properties through the link’s ladder (SPEC 4); cartesian-expand fan groups into one resolved link per pair; the operator’s line sets stroke-style unless overridden.

Layout (bottom-up): leaf bbox from width/height or defaults (text → its glyphs; box → content + padding; + half-stroke-width per side); arrange flow children per layout / direction honouring align/justify/stretch/evenly when there is slack; pin out-of-flow children to their parent anchor (the parent never grows for them); compute gutters; apply padding; apply each node’s translate; rotate last. A layout-owning container — sequence (SPEC 13), chart / pie (SPEC 14.9), and drawing / floorplan (SPEC 15.10, SPEC 15.11) — instead reads its whole subtree here and lowers it to primitives, consuming its own links, so the router never sees them.

Route links. Per ROUTING.md — orthogonal, clearance-respecting, deterministic — over every link except those a drawing scope already drew; a sequence’s messages route straight with layout-fixed anchors. Place markers (sized max(5, stroke-width × 4) + 1, tip on the endpoint) and link labels at their along: fractions (auto-distributed when unset).

Render. Depth-first emit SVG per SPEC 18: a box is a <g>, a string is a <text>. A lowered chart / sequence subtree renders as ordinary primitives (SPEC 11, seam 3).