lib/strings+test: add index/rindex Hare sum-type dispatch (#11)
index(haystack: str, needle: (str|rune)) (i32|void) per
ref/hare/strings/index.ha:10. rindex symmetric per :22.
Returns RUNE-index (not byte-index) per Hare contract. str-arm reuses
byteindex/rbyteindex for the anchor byte offset, then walks iter
forward counting runes until position(&it) >= bo. rune-arm forward-
iterates with next(), counts rune positions.
rindex_rune divergence from ref/hare/strings/index.ha:45: Hare's
rindex_rune walks i = len(s) - 1 by 1 per step (byte-len-1 minus
decrement count) — neither pure-byte nor pure-rune for multibyte
input, contradicts its own docstring's rune-wise claim. ww honors
the docstring contract: forward iter + last-match-index. Cited
inline at strings.ww.
Unblocked by #13 (d2c64bc) — pre-#13 the test rows
"strings.index" + "bytes.index" would collide on
*.index_match_next_1 labels in combined.s.
index_cases + rindex_cases per-row inline-match (sister convention of
byteindex_str/rune_cases at stringstest.ww:147-231; sum-type-needle
single-struct table awkward). Bisect via signalled = 1400+i / 1500+i.
Rune-vs-byte pin rows: "こんにちは"+"ちは" → 3 (byte 9),
"またあったね"+"た" rindex → 4 (byte 12). Void miss + 4-byte rune
multibyte coverage.
make test 125/125; ww2==ww3==ww4 byte-id holds via 995_self_rebuild.
This commit is contained in:
@@ -230,6 +230,131 @@ fn streq(a: str, b: str) bool = {
|
||||
};
|
||||
};
|
||||
|
||||
// ---- index ------------------------------------------------------------
|
||||
// ref/hare/strings/index.ha:108. Rune-wise offset, NOT byte-wise — the
|
||||
// multibyte rows pin that distinction (Hare doc at index.ha:7).
|
||||
|
||||
@test fn index_cases() void = {
|
||||
// str-arm: ASCII haystack/needle, mid-string match.
|
||||
signalled = 1400;
|
||||
match (strings.index("hello", "ll")) {
|
||||
case let i: i32 => { if (i != 2) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// str-arm: absent needle.
|
||||
signalled = 1401;
|
||||
match (strings.index("hello", "world")) {
|
||||
case let i: i32 => { fail(); };
|
||||
case void => void;
|
||||
};
|
||||
// Hare vectors at ref/hare/strings/index.ha:113-119.
|
||||
signalled = 1402;
|
||||
match (strings.index("hello world!", "hello")) {
|
||||
case let i: i32 => { if (i != 0) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1403;
|
||||
match (strings.index("hello world!", "world")) {
|
||||
case let i: i32 => { if (i != 6) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1404;
|
||||
match (strings.index("hello world!", "orld!")) {
|
||||
case let i: i32 => { if (i != 7) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// Multibyte haystack + str needle: "ちは" at rune index 3
|
||||
// in "こんにちは" (byteindex returns 9, rune-index is 3).
|
||||
signalled = 1405;
|
||||
match (strings.index("こんにちは", "ちは")) {
|
||||
case let i: i32 => { if (i != 3) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// rune-arm.
|
||||
signalled = 1406;
|
||||
match (strings.index("hello", 'l')) {
|
||||
case let i: i32 => { if (i != 2) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1407;
|
||||
match (strings.index("hello world", 'w')) {
|
||||
case let i: i32 => { if (i != 6) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// Multibyte rune: 'é' U+00E9 at rune 1 in "héllo" — pins
|
||||
// rune-index vs byte-index (byteindex returns 1; rune-index is
|
||||
// 1 also — but the str-arm's 1405 row covers the distinction).
|
||||
signalled = 1408;
|
||||
match (strings.index("héllo", 0xE9u32: rune)) {
|
||||
case let i: i32 => { if (i != 1) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// Multibyte rune in multibyte haystack: 'ち' U+3061 at rune 3
|
||||
// in "こんにちは" (byteindex returns 9, rune-index is 3).
|
||||
signalled = 1409;
|
||||
match (strings.index("こんにちは", 0x3061u32: rune)) {
|
||||
case let i: i32 => { if (i != 3) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1410;
|
||||
match (strings.index("こんにちは", 'q')) {
|
||||
case let i: i32 => { fail(); };
|
||||
case void => void;
|
||||
};
|
||||
};
|
||||
|
||||
// ---- rindex -----------------------------------------------------------
|
||||
// ref/hare/strings/index.ha:22. Symmetric: last-occurrence rune index.
|
||||
|
||||
@test fn rindex_cases() void = {
|
||||
// str-arm.
|
||||
signalled = 1500;
|
||||
match (strings.rindex("hello", "lo")) {
|
||||
case let i: i32 => { if (i != 3) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// Hare vector at ref/hare/strings/index.ha:122.
|
||||
signalled = 1501;
|
||||
match (strings.rindex("hello world!", "o")) {
|
||||
case let i: i32 => { if (i != 7) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1502;
|
||||
match (strings.rindex("hello", "world")) {
|
||||
case let i: i32 => { fail(); };
|
||||
case void => void;
|
||||
};
|
||||
// Multibyte: last "た" in "またあったね" — rbyteindex returns
|
||||
// 12, rune-index is 4 (ま=0 た=1 あ=2 っ=3 た=4 ね=5).
|
||||
signalled = 1503;
|
||||
match (strings.rindex("またあったね", "た")) {
|
||||
case let i: i32 => { if (i != 4) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// rune-arm.
|
||||
signalled = 1504;
|
||||
match (strings.rindex("hello", 'l')) {
|
||||
case let i: i32 => { if (i != 3) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1505;
|
||||
match (strings.rindex("aaaaa", 'a')) {
|
||||
case let i: i32 => { if (i != 4) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
// Multibyte rune: 'に' U+306B at rune 2 in "こんにちは".
|
||||
signalled = 1506;
|
||||
match (strings.rindex("こんにちは", 0x306Bu32: rune)) {
|
||||
case let i: i32 => { if (i != 2) { fail(); }; };
|
||||
case void => { fail(); };
|
||||
};
|
||||
signalled = 1507;
|
||||
match (strings.rindex("hello", 'z')) {
|
||||
case let i: i32 => { fail(); };
|
||||
case void => void;
|
||||
};
|
||||
};
|
||||
|
||||
// ---- trimprefix / trimsuffix ------------------------------------------
|
||||
// ref/hare/strings/trim.ha:99-107.
|
||||
|
||||
@@ -709,6 +834,8 @@ export fn main() i32 = {
|
||||
signalled = 6; byteindex_str_cases();
|
||||
signalled = 7; byteindex_rune_cases();
|
||||
signalled = 8; rbyteindex_cases();
|
||||
signalled = 28; index_cases();
|
||||
signalled = 29; rindex_cases();
|
||||
signalled = 9; trimprefix_cases();
|
||||
signalled = 10; trimsuffix_cases();
|
||||
signalled = 11; ltrim_cases();
|
||||
|
||||
Reference in New Issue
Block a user