ww+wcc: Hare-strict enum types — back out the int↔enum relaxation
Cascades the four enum kinds through every signature and local that
holds one of their values, then removes the type_assignable /
unify_arith relaxation that previously let bare i32 mix with the
named enum types.
Signature updates:
- kwlookup() now returns `tkind` (not i32); tokname() takes `tkind`
- accepttok / expecttok / bprec / isassignop take `tkind`
- parsearglist's closekind is `tkind`
- newtype / prim take `tykind`; scopedefine takes `skind`
- newnode / nkname take `nkind`
Struct fields:
- tok.kind is `tkind`; parser.curkind is `tkind`
- node.kind is `nkind`; node.op is `tkind`
- tinfo.kind is `tykind`; sym.skind is `skind`
Locals holding kinds across lex/parse/check/cgen are now typed with
their enum, including sentinel patterns like `let lkind: nkind =
nkind.N_NONE; if (...) lkind = tn.kind;`.
The selfhost cgen had a load-width bug exposed by this: fieldsize()
fell back to 8 bytes for any TNAME that wasn't a struct or primitive.
For a tkind-typed field that gave `MOVQ (BX), AX` instead of `MOVL`,
diverging from the C cgen on tok.kind / parser.curkind / etc. Two
fixes:
- fieldsize now consults the enum registry and returns the storage
type's size (4 for `enum i32`)
- collectenums runs before collectstructs in cgfile so the registry
is populated when registerstruct asks for field sizes
All 22 tests stay green; 990/993/995 byte-identity probes pass with
the strict typing in place.
This commit is contained in:
@@ -199,7 +199,7 @@ fn parseprimary(p: *parser) *node = {
|
||||
return newnode(p.a, nkind.N_NONE, pf, pl, pc);
|
||||
};
|
||||
|
||||
fn parsearglist(p: *parser, closekind: i32, headout: **node) void = {
|
||||
fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = {
|
||||
*headout = nil;
|
||||
if (p.curkind == closekind) { return; };
|
||||
let head: *node = nil;
|
||||
@@ -355,7 +355,7 @@ fn parseunary(p: *parser) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
let k: i32 = p.curkind;
|
||||
let k: tkind = p.curkind;
|
||||
if (k == tkind.TK_MINUS) {
|
||||
advance(p);
|
||||
let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc);
|
||||
@@ -398,7 +398,7 @@ fn parseunary(p: *parser) *node = {
|
||||
fn parsebin(p: *parser, lhs: *node, minp: i32) *node = {
|
||||
let cur: *node = lhs;
|
||||
for (true) {
|
||||
let op: i32 = p.curkind;
|
||||
let op: tkind = p.curkind;
|
||||
let pr: i32 = bprec(op);
|
||||
if (pr == 0) { return cur; };
|
||||
if (pr < minp) { return cur; };
|
||||
@@ -425,7 +425,7 @@ fn parseexpr(p: *parser) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
let op: i32 = p.curkind;
|
||||
let op: tkind = p.curkind;
|
||||
advance(p);
|
||||
let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc);
|
||||
n.op = op;
|
||||
|
||||
@@ -24,7 +24,7 @@ type parser = struct {
|
||||
// nocast: while inside `[...]` we treat ':' as the slice
|
||||
// separator, not the cast operator. Mirrors parse.c's flag.
|
||||
nocast: i32,
|
||||
curkind: i32, // holds a `tkind` value (relaxation lets it mix)
|
||||
curkind: tkind,
|
||||
curfile: str,
|
||||
curline: i32,
|
||||
curcol: i32,
|
||||
@@ -53,7 +53,7 @@ export fn parserinit(p: *parser, a: *arena, l: *lex) void = {
|
||||
|
||||
fn advance(p: *parser) void = { refill(p); };
|
||||
|
||||
fn accepttok(p: *parser, k: i32) bool = {
|
||||
fn accepttok(p: *parser, k: tkind) bool = {
|
||||
if (p.curkind == k) { advance(p); return true; };
|
||||
return false;
|
||||
};
|
||||
@@ -66,7 +66,7 @@ fn errmsg(p: *parser, msg: str) void = {
|
||||
p.errs += 1;
|
||||
};
|
||||
|
||||
fn expecttok(p: *parser, k: i32, what: str) bool = {
|
||||
fn expecttok(p: *parser, k: tkind, what: str) bool = {
|
||||
if (p.curkind == k) { advance(p); return true; };
|
||||
errmsg(p, what);
|
||||
return false;
|
||||
@@ -313,7 +313,7 @@ fn parsetype(p: *parser) *node = {
|
||||
// and the ?/! try operators are not yet wired — they'll arrive as the
|
||||
// AST diff fixture grows to need them.
|
||||
|
||||
fn bprec(k: i32) i32 = {
|
||||
fn bprec(k: tkind) i32 = {
|
||||
if (k == tkind.TK_OR) { return 1; };
|
||||
if (k == tkind.TK_AND) { return 2; };
|
||||
if (k == tkind.TK_EQ) { return 3; };
|
||||
@@ -335,7 +335,7 @@ fn bprec(k: i32) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
fn isassignop(k: i32) bool = {
|
||||
fn isassignop(k: tkind) bool = {
|
||||
if (k == tkind.TK_ASSIGN) { return true; };
|
||||
if (k == tkind.TK_PLUSEQ) { return true; };
|
||||
if (k == tkind.TK_MINUSEQ) { return true; };
|
||||
|
||||
Reference in New Issue
Block a user