cgen: sub-slice cap = base_cap - lo
A sub-slice `base[lo:hi]` now sets cap to base_cap - lo (the storage remaining to the underlying end; Go/Hare-identical) instead of hi - lo (== len). base_cap is the array length N for [N]T, or the .capacity word carried in a slice/str header at +16. Authored once per stage in the cg_base_cap / cgbasecap helper, applied at both cap sites: the N_SLICE value path (which serves let-init since the prior commit) and the call-arg push. Both stages stay byte-identical (find-4 closed). cap arithmetic per ref/harec/src/eval.c:1017 (slice: slice.cap -= start) and eval.c:1024 (array: cap = array.length - start); capacity is a distinct field per ref/hare/rt/ensure.ha:4-8 and cap >= len per ref/harec/src/check.c:596. Only the cap arithmetic transfers: the ptr stays unscaled (lo*esz is #76) and eval.c's stricter start>=end bound is not ported (ww's runtime bound is start>end). str[lo:hi] yields str with a real .capacity (D1), so the str base uses the same +16 load -- no downgrade to []u8. base_cap falls back to len (prior behavior) where it isn't cleanly available: a non-ident base (its header cap was discarded by cgexpr; len is likewise wrong for a defaulted hi there, pre-existing) and a global str base (wwstage cgslice has no global-str load, #73 -- the carve-out keeps both stages byte-identical). Test: 942_subslice_cap_run, table-driven over both drivers, array / slice / str base + an append-no-realloc row, each shape chosen so base_cap-lo != hi-lo. Fold in three pre-existing fixtures that asserted the old cap == len and so failed under the corrected semantics (project #20): 681_arr_elem_field_write (slice_field_value_write, slice_field_ptr_write, slice_field_distinct_bytes), 693_dot_tagged_source (local_struct_slice_variant, via_ptr_slice_variant, letinit_slice_roundtrip, top_level_global_slice), and 695_match_bind_struct (slice_neg_control). Each cap word updated to base_cap - lo: a [8]u8 base sliced at lo=0 yields cap 8 (5->8, 3->8); distinct_bytes slices a [16]u8 at lo=0, yielding cap 16 (6->16). len / mark / ptr assertions are unchanged -- only the cap word moved.
This commit is contained in:
@@ -209,7 +209,7 @@ static const struct row rows[] = {
|
||||
" b.mark = 7;\n"
|
||||
" b.rbuf = rbuf;\n"
|
||||
" if (b.rbuf.len != 5) { return 1; };\n"
|
||||
" if (b.rbuf.cap != 5) { return 2; };\n"
|
||||
" if (b.rbuf.cap != 8) { return 2; };\n"
|
||||
" if (b.mark != 7) { return 3; };\n"
|
||||
" return 42;\n"
|
||||
"};\n",
|
||||
@@ -229,7 +229,7 @@ static const struct row rows[] = {
|
||||
" let b: bs;\n"
|
||||
" init(&b, raw[0:5]);\n"
|
||||
" if (b.rbuf.len != 5) { return 1; };\n"
|
||||
" if (b.rbuf.cap != 5) { return 2; };\n"
|
||||
" if (b.rbuf.cap != 8) { return 2; };\n"
|
||||
" if (b.mark != 9) { return 3; };\n"
|
||||
" return 42;\n"
|
||||
"};\n",
|
||||
@@ -240,10 +240,12 @@ static const struct row rows[] = {
|
||||
* patterns at raw[0] (0xAA) and raw[5] (0xFF) are read back
|
||||
* through b.rbuf[i], which only succeeds if .ptr (AX) survived
|
||||
* at +0. Trailing mark uses a distinctive value (0x33) so a
|
||||
* stray CX store one slot too far is caught separately. .len
|
||||
* and .cap are forced equal by ww's slice expression (both
|
||||
* BX = hi-lo), so this row pins .ptr survival while the other
|
||||
* rows pin .len/.cap distinctness from the zero default. */
|
||||
* stray CX store one slot too far is caught separately. Here
|
||||
* .len=6 (hi-lo) and .cap=16 (base_cap-lo; raw is [16]u8) per
|
||||
* project #20, so this row pins .ptr survival and additionally
|
||||
* confirms .len and .cap land as distinct words (they no longer
|
||||
* coincide), while the other rows pin .len/.cap distinctness
|
||||
* from the zero default. */
|
||||
{ "slice_field_distinct_bytes",
|
||||
"type bs = struct { rbuf: []u8, mark: i32 };\n"
|
||||
"fn main() i32 = {\n"
|
||||
@@ -254,7 +256,7 @@ static const struct row rows[] = {
|
||||
" b.mark = 0x33;\n"
|
||||
" b.rbuf = raw[0:6];\n"
|
||||
" if (b.rbuf.len != 6) { return 1; };\n"
|
||||
" if (b.rbuf.cap != 6) { return 2; };\n"
|
||||
" if (b.rbuf.cap != 16) { return 2; };\n"
|
||||
" if (b.mark != 0x33) { return 3; };\n"
|
||||
" if (b.rbuf[0] != 0xAAu8) { return 4; };\n"
|
||||
" if (b.rbuf[5] != 0xFFu8) { return 5; };\n"
|
||||
|
||||
Reference in New Issue
Block a user