# Step: variant records Tag `v3-variant-records`. Suite **132/132**; fixpoint **OK** (image **2,135,590 bytes**). ## Grammar ``` RECORD id : INTEGER; (* plain fields *) ; CASE k : Kind OF (* the variant part *) circle : radius : INTEGER; | square : side : INTEGER; | rect : w, h : INTEGER; END END ``` - `RecordType` = `RECORD [ RecItem { ";" [ RecItem ] } ] END`, where `RecItem` is a plain `RecField` or a `CaseField`. Because a variant part starts with the `CASE` keyword it is unambiguously distinguishable from a field (which starts with an identifier), so the grammar stays LL(1). - `CaseField` = `CASE tag : Type OF RecFieldList { "|" RecFieldList } END`. Each `RecFieldList` is `VarLabel [ ".." VarLabel ] ":" RecField …`; labels are parsed but not interpreted (the layout overlays regardless). - The tag must be an ordinal type (else error **224**). ## Layout (`SymTab`) - Fields are registered per record as before; the tag field is recorded via `SetVariantTag`, and the record is flagged with `MarkVariant`. - `ComputeOffsets`: fields declared **before** the tag pack normally; the tag gets the next slot; **every** branch field overlays in the region after the tag. (Ranks are reverse-declaration, so "before the tag" is `ord < tag^.ord`.) - `TypeSizeD`: `plainSize + tagSize + max(branch field sizes)`. Example (`Kind`, then `Shape`): `id`@0, `k`@4, `radius`/`side`/`w`,`h` all @8; size 12. Branch fields share storage, so assigning `w` then `h` leaves `h`, and switching `k` reuses the slot — exactly the variant-record contract. `ResetFields` clears a record's pending-field buffer and layout at each `|` so later branches re-register; field names stay visible for `WITH`/`.field` access. ## Notes - Whole-record equality/assignment for a variant record is not offered (overlapping storage makes a field-by-field copy wrong); the existing array/record strictness gives 213 for such comparisons. - `WITH` over a variant's fields works (verified). ## Tests `t_variant.mod` (exit 31): plain field + tag + three branches, overlay (`w`/`h` share), branch switch (`square` reuses the slot). ## Files `compiler/src/M2.atg` (`RecItem`/`CaseField`/`VarLabel`, `RecFieldList`), `compiler/src/SymTab.def`/`.mod` (`IsOrdinal`, `SetVariantTag`, `MarkVariant`, `IsVariant`, `ResetFields`, `ComputeOffsets`, `TypeSizeD`), `compiler/src/compiler.frm` (message 236 `bad variant record`), `compiler/tests/t_variant.mod`, `compiler/run_tests.sh`, `docs/features.md`.