From f82742921566a6e450c549710475ac85652a1192 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Tue, 19 May 2026 22:39:05 +0900 Subject: [PATCH] lib/strings+test: compare returns int, not i32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- lib/strings/strings.ww | 11 ++++++----- lib/strings/stringstest.ww | 1 + selfhost/cmd/w6c/main.combined.ww | 11 ++++++----- selfhost/cmd/wwdump/main.combined.ww | 11 ++++++----- selfhost/test/smoke.combined.ww | 11 ++++++----- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/strings/strings.ww b/lib/strings/strings.ww index a2c4f513..75052521 100644 --- a/lib/strings/strings.ww +++ b/lib/strings/strings.ww @@ -52,17 +52,18 @@ export fn fromutf8_unsafe(in: []u8) str = { return r; }; -// compare — three-way bytewise codepoint-order comparison. -// ref/hare/strings/compare.ha:12. -export fn compare(a: str, b: str) i32 = { +// compare — three-way bytewise codepoint-order comparison. Return is +// a sign (neg/zero/pos), not an index, so it tracks Hare's `int` +// 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; if (b.len < n) { n = b.len; }; let i: i32 = 0; 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; }; - return a.len - b.len; + return (a.len: int) - (b.len: int); }; // dup — allocate a fresh copy of `s`. Caller releases with diff --git a/lib/strings/stringstest.ww b/lib/strings/stringstest.ww index 25708a0c..782f7447 100644 --- a/lib/strings/stringstest.ww +++ b/lib/strings/stringstest.ww @@ -584,6 +584,7 @@ fn streq(a: str, b: str) bool = { if (strings.compare("AB", "ABC") >= 0) { fail(); }; if (strings.compare("BCD", "ABC") <= 0) { fail(); }; if (strings.compare("ABC", "abc") >= 0) { fail(); }; + if (strings.compare("ABC", "こんにちは") >= 0) { fail(); }; }; // ---- sub / bytesub ---------------------------------------------------- diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 90f427ec..f6540983 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -1889,17 +1889,18 @@ export fn fromutf8_unsafe(in: []u8) str = { return r; }; -// compare — three-way bytewise codepoint-order comparison. -// ref/hare/strings/compare.ha:12. -export fn compare(a: str, b: str) i32 = { +// compare — three-way bytewise codepoint-order comparison. Return is +// a sign (neg/zero/pos), not an index, so it tracks Hare's `int` +// 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; if (b.len < n) { n = b.len; }; let i: i32 = 0; 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; }; - return a.len - b.len; + return (a.len: int) - (b.len: int); }; // dup — allocate a fresh copy of `s`. Caller releases with diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 14250020..820ca563 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -1889,17 +1889,18 @@ export fn fromutf8_unsafe(in: []u8) str = { return r; }; -// compare — three-way bytewise codepoint-order comparison. -// ref/hare/strings/compare.ha:12. -export fn compare(a: str, b: str) i32 = { +// compare — three-way bytewise codepoint-order comparison. Return is +// a sign (neg/zero/pos), not an index, so it tracks Hare's `int` +// 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; if (b.len < n) { n = b.len; }; let i: i32 = 0; 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; }; - return a.len - b.len; + return (a.len: int) - (b.len: int); }; // dup — allocate a fresh copy of `s`. Caller releases with diff --git a/selfhost/test/smoke.combined.ww b/selfhost/test/smoke.combined.ww index 781ed442..d6e21a4d 100644 --- a/selfhost/test/smoke.combined.ww +++ b/selfhost/test/smoke.combined.ww @@ -1780,17 +1780,18 @@ export fn fromutf8_unsafe(in: []u8) str = { return r; }; -// compare — three-way bytewise codepoint-order comparison. -// ref/hare/strings/compare.ha:12. -export fn compare(a: str, b: str) i32 = { +// compare — three-way bytewise codepoint-order comparison. Return is +// a sign (neg/zero/pos), not an index, so it tracks Hare's `int` +// 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; if (b.len < n) { n = b.len; }; let i: i32 = 0; 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; }; - return a.len - b.len; + return (a.len: int) - (b.len: int); }; // dup — allocate a fresh copy of `s`. Caller releases with