// A CHAINED index `m[i][k]` whose element is a str/slice must // load the full 24B/16B header, both stages, migrated from // test/wcc/989_chainidx_run.c (#22). The chained-index arm in cgindex read // the element tinfo for esz/signedness but NOT elemisstr/elemisslice, so a // chained index over [N][M]str / [N][M][]T loaded only the .ptr word and left // .len/.cap stale — a cat-A divergence the bootstrap corpus never hits. // // Each "row" is a distinct chained-index SHAPE (str read, str as call-arg, // slice read, scalar control), not data, so this file uses per-shape asserts // rather than the uniesc row-loop idiom. The [N][M] arrays are built by // per-element store — the nested array literal `[[..],[..]]` is independently // #270-1c-blocked (orthogonal). package chainidx_test; fn takelen(s: str) int = { return len(s): int; }; @test fn chain_str() void = { let m: [2][2]str; m[0][0] = "aa"; m[0][1] = "bbb"; m[1][0] = "c"; m[1][1] = "ddddd"; // chain_str_read: m[1][1] = "ddddd", len 5 (bug dropped the .len load). let str0: str = m[1][1]; assert(len(str0) == 5); // chain_str_call: the chained str element passed as a CALL ARG — needs // both the c2 push-side recognizer and this c3 read-side header load. assert(takelen(m[1][1]) == 5); }; @test fn chain_slice() void = { let a: []int = [1, 2]; let b: []int = [9, 9, 9, 9, 9, 9, 9]; let m: [2][2][]int; m[0][0] = a; m[0][1] = a; m[1][0] = a; m[1][1] = b; // chain_slice_read: m[1][1] = b, len 7 (bug dropped the .len/.cap load). let xs: []int = m[1][1]; assert(len(xs) == 7); }; @test fn chain_scalar() void = { let m: [2][2]int; m[0][0] = 1; m[0][1] = 2; m[1][0] = 3; m[1][1] = 42; // chain_scalar_read: control — the scalar chained index the arm already // handled; c3 must not regress it. m[1][1] == 42. assert(m[1][1] == 42); };