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:
@@ -22,7 +22,7 @@ use strconv;
|
||||
|
||||
fn cgexpr(c: *cgen, n: *node) void = {
|
||||
if (n == nil) { return; };
|
||||
let k: i32 = n.kind;
|
||||
let k: nkind = n.kind;
|
||||
|
||||
if (k == nkind.N_INTLIT) {
|
||||
// Print signed (i64), not unsigned (u64). C cgen uses
|
||||
@@ -257,7 +257,7 @@ fn cgtypetest(c: *cgen, n: *node) void = {
|
||||
// through the cast pass-through too).
|
||||
fn isenumexpr(c: *cgen, e: *node) bool = {
|
||||
if (e == nil) { return false; };
|
||||
let k: i32 = e.kind;
|
||||
let k: nkind = e.kind;
|
||||
if (k == nkind.N_DOT) {
|
||||
if (e.lhs != nil) {
|
||||
if (e.lhs.kind == nkind.N_IDENT) {
|
||||
@@ -650,7 +650,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
let lc: *local = localfindnode(c, nm);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
let lkind: i32 = -1;
|
||||
let lkind: nkind = nkind.N_NONE;
|
||||
if (tn != nil) { lkind = tn.kind; };
|
||||
// Pointer-to-struct: deref then field load.
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
@@ -807,7 +807,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// pointed-to header. C cgen does the same.
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
let inner: *node = tn.lhs;
|
||||
let innerkind: i32 = -1;
|
||||
let innerkind: nkind = nkind.N_NONE;
|
||||
if (inner != nil) { innerkind = inner.kind; };
|
||||
let innerstr: bool = false;
|
||||
if (innerkind == nkind.N_TNAME) {
|
||||
@@ -1071,7 +1071,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
let lkind: i32 = tn.kind;
|
||||
let lkind: nkind = tn.kind;
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (lkind == nkind.N_TNAME) { sname = tn.str; };
|
||||
@@ -1291,7 +1291,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
let lc: *local = localfindnode(c, bn);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
let lkind: i32 = -1;
|
||||
let lkind: nkind = nkind.N_NONE;
|
||||
if (tn != nil) { lkind = tn.kind; };
|
||||
// Pointer-to-struct: deref then store.
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
@@ -1397,7 +1397,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (delta >= 0) {
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
let inner: *node = tn.lhs;
|
||||
let innerkind: i32 = -1;
|
||||
let innerkind: nkind = nkind.N_NONE;
|
||||
if (inner != nil) { innerkind = inner.kind; };
|
||||
let innerstr: bool = false;
|
||||
if (innerkind == nkind.N_TNAME) {
|
||||
|
||||
Reference in New Issue
Block a user