wcc+w6c+w6c_ww: delete() builtin — single-element slice removal (part of #35)

Hare's delete(xs[i]) (ref/harec/src/check.c:1981-2027): checker accepts
an N_INDEX over a slice-typed base, stamps void; loud-rejects the range
form delete(xs[i..j]) (stays filed on #35 — regex fold-2b's consumers
are all single-element), non-index operands, array bases, wrong arity.

Lowering (both stages, converged byte-identical by construction):
ascending word-copy loop shifts [i+1..len) down one esz stride, then
hdr.len -= 1; cap unchanged. The move is a same-type whole-stride byte
copy — src and dst are elements of the SAME slice, so no boxing exists
for any element kind; one loop serves scalar/narrow/str/struct/tagged.
esz off the STAMPED base type (#34/#48 discipline). Base shapes: local
slice ident (LEAQ) and deref-of-local ptr-to-slice (MOVQ — the fold-2b
delete_thread shape); others rule-7 loud-stop.

test/804: 38 fixtures — first/middle/last/to-empty, esz 1/4/8/24/56
(MOVB/MOVL tails + 7-qword tagged), cap-unchanged, (*threads)[i], 4
checker reject rows; every accept row cs==ww asm byte-id.
This commit is contained in:
2026-06-04 06:41:12 +09:00
parent e93be8495a
commit 37febab9d5
8 changed files with 1120 additions and 6 deletions

View File

@@ -1435,6 +1435,37 @@ cexpr(Checker *c, Node *n)
n->lhs->type = ty_err;
return n->type;
}
/* delete(xs[i]) — single-element slice removal, the
* delete-half of #35 (insert() stays deferred). harec
* ref/harec/src/check.c:1981-2027 also accepts the range
* form delete(xs[i..j]) (EXPR_SLICE) — out of scope here
* (regex fold-2b's consumers are all single-element);
* loud-rejected below, the range form stays filed on #35. */
if (n->lhs && n->lhs->kind == N_IDENT &&
n->lhs->str && strcmp(n->lhs->str, "delete") == 0) {
Node *d = n->list;
if (d == NULL || d->next != NULL)
err(c, n->pos, "delete: takes exactly one argument");
if (d != NULL) {
(void)cexpr(c, d);
if (d->kind == N_SLICE)
err(c, n->pos, "delete: range form delete(xs[i..j]) unimplemented (task #35)");
else if (d->kind != N_INDEX)
err(c, n->pos, "delete: operand must be an indexing expression xs[i]");
else {
Type *bt = d->lhs ? d->lhs->type : NULL;
while (bt && bt->kind == TY_NAMED)
bt = bt->under;
/* harec check.c:2024 wording; a
* fixed-size [N]T base lands here. */
if (bt == NULL || bt->kind != TY_SLICE)
err(c, n->pos, "delete must operate on a slice");
}
}
n->type = ty_void;
n->lhs->type = ty_err;
return n->type;
}
/* assert(cond[, msg]) / abort([msg]) — runtime checks that
* call into rt_abort. msg must be a str when present.
* Only treated as builtins when no user symbol shadows the