lib/strconv: stoi/stou/stoz machine-word int parse (strconv-int fold-1 C2)

Add the int/uint/size entry points (ref/hare/strconv/stoi.ha:53,
stou.ha:107,113). Hare clamps to types::INT_MIN/MAX, UINT_MAX, SIZE_MAX
via stoiminmax/stoumax; ww's int/uint/size are 8B machine words
(INT/UINT/SIZE limits == I64/U64 per lib/types/types.ww:30-37), so the
clamp is a no-op — the full i64/u64 range parses with no spurious
overflow. Documented at-site (the bound consts are package-private, so
inlining them would just re-encode I64/U64_MAX).

Tests: extend inttest.ww with test_stoi_stou_stoz — value path, sign,
overflow pass-through, and the no-clamp fidelity (I64_MAX/U64_MAX parse
without overflow) plus hex/bin bases through the shared parseint core.

combined.ww regen: w6c + wwdump main.combined.ww.
This commit is contained in:
2026-06-01 22:07:04 +09:00
parent 6a5cdbd779
commit a11785273a
5 changed files with 250 additions and 0 deletions

View File

@@ -6234,6 +6234,23 @@ export fn stoi8(s: str, b: base) (i8 | invalid | overflow) = {
return 0: invalid;
};
// stoi — parse signed base-b number into an int. Mirrors Hare's
// strconv::stoi (ref/hare/strconv/stoi.ha:53), which clamps to
// types::INT_MIN/INT_MAX via stoiminmax. ww's int is a machine word
// (8B → i64-width, so INT_MIN/INT_MAX == I64_MIN/I64_MAX per
// lib/types/types.ww:30-31), so stoi64's result always fits and the
// clamp is a no-op — omitted, not inlined (the bound consts are
// package-private; see the inline note at mulshift32 in ftos.ww).
export fn stoi(s: str, b: base) (int | invalid | overflow) = {
let r = stoi64(s, b);
match (r) {
case let v: i64 => return v: int;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
export fn stou32(s: str, b: base) (u32 | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
@@ -6273,6 +6290,34 @@ export fn stou8(s: str, b: base) (u8 | invalid | overflow) = {
return 0: invalid;
};
// stou — parse unsigned base-b number into a uint. Mirrors Hare's
// strconv::stou (ref/hare/strconv/stou.ha:107), which clamps to
// types::UINT_MAX via stoumax. ww's uint is a machine word (8B →
// u64-width, so UINT_MAX == U64_MAX per lib/types/types.ww:33), so
// stou64's result always fits and the clamp is a no-op.
export fn stou(s: str, b: base) (uint | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
case let v: u64 => return v: uint;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
// stoz — parse unsigned base-b number into a size. Mirrors Hare's
// strconv::stoz (ref/hare/strconv/stou.ha:113). ww's size is u64-width
// (SIZE_MAX == U64_MAX per lib/types/types.ww:37), so the clamp is a no-op.
export fn stoz(s: str, b: base) (size | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
case let v: u64 => return v: size;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
// f64tos — graduated to the Ryū shortest-round-trippable implementation
// in ftos.ww (strconv #106 fold-5). The old lossy fixed-point version
// (6 fractional digits, "huge" fallback ≥9e18, no NaN/Inf) was deleted

View File

@@ -6234,6 +6234,23 @@ export fn stoi8(s: str, b: base) (i8 | invalid | overflow) = {
return 0: invalid;
};
// stoi — parse signed base-b number into an int. Mirrors Hare's
// strconv::stoi (ref/hare/strconv/stoi.ha:53), which clamps to
// types::INT_MIN/INT_MAX via stoiminmax. ww's int is a machine word
// (8B → i64-width, so INT_MIN/INT_MAX == I64_MIN/I64_MAX per
// lib/types/types.ww:30-31), so stoi64's result always fits and the
// clamp is a no-op — omitted, not inlined (the bound consts are
// package-private; see the inline note at mulshift32 in ftos.ww).
export fn stoi(s: str, b: base) (int | invalid | overflow) = {
let r = stoi64(s, b);
match (r) {
case let v: i64 => return v: int;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
export fn stou32(s: str, b: base) (u32 | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
@@ -6273,6 +6290,34 @@ export fn stou8(s: str, b: base) (u8 | invalid | overflow) = {
return 0: invalid;
};
// stou — parse unsigned base-b number into a uint. Mirrors Hare's
// strconv::stou (ref/hare/strconv/stou.ha:107), which clamps to
// types::UINT_MAX via stoumax. ww's uint is a machine word (8B →
// u64-width, so UINT_MAX == U64_MAX per lib/types/types.ww:33), so
// stou64's result always fits and the clamp is a no-op.
export fn stou(s: str, b: base) (uint | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
case let v: u64 => return v: uint;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
// stoz — parse unsigned base-b number into a size. Mirrors Hare's
// strconv::stoz (ref/hare/strconv/stou.ha:113). ww's size is u64-width
// (SIZE_MAX == U64_MAX per lib/types/types.ww:37), so the clamp is a no-op.
export fn stoz(s: str, b: base) (size | invalid | overflow) = {
let r = stou64(s, b);
match (r) {
case let v: u64 => return v: size;
case let e: invalid => return e;
case let e: overflow => return e;
};
return 0: invalid;
};
// f64tos — graduated to the Ryū shortest-round-trippable implementation
// in ftos.ww (strconv #106 fold-5). The old lossy fixed-point version
// (6 fractional digits, "huge" fallback ≥9e18, no NaN/Inf) was deleted