// idxarg_test — an INDEXED slice/str element passed as a call argument must // push its full multi-word header, both stages, migrated from // test/wcc/989_idxarg_run.c (#45/#46). pushargsrev sizes a call arg via // nodeisslice/nodeisstr; pre-fix nodeisslice had no N_INDEX arm (#45, slice // element fell to a 1-word scalar push) and nodeisstr's N_INDEX arm was a // base-kind whitelist that only knew N_IDENT/N_DOT bases (#46, a non-ident/ // non-dot base fell through to a 1-word push). Either way the callee read // garbage .len/.cap — a cat-A divergence invisible to byte-id. // // Each "row" is a distinct index-base SHAPE (slice element, N_CALL base, // N_IDENT base, plain local control), not data, so this file uses per-shape // asserts rather than the uniesc row-loop idiom. package idxarg_test; fn takeintlen(xs: []int) int = { return len(xs): int; }; fn takestrlen(s: str) int = { return len(s): int; }; fn getarr() []str = { let a: []str = ["x", "ddddd", "zz"]; return a; }; @test fn idx_slice_arg() void = { // slice_elem_arg (#45): a []int slice element `rows[1]` as a call arg — // pre-fix nodeisslice had no N_INDEX arm, so a 1-word push gave the // callee garbage len. len(rows[1]) == len(b) == 2. let a: []int = [10, 20, 30, 40]; let b: []int = [1, 2]; let rows: [2][]int = [a, b]; assert(takeintlen(rows[1]) == 2); }; @test fn idx_str_arg() void = { // call_str_elem (#46): an index whose base is an N_CALL (`getarr()[1]`) // — the non-ident/non-dot base the old whitelist missed. len == 5. assert(takestrlen(getarr()[1]) == 5); // ident_str_elem (#46 control): an N_IDENT base `arr[1]` — the case the // old whitelist DID handle; the stamp read must not regress it. let arr: [3]str = ["x", "ddddd", "zz"]; assert(takestrlen(arr[1]) == 5); }; @test fn idx_local_arg() void = { // slice_local_arg (control): a plain non-indexed str/slice local arg // (the c1 N_IDENT-local arm) — c2 must leave it alone. len == 3. let xs: []int = [7, 8, 9]; assert(takeintlen(xs) == 3); };