lib/bytes+test: graduate contains to Hare (u8|[]u8)... variadic (#10)

contains(s, needle: (u8|[]u8)) -> contains(s: []u8, needles:
(u8|[]u8)...) bool per ref/hare/bytes/contains.ha:6.

Body: for-loop over needles.len; inner match (needles[i]) with u8/
[]u8 arms each forwarding to index(s, ...) with early return true
on the i32-match arm. 0-arg returns false per Hare spec. Mirrors
sister #9 strings.contains body shape modulo element type.

Sister of #9 (7c5463c). Element shape (u8|[]u8) — slice payload +
scalar u8 — structurally distinct from (str|rune). Was flagged as
potential new-latent surface; verified clean by 967_bytes_run +
cross-module 750_mklabel_modscoped[bytes_strings_contains] +
995_self_rebuild byte-id. No cgen wedge fired — #15 frame growth +
#12 sum-tag forward + #16 fnparamslookupmod close it on the slice-
payload variant too.

contains_cases adds 5 variadic rows (signalled 1700+i): 0-arg false,
1-arg slice hit, 1-arg u8 hit, 3-arg mixed middle-hit, 3-arg all-miss.

Module-header non-variadic divergence note removed.

make test 126/126; ww2==ww3==ww4 byte-id holds via 995_self_rebuild.
This commit is contained in:
2026-05-19 05:19:21 +09:00
parent 7c5463c7d9
commit 23fccee4a0
5 changed files with 92 additions and 36 deletions

View File

@@ -7,9 +7,6 @@
// 2/3/4-byte needles and falls back to two_way (Crochemore-Perrin)
// for longer (ref/hare/bytes/index.ha:61, ref/hare/bytes/two_way.ha).
// Correctness equivalent.
// - contains takes a single needle; Hare's contains is variadic
// `(u8 | []u8)...` (ref/hare/bytes/contains.ha:5). No caller needs
// the variadic shape yet; graduate when one does.
// equal — true iff `a` and `b` have the same length and contents.
// ref/hare/bytes/equal.ha:9.
@@ -92,12 +89,26 @@ export fn rindex(s: []u8, needle: (u8 | []u8)) (i32 | void) = {
return;
};
// contains — true iff `needle` (byte or sub-slice) appears in `s`.
// ref/hare/bytes/contains.ha:5 (variadic subset; see header note).
export fn contains(s: []u8, needle: (u8 | []u8)) bool = {
match (index(s, needle)) {
case let i: i32 => return true;
case void => return false;
// contains — true iff any of `needles` (byte or sub-slice) appears in `s`.
// ref/hare/bytes/contains.ha:6.
export fn contains(s: []u8, needles: (u8 | []u8)...) bool = {
let i: i32 = 0;
for (i < needles.len) {
match (needles[i]) {
case let b: u8 => {
match (index(s, b)) {
case let bo: i32 => return true;
case void => void;
};
};
case let n: []u8 => {
match (index(s, n)) {
case let bo: i32 => return true;
case void => void;
};
};
};
i += 1;
};
return false;
};

View File

@@ -195,6 +195,18 @@ fn fail() void = { os.exit(signalled + 10); };
if (!bytes.contains(a[0:4], n[0:2])) { fail(); };
let m: [2]u8; m[0] = 9u8; m[1] = 9u8;
if ( bytes.contains(a[0:4], m[0:2])) { fail(); };
// Variadic rows. ref/hare/bytes/contains.ha:6.
signalled = 1700;
if ( bytes.contains(a[0:4])) { fail(); };
signalled = 1701;
if (!bytes.contains(a[0:4], n[0:2])) { fail(); };
signalled = 1702;
if (!bytes.contains(a[0:4], 7u8)) { fail(); };
signalled = 1703;
if (!bytes.contains(a[0:4], m[0:2], n[0:2], 42u8)) { fail(); };
signalled = 1704;
if ( bytes.contains(a[0:4], m[0:2], 42u8, m[0:2])) { fail(); };
};
// ---- hasprefix --------------------------------------------------------