selfhost/cmd/wcc: collapse type-kind predicates onto n.type_ (A.6.3b, #46)
The node-keyed kind helpers (typeis8byteprimitive, isstrtype/raw,
isslicetype/raw, istaggedtype/raw, isfloattype, isf32type/raw,
isf64typeraw, isnullabletype) each re-walked TNAME aliases via
aliaslookup and peeled TBANG by hand — duplicating cstage's single-
peel kind predicates at the AST level. After A.6.2 every type-AST
kind these read is tinfo-stamped at check.ww L426-436, and
tinfofornode collapses N_TBANG (check.ww:1145-1152) and the TY_NAMED
chain, so each predicate folds to one tinfo read.
Six new tinfo helpers in lib/ww/typ.ww mirror their cstage SSoT
verbatim:
typeisstr — cstage cgen.c:159 `type_isstr` (TY_STR / TY_UNTYPED_STR)
typeisslice — cstage cgen.c:174 `type_isslice`
typeistagged — cstage cgen.c:516 `type_istagged`
typeisf32 — cstage cgen.c:188 `type_isf32`
typeisnullable — cstage cgen.c:396 `type_isnullable` (reads tinfo.nullable
stamped at check.ww:1309-1318)
typeis8byteprim — cstage cgen.c N_LET sz==8 ladder (slot-pad set)
Rule 9 carve-out per the A.6.3a precedent: each helper has a named
cstage counterpart; the wwstage shape mirrors it directly. The five
dead AST-walking variants (isstrtyperaw, isslicetyperaw,
istaggedtyperaw, isf32typeraw, isf64typeraw) are deleted; the five
remaining callsites (cgenstmt cglet / cgmlet str-routing, cgenexpr
cgdot tuple-field) graduate to the alias-aware isstrtype(c, t).
nullableptrtag stays AST-keyed for now — tinfofornode doesn't
populate TY_TAGGED.params (check.ww:1287-1337 sets size / align /
nullable but not the variant chain), so the tinfo equivalent of
cstage cgen.c:405 `nullable_ptr_tag` can't read params today. WHY
comment at the site cites #50 / A.6.3f as the graduation point,
alongside the variant-index work and the tparam-population glue.
Byte-identity (994/995) is the behavior gate; full `make test` green
at 133/133 confirms.
This commit is contained in:
@@ -336,6 +336,94 @@ export fn typeissigned(t: *tinfo) bool = {
|
||||
return typeisint(t);
|
||||
};
|
||||
|
||||
// typeisstr — TY_STR (and TY_UNTYPED_STR for literals pre-default).
|
||||
// Cite cstage cgen.c:159 `type_isstr` — single TY_NAMED peel, accepts
|
||||
// the same untyped form. ww walks the .under chain so alias-of-alias
|
||||
// (`type s2 = s1; type s1 = str;`) lands the same way.
|
||||
export fn typeisstr(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_STR) { return true; };
|
||||
if (k == tykind.TY_UNTYPED_STR) { return true; };
|
||||
if (k == tykind.TY_NAMED) { return typeisstr(t.under); };
|
||||
return false;
|
||||
};
|
||||
|
||||
// typeisslice — TY_SLICE. Cite cstage cgen.c:174 `type_isslice`.
|
||||
export fn typeisslice(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_SLICE) { return true; };
|
||||
if (k == tykind.TY_NAMED) { return typeisslice(t.under); };
|
||||
return false;
|
||||
};
|
||||
|
||||
// typeistagged — TY_TAGGED (alias-aware). Cite cstage cgen.c:516
|
||||
// `type_istagged` — same single-peel shape. The node-keyed wwstage
|
||||
// helper this replaces also unwrapped a leading N_TBANG so
|
||||
// `type error = !(invalid | overflow);` registered as tagged. Post-
|
||||
// A.6.2 the TBANG unwrap is handled by tinfofornode (check.ww:1145-
|
||||
// 1152 returns the inner tinfo unchanged) so we recover the cstage
|
||||
// semantics with the bare kind check + NAMED chase.
|
||||
export fn typeistagged(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_TAGGED) { return true; };
|
||||
if (k == tykind.TY_NAMED) { return typeistagged(t.under); };
|
||||
return false;
|
||||
};
|
||||
|
||||
// typeisf32 — narrower-than-typeisfloat: only TY_F32 (after alias
|
||||
// chase). Cite cstage cgen.c:188 `type_isf32`. Used to pick MOVSS vs
|
||||
// MOVSD and the SS-variant arithmetic / cast opcodes.
|
||||
export fn typeisf32(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_F32) { return true; };
|
||||
if (k == tykind.TY_NAMED) { return typeisf32(t.under); };
|
||||
return false;
|
||||
};
|
||||
|
||||
// typeisnullable — TY_TAGGED with the `(*T | void)` one-word fold.
|
||||
// Cite cstage cgen.c:396 `type_isnullable`. The .nullable flag is
|
||||
// stamped by tinfofornode (check.ww:1309-1318) when the two-variant
|
||||
// shape matches.
|
||||
export fn typeisnullable(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_TAGGED) { return t.nullable != 0; };
|
||||
if (k == tykind.TY_NAMED) { return typeisnullable(t.under); };
|
||||
return false;
|
||||
};
|
||||
|
||||
// typeis8byteprim — does this type take exactly one 8-byte stack
|
||||
// slot (ptr / fn / chan / 64-bit int / scalar primitive padded up to
|
||||
// 8 / `[N]T` whose natural width is 8) rather than a wider aggregate?
|
||||
// Mirrors the ladder cstage's cgen.c N_LET zero-init takes on `sz==8`
|
||||
// (cmd/wcc/check.c sizing + cgen.c N_LET). The node-keyed wwstage
|
||||
// helper this replaces predates tinfo and AST-walked TBANG / TNAME
|
||||
// alias chains; tinfofornode now collapses TBANG (check.ww:1145) and
|
||||
// TY_NAMED.under carries the chain, so the tinfo walk handles every
|
||||
// shape the AST walker did.
|
||||
export fn typeis8byteprim(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
if (k == tykind.TY_PTR) { return true; };
|
||||
if (k == tykind.TY_FN) { return true; };
|
||||
if (k == tykind.TY_CHAN) { return true; };
|
||||
if (k == tykind.TY_SLICE) { return false; };
|
||||
if (k == tykind.TY_TUPLE) { return false; };
|
||||
if (k == tykind.TY_TAGGED) { return false; };
|
||||
if (k == tykind.TY_STR) { return false; };
|
||||
if (k == tykind.TY_STRUCT) { return false; };
|
||||
if (k == tykind.TY_ARRAY) { return t.size == 8u64; };
|
||||
if (k == tykind.TY_NAMED) { return typeis8byteprim(t.under); };
|
||||
// Remaining: primitives (i8/u8/.../i64/u64/bool/rune/f32/f64/
|
||||
// int/uint/uintptr) and TY_VOID. All slot-pad to 8 and zero-init
|
||||
// in cstage's `sz==8` branch.
|
||||
return true;
|
||||
};
|
||||
|
||||
export fn typeisuntyped(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
|
||||
Reference in New Issue
Block a user