wcc+w6c+w6c_ww: insert() builtin — single-element slice insertion (part of #35)
Hare's insert(xs[idx], v) (ref/harec/src/check.c:745 check_expr_append_insert — append/insert share the checker arm, "insert" at :786): checker accepts an INDEX place over a slice plus one value, stamps void; idx == len is a legal end-insert (the ref/hare os/exec/platform_cmd.ha:86 idiom). Loud-rejects with exact texts: spread form insert(xs[i], vs...) (filed, #35 — also covers harec's with-length form via the arity check), range place (not Hare; harec only parses ACCESS_INDEX, :784), non-index operands, array bases, wrong arity. delete()-parity throughout. Lowering (both stages, converged byte-identical by construction) is a DESUGAR: append(xs, v) — reusing append's grow (rt_ensure) and the entire #34 value-store dispatch (scalar / str-slice header / tagged widen / struct fill) verbatim, one boxing choke-point — lands v at slot len-1; then a rotate-right of [idx, len) moves it home through a fresh per-site esz frame scratch (@insscr). The rotate is delete's shift loop in reverse (descending j, the safe memmove-up direction) and is a same-slice whole-stride raw byte move — no boxing exists for any element kind. idx evaluates BEFORE the grow (Hare's left-to-right operand order — pinned by the pregrow_len_idx row, insert(xs[len(xs)-1], v): pre-grow [7,13,11] vs post-grow [7,11,13]; an idx==len(xs) end-insert cannot discriminate, the rotate degenerates either way). Base shapes: local slice ident (LEAQ) and deref-of-local ptr-to-slice (MOVQ); others rule-7 loud-stop, like delete. test/807: 57 fixtures — front/middle/end + idx==len via len(xs) + the pre-grow eval-order pin, esz 1/2/4/8/16/24/56 (MOVB/MOVW/MOVL tails, struct body, str header, 7-qword tagged from a typed local [the regex fold-3 ha:347 newinst shape] and from a cast rvalue [ha:419/441]), empty-slice grow, (*p)[i] deref base, front-insert loop, 6 checker reject rows with diagnostic-text checks; every accept row cs==ww asm byte-id.
This commit is contained in:
@@ -1436,7 +1436,7 @@ cexpr(Checker *c, Node *n)
|
||||
return n->type;
|
||||
}
|
||||
/* delete(xs[i]) — single-element slice removal, the
|
||||
* delete-half of #35 (insert() stays deferred). harec
|
||||
* delete-half of #35 (insert() is the twin arm below). 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);
|
||||
@@ -1466,6 +1466,50 @@ cexpr(Checker *c, Node *n)
|
||||
n->lhs->type = ty_err;
|
||||
return n->type;
|
||||
}
|
||||
/* insert(xs[idx], v) — single-element slice insertion
|
||||
* before idx, delete()'s twin (the insert-half of #35).
|
||||
* harec models append/insert in ONE checker arm
|
||||
* (ref/harec/src/check.c:745 check_expr_append_insert;
|
||||
* "insert" at :786): operand 1 must be an indexing place
|
||||
* over a slice; idx == len is a legal end-insert (the
|
||||
* ref/hare os/exec platform_cmd.ha:86 idiom). The spread
|
||||
* form insert(xs[i], vs...) and the with-length form
|
||||
* (harec :821/:837) stay filed on #35 — regex fold-3's
|
||||
* consumers are all single-value. A range PLACE is not
|
||||
* Hare (harec asserts ACCESS_INDEX at :784; the form
|
||||
* never parses there) — rejected, no task cite. */
|
||||
if (n->lhs && n->lhs->kind == N_IDENT &&
|
||||
n->lhs->str && strcmp(n->lhs->str, "insert") == 0) {
|
||||
Node *d = n->list;
|
||||
if (d == NULL || d->next == NULL ||
|
||||
d->next->next != NULL)
|
||||
err(c, n->pos, "insert: takes exactly two arguments");
|
||||
if (d != NULL) {
|
||||
(void)cexpr(c, d);
|
||||
if (d->kind == N_SLICE)
|
||||
err(c, n->pos, "insert: range place is invalid; operand must be an indexing expression xs[i]");
|
||||
else if (d->kind != N_INDEX)
|
||||
err(c, n->pos, "insert: 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:807 wording; a
|
||||
* fixed-size [N]T base lands here. */
|
||||
if (bt == NULL || bt->kind != TY_SLICE)
|
||||
err(c, n->pos, "insert must operate on a slice");
|
||||
}
|
||||
if (d->next != NULL) {
|
||||
if (d->next->kind == N_SPREAD)
|
||||
err(c, n->pos, "insert: spread form insert(xs[i], vs...) unimplemented (task #35)");
|
||||
else
|
||||
(void)cexpr(c, d->next);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user