wcc/check: GAP-A .cap-on-array loud-reject; .ptr-on-array ratified valid (#12)

.cap on a fixed-size array is invalid (Hare has no capacity-read; arrays
can't grow) -> both stages now loud-reject at the checker. wwstage was
silently returning frame garbage for a local array's .cap; cstage typed
it then vaguely rejected at use. Unified to one early checker reject with
an identical diagnostic both stages.

.ptr on a fixed-size array is ratified VALID: array.ptr is &A[0], a
sanctioned ww spelling divergence from Hare; see task #13. The toolchain
already relies on it in 14 backing-pointer sites. WHY-doc added at both
checker .ptr-on-array sites. The def-global .ptr cgen base-selection bug
(#11) is a separate following commit.

Valid-program asm unchanged (byte-id 990-997 8/8); w6c/w6c_ww binaries
move (checker code changed). test/wcc/817 table-driven, model 684.
This commit is contained in:
2026-06-08 17:22:09 +09:00
parent 7b0e09e065
commit 1c87881bda
6 changed files with 373 additions and 0 deletions

View File

@@ -1361,7 +1361,20 @@ cexpr(Checker *c, Node *n)
if (u && (u->kind == TY_SLICE || u->kind == TY_ARRAY ||
u->kind == TY_STR)) {
if (strcmp(n->str, "len") == 0) return n->type = ty_i32;
/* A fixed array has no capacity word — .cap is invalid
* (drew ruling; arrays expose .len + .ptr only). Pre-fix
* cstage typed it i32 → cgen vague-rejected; wwstage
* link-errored / read garbage. Reject loud + early. */
if (u->kind == TY_ARRAY && strcmp(n->str, "cap") == 0)
return n->type = err(c, n->pos,
"no field 'cap' on a fixed-size array "
"(arrays have no capacity; use .len)");
if (strcmp(n->str, "cap") == 0) return n->type = ty_i32;
/* rule-9 divergence-doc (drew, task #13): `array.ptr` is a
* sanctioned ww spelling for `&A[0]` — a faithful Hare
* desugaring (arrays expose .len + .ptr; not .cap). 14 live
* consumers (lib/ww + cmd/wcc/cgen.ww). See
* .ai/drew-gapa-ptr-ruling.md. */
if (strcmp(n->str, "ptr") == 0) {
Type *elem = (u->kind == TY_STR) ? ty_u8 : u->sub;
return n->type = type_ptr(c->a, elem);