selfhost/cmd/wcc/check+test: fold size(T)/align(T)/offset(e.f) at check time
Mirror cstage cmd/wcc/check.c:907-960. Three typed-builtin intercepts that cstage already had: - size(T) — folds to a literal integer at check time from a newly-introduced astsize walker over the type AST. Mirrors the size computation in cstage resolve_type at check.c:286-528. - align(T) — same, via astalign. - offset(e.f) — folds the byte offset of field f in e's struct type via astoffset. Peels exactly one N_TPTR for `p.field`. seedprimitives registers the three names as SK_FN nil; exprtype's N_CALL arm gates on a same-module shadow check (per #23 alloc precedent) and consumes the parser-planted type-expression arg. The fold is in-place — foldtointlit mutates N_CALL into N_INTLIT so cgen sees a plain integer. resolvewalk's N_CALL trigger invokes exprtype so the fold fires from non-let contexts too (e.g. inside `if (size(T) != …)`). selfhost/test/smoke.ww gains a probe-8 block: size/align/offset assertions across str, primitive widths, ptrs, slices, and two structs (`point`, `mixalign`) covering both no-padding and i8+i64 natural-align padding cases. Known divergences NOT in #42 scope: - size((*T|void)) ≠ 8 on the cstage nullable-ptr fold (#13 family, unreachable through current grammar). - 8B-struct bare-let zero-init wwstage skip vs cstage emit (#59). - Same-module shadow gate added here, cstage has none — sibling shape to #26 (free/append/len gates). Closes the original chain that started with the user's call to fix the structural debt — six precondition fixes (#51, #52, #53, #55, #56, #50) landed before this fold could safely live in the check pass. Unblocks #43 (sweep literal 16s → size(str)) and #1 (str → 24B becomes one line).
This commit is contained in:
@@ -3287,6 +3287,20 @@ fn count_emit(ctx: *void, b: u8) void = {
|
||||
c.n += 1;
|
||||
};
|
||||
|
||||
// --- size/align/offset typed-builtin fixtures (#42) --------------------
|
||||
|
||||
type point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
// Mixed-alignment struct: i8 lays at 0, then i64 needs to skip to
|
||||
// offset 8 (the i64's natural align). Probe asserts both ends.
|
||||
type mixalign = struct {
|
||||
tag: i8,
|
||||
val: i64,
|
||||
};
|
||||
|
||||
// --- byte scanner like lex.ww's hot path -------------------------------
|
||||
|
||||
fn count_digits(s: str) i32 = {
|
||||
@@ -3380,6 +3394,33 @@ export fn main() i32 = {
|
||||
os.close(fd);
|
||||
if (n <= 0i64) { return 22; };
|
||||
|
||||
// Probe 8 — size(T) / align(T) / offset(e.f) typed-builtin folds
|
||||
// (#42). Each call folds to an N_INTLIT at check time; cgen
|
||||
// materialises the literal as a plain `MOVQ $N, AX`. Mirrors
|
||||
// cstage cmd/wcc/check.c:907-960 byte-for-byte on this corpus.
|
||||
if (size(str) != 16) { return 23; };
|
||||
if (size(i64) != 8) { return 24; };
|
||||
if (size(i32) != 4) { return 25; };
|
||||
if (align(i64) != 8) { return 26; };
|
||||
if (align(i32) != 4) { return 27; };
|
||||
// Initialize struct locals explicitly so the cgen path doesn't
|
||||
// drift from cstage on bare `let X: T;` zero-init (pre-existing
|
||||
// wwstage divergence outside #42).
|
||||
let pt: point = point { x = 0, y = 0 };
|
||||
if (offset(pt.x) != 0) { return 28; };
|
||||
if (offset(pt.y) != 4) { return 29; };
|
||||
let mx: mixalign = mixalign { tag = 0i8, val = 0i64 };
|
||||
if (offset(mx.tag) != 0) { return 30; };
|
||||
if (offset(mx.val) != 8) { return 31; }; // align-padded to 8
|
||||
// Width breadth: smallest prim, ptr, slice, struct (8B + padded),
|
||||
// covering astsize's TPTR/TSLICE/TNAME-resolve-to-struct arms.
|
||||
if (size(i8) != 1) { return 32; };
|
||||
if (align(i8) != 1) { return 33; };
|
||||
if (size(*i32) != 8) { return 34; };
|
||||
if (size([]i32) != 24) { return 35; };
|
||||
if (size(point) != 8) { return 36; };
|
||||
if (size(mixalign) != 16) { return 37; };
|
||||
|
||||
return 42;
|
||||
};
|
||||
|
||||
|
||||
@@ -74,6 +74,20 @@ fn count_emit(ctx: *void, b: u8) void = {
|
||||
c.n += 1;
|
||||
};
|
||||
|
||||
// --- size/align/offset typed-builtin fixtures (#42) --------------------
|
||||
|
||||
type point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
// Mixed-alignment struct: i8 lays at 0, then i64 needs to skip to
|
||||
// offset 8 (the i64's natural align). Probe asserts both ends.
|
||||
type mixalign = struct {
|
||||
tag: i8,
|
||||
val: i64,
|
||||
};
|
||||
|
||||
// --- byte scanner like lex.ww's hot path -------------------------------
|
||||
|
||||
fn count_digits(s: str) i32 = {
|
||||
@@ -167,5 +181,32 @@ export fn main() i32 = {
|
||||
os.close(fd);
|
||||
if (n <= 0i64) { return 22; };
|
||||
|
||||
// Probe 8 — size(T) / align(T) / offset(e.f) typed-builtin folds
|
||||
// (#42). Each call folds to an N_INTLIT at check time; cgen
|
||||
// materialises the literal as a plain `MOVQ $N, AX`. Mirrors
|
||||
// cstage cmd/wcc/check.c:907-960 byte-for-byte on this corpus.
|
||||
if (size(str) != 16) { return 23; };
|
||||
if (size(i64) != 8) { return 24; };
|
||||
if (size(i32) != 4) { return 25; };
|
||||
if (align(i64) != 8) { return 26; };
|
||||
if (align(i32) != 4) { return 27; };
|
||||
// Initialize struct locals explicitly so the cgen path doesn't
|
||||
// drift from cstage on bare `let X: T;` zero-init (pre-existing
|
||||
// wwstage divergence outside #42).
|
||||
let pt: point = point { x = 0, y = 0 };
|
||||
if (offset(pt.x) != 0) { return 28; };
|
||||
if (offset(pt.y) != 4) { return 29; };
|
||||
let mx: mixalign = mixalign { tag = 0i8, val = 0i64 };
|
||||
if (offset(mx.tag) != 0) { return 30; };
|
||||
if (offset(mx.val) != 8) { return 31; }; // align-padded to 8
|
||||
// Width breadth: smallest prim, ptr, slice, struct (8B + padded),
|
||||
// covering astsize's TPTR/TSLICE/TNAME-resolve-to-struct arms.
|
||||
if (size(i8) != 1) { return 32; };
|
||||
if (align(i8) != 1) { return 33; };
|
||||
if (size(*i32) != 8) { return 34; };
|
||||
if (size([]i32) != 24) { return 35; };
|
||||
if (size(point) != 8) { return 36; };
|
||||
if (size(mixalign) != 16) { return 37; };
|
||||
|
||||
return 42;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user