Continue fold-2 (after 374e97b): migrate the remaining Family-1 str/slice
global + literal + index + call-arg group from bespoke build+run C twins to
test/lang @test, retiring each twin in the same commit. Runtime coverage MOVES
from $(TESTS) to test-lang (T1 runs+asserts via `ww test`) + test-lang-byteid
(T2 keeps cs==ww .s byte-id); coverage is preserved, the $(TESTS) headline
drops 9 (434->425). All asserts are primitive int/u8/bool comparisons (no
fmt/strconv in the assert path); the slice-store/index rows reset the global
each fn and sum ADJACENT elements so a dropped/mis-strided/over-wide word FAILS.
989_globslicefield_run.c -> glob_slice_field_test.ww (slice field of a global struct: g.f=<slice> stores full 24B header; len/cap/non-zero-offset + str/scalar controls)
989_globstrslice_run.c -> glob_str_slice_arg_test.ww (global str sliced with default hi passed as call arg loads its len word; explicit-hi control)
989_trystr_run.c -> try_str_unwrap_test.ww (`!` unwrap of str-success tagged union shuffles the str header for ident-source/error-first/success-first)
797_len_strglobal_run.c -> len_str_global_test.ww (len(str-global) loads .len via name(SB); local-str control)
801_litstr_pseudo_run.c -> lit_str_pseudo_test.ww (string-literal .len/.ptr pseudo-field; empty/multibyte + arg-passthrough)
803_globalidx_run.c -> global_index_test.ww (global str/slice index read/addr-of/store/compound, esz 1/4; local regression pins)
903_tuple_elem_slice_len.c -> tuple_elem_slice_len_test.ww (len(t.N) of a slice/str tuple element loads .len at +8; 2/3-slice, str-slice both orders)
927_composite_call_arg_run.c-> composite_call_arg_test.ww (slice-returning CALL passed inline as a composite arg; canonical/letslice/two-call/middle/nested/scalar/tagged)
952_slicecopy_assign_run.c -> slice_copy_assign_test.ww (bulk slice-copy-assign `arr[lo:hi]=bs`, esz 1/4, field/via-ptr/local bases; reslice-read companion)
rd_reslice asserts the TRUE value 360 (the .c twin's want=104 was 360 & 0xFF,
an exit-code truncation). 723_composite_call_arg.c's comment repointed to the
new test/lang location. 802_lenidx_run.c is DEFERRED (it carries //ww:error
reject rows — needs a value-rows-only split + a slim reject carrier, a fold-3
pass). Bump LANGBYTEID_EXPECTED_MIN 22->31 to ratchet the new corpus floor.
40 lines
1.5 KiB
Plaintext
40 lines
1.5 KiB
Plaintext
// lit_str_pseudo_test — the string-LITERAL `.len` / `.ptr` pseudo-field,
|
|
// migrated from test/wcc/801_litstr_pseudo_run.c (#14). cstage was wrong,
|
|
// wwstage correct (a rule-10 divergence): `"hi".len` returned the POINTER — a
|
|
// string literal is TY_UNTYPED_STR (not TY_STR), so it missed the typed str
|
|
// pseudo-field gate in cgen.c's N_DOT and fell to `cgexpr(lhs)` (AX=.ptr)
|
|
// without the BX->AX len shuffle that wwstage's cgdot catch-all already did.
|
|
// byte-id was BLIND: no bootstrap source uses literal `.len` (devs hardcoded
|
|
// the lengths). The fix aligns cstage UP — the N_DOT fallback emits `MOVQ BX,AX`
|
|
// for `.len`; `.ptr` already returned AX. The str-VARIABLE `.len` was a control.
|
|
|
|
package lit_str_pseudo_test;
|
|
|
|
fn slen(s: str) i32 = { return s.len: i32; };
|
|
|
|
@test fn lit_len() void = {
|
|
assert("hello".len: i32 == 5);
|
|
};
|
|
|
|
@test fn lit_len_empty_multibyte() void = {
|
|
// "" is 0 bytes; "héllo\n" is 7 bytes (h, é=2 UTF-8 bytes, l, l, o, \n) —
|
|
// a ptr would not read 7, so this guards a .ptr/.len confusion.
|
|
assert("".len: i32 == 0);
|
|
assert("héllo\n".len: i32 == 7);
|
|
};
|
|
|
|
@test fn lit_ptr_deref() void = {
|
|
// .ptr still points at the bytes (first byte == 'h'), proving the fix left
|
|
// .ptr untouched; then .len == 5.
|
|
let p: *u8 = "hello".ptr;
|
|
assert(*p == 'h');
|
|
assert("hello".len: i32 == 5);
|
|
};
|
|
|
|
@test fn lit_arg_passthrough() void = {
|
|
// callee-side .len on a literal passed as a str arg — the real-world shape
|
|
// (os.write(1, lit.ptr, lit.len)) that surfaced #14.
|
|
assert(slen("abcdef") == 6);
|
|
assert("abcdef".len: i32 == 6);
|
|
};
|