lib/strings+test: compare returns int, not i32

Hare's strings::compare returns int (ref/hare/strings/compare.ha:12).
Result is a sign, not an index, so the i32 was cargo-culted from the
str-index type. Callsites already compared against 0, so callers
needed no migration. Widened the two return-site casts (u8→int,
i32→int) — the latter avoids i32 underflow on adversarial length
diffs. Added a multibyte test row contrasting ASCII vs UTF-8 lead
byte to exercise the high-bit-operand path.
This commit is contained in:
2026-05-19 22:39:05 +09:00
parent 031f5f9ec8
commit f827429215
5 changed files with 25 additions and 20 deletions

View File

@@ -52,17 +52,18 @@ export fn fromutf8_unsafe(in: []u8) str = {
return r; return r;
}; };
// compare — three-way bytewise codepoint-order comparison. // compare — three-way bytewise codepoint-order comparison. Return is
// ref/hare/strings/compare.ha:12. // a sign (neg/zero/pos), not an index, so it tracks Hare's `int`
export fn compare(a: str, b: str) i32 = { // rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12.
export fn compare(a: str, b: str) int = {
let n: i32 = a.len; let n: i32 = a.len;
if (b.len < n) { n = b.len; }; if (b.len < n) { n = b.len; };
let i: i32 = 0; let i: i32 = 0;
for (i < n) { for (i < n) {
if (a[i] != b[i]) { return (a[i]: i32) - (b[i]: i32); }; if (a[i] != b[i]) { return (a[i]: int) - (b[i]: int); };
i += 1; i += 1;
}; };
return a.len - b.len; return (a.len: int) - (b.len: int);
}; };
// dup — allocate a fresh copy of `s`. Caller releases with // dup — allocate a fresh copy of `s`. Caller releases with

View File

@@ -584,6 +584,7 @@ fn streq(a: str, b: str) bool = {
if (strings.compare("AB", "ABC") >= 0) { fail(); }; if (strings.compare("AB", "ABC") >= 0) { fail(); };
if (strings.compare("BCD", "ABC") <= 0) { fail(); }; if (strings.compare("BCD", "ABC") <= 0) { fail(); };
if (strings.compare("ABC", "abc") >= 0) { fail(); }; if (strings.compare("ABC", "abc") >= 0) { fail(); };
if (strings.compare("ABC", "こんにちは") >= 0) { fail(); };
}; };
// ---- sub / bytesub ---------------------------------------------------- // ---- sub / bytesub ----------------------------------------------------

View File

@@ -1889,17 +1889,18 @@ export fn fromutf8_unsafe(in: []u8) str = {
return r; return r;
}; };
// compare — three-way bytewise codepoint-order comparison. // compare — three-way bytewise codepoint-order comparison. Return is
// ref/hare/strings/compare.ha:12. // a sign (neg/zero/pos), not an index, so it tracks Hare's `int`
export fn compare(a: str, b: str) i32 = { // rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12.
export fn compare(a: str, b: str) int = {
let n: i32 = a.len; let n: i32 = a.len;
if (b.len < n) { n = b.len; }; if (b.len < n) { n = b.len; };
let i: i32 = 0; let i: i32 = 0;
for (i < n) { for (i < n) {
if (a[i] != b[i]) { return (a[i]: i32) - (b[i]: i32); }; if (a[i] != b[i]) { return (a[i]: int) - (b[i]: int); };
i += 1; i += 1;
}; };
return a.len - b.len; return (a.len: int) - (b.len: int);
}; };
// dup — allocate a fresh copy of `s`. Caller releases with // dup — allocate a fresh copy of `s`. Caller releases with

View File

@@ -1889,17 +1889,18 @@ export fn fromutf8_unsafe(in: []u8) str = {
return r; return r;
}; };
// compare — three-way bytewise codepoint-order comparison. // compare — three-way bytewise codepoint-order comparison. Return is
// ref/hare/strings/compare.ha:12. // a sign (neg/zero/pos), not an index, so it tracks Hare's `int`
export fn compare(a: str, b: str) i32 = { // rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12.
export fn compare(a: str, b: str) int = {
let n: i32 = a.len; let n: i32 = a.len;
if (b.len < n) { n = b.len; }; if (b.len < n) { n = b.len; };
let i: i32 = 0; let i: i32 = 0;
for (i < n) { for (i < n) {
if (a[i] != b[i]) { return (a[i]: i32) - (b[i]: i32); }; if (a[i] != b[i]) { return (a[i]: int) - (b[i]: int); };
i += 1; i += 1;
}; };
return a.len - b.len; return (a.len: int) - (b.len: int);
}; };
// dup — allocate a fresh copy of `s`. Caller releases with // dup — allocate a fresh copy of `s`. Caller releases with

View File

@@ -1780,17 +1780,18 @@ export fn fromutf8_unsafe(in: []u8) str = {
return r; return r;
}; };
// compare — three-way bytewise codepoint-order comparison. // compare — three-way bytewise codepoint-order comparison. Return is
// ref/hare/strings/compare.ha:12. // a sign (neg/zero/pos), not an index, so it tracks Hare's `int`
export fn compare(a: str, b: str) i32 = { // rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12.
export fn compare(a: str, b: str) int = {
let n: i32 = a.len; let n: i32 = a.len;
if (b.len < n) { n = b.len; }; if (b.len < n) { n = b.len; };
let i: i32 = 0; let i: i32 = 0;
for (i < n) { for (i < n) {
if (a[i] != b[i]) { return (a[i]: i32) - (b[i]: i32); }; if (a[i] != b[i]) { return (a[i]: int) - (b[i]: int); };
i += 1; i += 1;
}; };
return a.len - b.len; return (a.len: int) - (b.len: int);
}; };
// dup — allocate a fresh copy of `s`. Caller releases with // dup — allocate a fresh copy of `s`. Caller releases with