unions (untagged)
This commit is contained in:
@@ -402,7 +402,48 @@
|
||||
loop) whose concrete yield references a local declared *past* the first yield (annotate);
|
||||
same-label loop/block shadowing resolves innermost-wins
|
||||
|
||||
21. unions and tagged unions
|
||||
21. unions and tagged unions (implemented; first pass — native untagged unions only; see below)
|
||||
- inspired by zig
|
||||
- ```
|
||||
# unions (untagged; named fields like a struct — Zig union members are always named)
|
||||
SomeStuff :: union {
|
||||
f float
|
||||
i int
|
||||
a Animal
|
||||
}
|
||||
|
||||
# tagged unions (constrained to the backing enum) — DEFERRED to 21.5
|
||||
AnimalNameOrHeight :: union(Animal) { # use just `enum` instead of `Animal` for unconstrained tagged union
|
||||
dog []u8
|
||||
cat []u8
|
||||
bird int
|
||||
lizard int
|
||||
}
|
||||
```
|
||||
- this first pass ships **native untagged unions with named fields**. an untagged union is a
|
||||
carrier sized to its largest/most-aligned member with no runtime tag (a C union); reading a
|
||||
non-active field reinterprets the bytes (unsafe, like a Zig `union {}` in ReleaseFast) and an
|
||||
untagged union is not matchable. the TODO's original bare type-only spelling
|
||||
(`union { float, int, Animal }`) was dropped in favor of named fields to match Zig and to
|
||||
reuse the existing field-access path
|
||||
- the entire untagged-union backend already existed from the C-interop work (milestone 4): the
|
||||
`.Union` type kind, carrier-based LLVM layout (`emit_types`), `size`/`alignment`, keyed-literal
|
||||
construction `Val{ field = value }` (exactly one initializer; the active-field index rides in
|
||||
`hir.Expr.integer`), and field access (GEP-at-offset-0 reinterpret). none of these are gated on
|
||||
`c_layout`, so a *native* union flows through them unchanged. record-declaration validation
|
||||
(`is_runtime_value` per field) already covers native unions too
|
||||
- the change is front-end only: a new `union` keyword (token/lexer), and `parse_union` is just
|
||||
`parse_struct` parametrized with `is_union=true` routing through `types.define_record`
|
||||
(native-only, so `c_layout=false` and the no-body case errors). no `types`/`checker`/`hir`/
|
||||
`lower`/`llvm` change (mirrors the minimal-footprint slices of 18/19/20)
|
||||
- deferred to **21.5**: tagged unions (`union(Enum)` constrained + `union(enum)` inferred) with a
|
||||
runtime `{tag, payload}` layout, tag init at construction, and tag extraction — the real codegen
|
||||
work and the foundation for milestone 22 (`match` with payload unwrapping)
|
||||
|
||||
21.5. tagged unions with a runtime tag (DEFERRED)
|
||||
- `union(Enum)` (variant names constrained to the backing enum's members) and `union(enum)`
|
||||
(auto-generated tag, one member per variant); both store an enum tag beside the payload
|
||||
(`{tag, payload}`), switchable in milestone 22
|
||||
|
||||
22. match statements with tagged unions payload unwrapping
|
||||
|
||||
|
||||
Reference in New Issue
Block a user