// slice_copy_assign_test — bulk slice-copy-assign into a range place // `s.arr[lo:hi] = bs` (the LHS is an N_SLICE), migrated from // test/wcc/952_slicecopy_assign_run.c (#145). No legacy N_ASSIGN arm caught an // N_SLICE LHS, so the statement fell through to the scalar tail and emitted // NOTHING — a silent no-op in BOTH stages, byte-id-green (#263-class). The fix // reuses the N_SLICE READ lowering (AX = base+lo*esz, BX = hi-lo, CX = cap), // scales BX by the SAME read-path element width (esz; [N]u8→1, [N]i32→4), and // emits a runtime-counted byte-granular copy loop. WRITE rows assert the copy // lands the right bytes in [lo,hi) AND leaves bytes OUTSIDE the range untouched // (each sums members both inside and outside, so a mis-strided / over-wide copy // fails); esz coverage [N]u8 + [N]i32; base coverage struct-field array (N_DOT), // via-*struct-param, and bare-local (N_IDENT). READ rows lock the reslice-consume // companion (#5, already clean). package slice_copy_assign_test; type buffer = struct { buf: [8]u8, end: i32 }; type box = struct { o: [8]i32 }; fn wr(s: *buffer, src: []u8) void = { s.buf[1:4] = src; }; @test fn w_u8_lo0() void = { // struct-field [N]u8 base (the appendlit shape). let s: buffer; let bs: [3]u8; bs[0] = 10u8; bs[1] = 20u8; bs[2] = 30u8; s.buf[0:3] = bs[0:3]; assert((s.buf[0] + s.buf[1] + s.buf[2] + s.buf[3] + s.buf[4] + s.buf[5]): i32 == 60); }; @test fn w_u8_lo2() void = { let s: buffer; let bs: [3]u8; bs[0] = 10u8; bs[1] = 20u8; bs[2] = 30u8; s.buf[2:5] = bs[0:3]; assert((s.buf[0] + s.buf[1] + s.buf[2] + s.buf[3] + s.buf[4] + s.buf[5]): i32 == 60); }; @test fn w_u8_single() void = { let s: buffer; let bs: [1]u8; bs[0] = 42u8; s.buf[3:4] = bs[0:1]; assert((s.buf[2] + s.buf[3] + s.buf[4]): i32 == 42); }; @test fn w_empty() void = { // hi==lo — count=0; the loop's CMPQ $0 guard must JLE-exit before the first // MOVB (an off-by-one underflow would clobber buf[lo] and run away). let s: buffer; s.buf[2] = 5u8; s.buf[3] = 7u8; let bs: [3]u8; bs[0] = 10u8; bs[1] = 20u8; bs[2] = 30u8; s.buf[2:2] = bs[0:0]; assert((s.buf[1] + s.buf[2] + s.buf[3] + s.buf[4]): i32 == 12); }; @test fn w_i32() void = { // esz=4 — [N]i32 field strides by the element width, not 1. let s: box; let bs: [2]i32; bs[0] = 40; bs[1] = 88; s.o[1:3] = bs[0:2]; assert((s.o[0] + s.o[1] + s.o[2] + s.o[3]): i32 == 128); }; @test fn w_viaptr() void = { // the field write through a *struct param (appendlit's `buf: *buffer`). let s: buffer; let bs: [3]u8; bs[0] = 11u8; bs[1] = 22u8; bs[2] = 33u8; wr(&s, bs[0:3]); assert((s.buf[0] + s.buf[1] + s.buf[2] + s.buf[3] + s.buf[4]): i32 == 66); }; @test fn w_local() void = { // N_IDENT base — a bare-local array place. let a: [8]u8; let bs: [3]u8; bs[0] = 10u8; bs[1] = 20u8; bs[2] = 30u8; a[2:5] = bs[0:3]; assert((a[0] + a[1] + a[2] + a[3] + a[4] + a[5]): i32 == 60); }; @test fn rd_reslice() void = { // READ twin (#5, already clean) — reslice the field array with a runtime hi // bound, consume as []u8. let s: buffer; let bs: [3]u8; bs[0] = 10u8; bs[1] = 20u8; bs[2] = 30u8; s.buf[0:3] = bs[0:3]; s.end = 3; let v: []u8 = s.buf[0:s.end]; // 10+20+30 + 3*100 == 360 (the .c twin's want=104 was 360 & 0xFF, an // exit-code truncation; the @test asserts the true value). assert(v[0]: i32 + v[1]: i32 + v[2]: i32 + (v.len: i32) * 100 == 360); }; @test fn rd_len() void = { let s: buffer; s.end = 5; let v: []u8 = s.buf[0:s.end]; assert(v.len: i32 == 5); };