wcc: Hare-style enum [storage] { ... } type

`type Foo = enum [intT] { NAME [= expr], ... };`. Storage defaults
to i32; members auto-increment from 0 (or last+1) when `= expr` is
omitted, and value expressions can reference earlier siblings —
enough surface for io::mode-style flag enums (`RDWR = READ | WRITE`).

`Foo.MEMBER` folds to an N_INTLIT in the checker, typed as the
named enum. Binops on enum values yield the same enum (type_eq on
the named pointer), so `mode.R | mode.W` is a `mode`. Enum ↔ int
is a reinterpret-only `as` cast — same register, no tag wrap — so
`mode.RDWR as i32` and `1 as mode` both work without runtime ops.

`is`/`?`/`!` are still tagged-union-only. CSP runtime (chan/proc)
is unchanged; only the type-system slot is touched here.
This commit is contained in:
2026-05-12 04:15:31 +09:00
parent 22999cd3fa
commit 34817eedcd
10 changed files with 257 additions and 1 deletions

View File

@@ -86,6 +86,8 @@ nkname(Nkind k)
case N_VOIDLIT: return "voidlit";
case N_TBANG: return "tbang";
case N_YIELD: return "yield";
case N_TENUM: return "tenum";
case N_TENUMMEMBER: return "tenummember";
case N_LAST: return "last";
}
return "?";
@@ -158,6 +160,7 @@ pr(FILE *f, Node *n, int d)
case N_LET:
case N_TNAME:
case N_TFIELD:
case N_TENUMMEMBER:
case N_FIELD:
case N_ATTR:
if (n->str) { fputc(' ', f); printq(f, n->str); }