scrml.dev v0.7.1
Reference › Elements

<match>

Tier 1 pattern matching as a block. Structural exhaustiveness against an enum type; rules-inert; same state-children shape that promotes mechanically to <engine>.

Syntax

<match for=TypeName [on=expr]>
  <Variant />
  <OtherVariant payload />
  ...
</match>

for= names the discriminating enum type. Every variant of that type must have an arm or the compiler fires E-MATCH-NOT-EXHAUSTIVE. on= picks the expression to match against; if omitted, the block matches the auto-declared engine variable for that type (typically the lowercased first-letter of the type name).

There is also a JS-style form match expr {...} for value-return branching in expression position. The two shapes coexist: the block-form <match> is the canonical UI-tree shape; the JS-style form is the canonical value-return shape. Both check exhaustiveness. See SPEC §18 for the JS-style grammar.

Worked example

A loading-state pattern. One enum, one match block, four arms — the compiler enforces that every variant has UI.

type Phase:enum = { Idle, Loading, Error(msg: string), Success(count: int) }

<phase> = .Idle

<match for=Phase>
  <Idle>
    <button onclick=${@phase = .Loading}>Load</button>
  </Idle>
  <Loading>
    Loading...
  </Loading>
  <Error msg>
    <div>${msg}</div>
  </Error>
  <Success count>
    Got it: ${count} rows
  </Success>
</match>

.Error and .Success carry payload; the arm binds it positionally (<Error msg>, <Success count>) and the body reads it bare. Per SPEC §18.0.3 + §18.7.

Semantics

  • Exhaustiveness is structural. The compiler reads the enum's variant list and requires an arm per variant. Missing arms fire E-MATCH-NOT-EXHAUSTIVE. A _ wildcard arm covers the residual.
  • Rules are inert. rule= on a <match> arm is accepted syntactically but does NOT enforce transitions — the surface is the <engine> feature. The compiler fires W-MATCH-RULE-INERT as a warning nudging toward promotion. Per SPEC §18.0.2.
  • effect= and <onTransition> are forbidden. <match> is pass-through case analysis — state-machine effects belong on <engine>. Fires E-MATCH-EFFECT-FORBIDDEN or E-MATCH-ONTRANSITION-FORBIDDEN.
  • Bare-variant inference. Arm patterns may omit the type qualifier (<Idle> not <Phase.Idle>) because for=Phase fixes the scope. Per SPEC §14.10 + §18.0.3.
  • Promotion is mechanical. bun scrml promote --match rewrites a <match> block to an <engine> in place. State-children carry verbatim; the wrapper tag changes. Per SPEC §56.

Errors this feature can fire

Edge cases

  • The on= expression is reactive. When on= reads reactive cells, the <match> block re-evaluates on change. Without on=, the block tracks the auto-declared engine variable for its for= type.
  • JS-style match expr {...} does NOT promote directly. Its semantic is value-return, not state-machine. If the value-return logic accumulates transition shape, hoist into a block-form <match for=Type> first, then run bun scrml promote.
  • An if-else chain over enum variants is also promotable. if (@phase == .Idle) ... else if (@phase == .Loading) ... fires I-MATCH-PROMOTABLE info-level lint at the discrimination site. Run bun scrml promote --match <file> to lift mechanically. Per SPEC §56.

Related features

  • <engine> — Tier 2 sibling. Same state-children shape; rules ACTIVE; transitions enforced; <onTransition> + effect= allowed.
  • JS-style match expr {...} — value-return form. Same exhaustiveness check against the discriminating type.
  • if= / show= — Tier 0 unstructured branching. No exhaustiveness guarantee; promotes to <match> via the I-MATCH-PROMOTABLE info-level lint.
  • <errors of=expr/> — the canonical way to render the ValidationError variants when a cell's validators fail. Often appears alongside <match> on form pages.

Availability

Surface Since Notes
<match for=Type> block S57 D2.8 (2026-05-04) Spec §18.0.1; parser+typer A1b B15-style
JS-style match expr { } v0.2 Pre-existing; ratified L8 — two shapes coexist
bun scrml promote --match S66 (Tier B SHIPPED 2026-05-07) CLI subcommand; idempotent; --dry-run supported
I-MATCH-PROMOTABLE info lint S66 (2026-05-07) Predicate matrix supports == and is .V at the discrimination site

Specification

This page summarizes SPEC §18 (Pattern Matching and Enums) plus §56 (Promotion Ergonomics). The normative text lives at compiler/SPEC.md in the scrmlTS repository. When this page disagrees with SPEC.md, SPEC.md is authoritative — surface the contradiction and we'll fix the docs.

Quick-lookup anchors: SPEC-INDEX.md entries — match block-form <match for=Type>, match attribute legality, bare-variant inference (match arm patterns), I-MATCH-PROMOTABLE, bun scrml promote --match.