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:
@@ -2175,6 +2175,16 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
Type *st = s ? s->type : NULL;
|
||||
Type *u = (st && st->kind == TY_NAMED) ? st->under : st;
|
||||
Type *vt = n->type;
|
||||
/* Enum ↔ integer: reinterpret-only. The value already lives
|
||||
* in AX after evaluating the LHS; no tag/unwrap needed. */
|
||||
{
|
||||
Type *vu = (vt && vt->kind == TY_NAMED) ? vt->under : vt;
|
||||
if ((u && u->kind == TY_ENUM) ||
|
||||
(vu && vu->kind == TY_ENUM)) {
|
||||
cgexpr(c, s, locals);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int slot_size = (u && u->kind == TY_TAGGED) ? (int)u->size : 16;
|
||||
int sl_off = 0;
|
||||
if (s && s->kind == N_IDENT && s->str) {
|
||||
|
||||
Reference in New Issue
Block a user