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.
244 lines
7.4 KiB
Plaintext
244 lines
7.4 KiB
Plaintext
// inttest — exercises lib/strconv integer parse: parseint / stoi64 /
|
|
// stou64 / the iN/uN width wrappers. Run with
|
|
// `out/bin/ww run lib/strconv/test/inttest.ww`. Same
|
|
// signalled-then-fail()-with-+10 pattern as decimaltest / bytestest:
|
|
// a non-zero exit code (signalled+10) pinpoints the failing case.
|
|
//
|
|
// Verbatim port of ref/hare/strconv/stoi.ha:56-86 (stoi/stoi_bases) and
|
|
// stou.ha:116-138 (stou/stou_bases). Hare's strconv integer tests are
|
|
// flat assert SEQUENCES, not row-array tables — mirrored here as inline
|
|
// per-case checks (feedback_test_match_hare_source: inline @test-fn for
|
|
// verbatim ports). Each case sets `signalled` first so a failure's exit
|
|
// code identifies the exact assertion.
|
|
//
|
|
// Lives in lib/strconv/test/ (not lib/strconv/) so `import strconv`
|
|
// resolves to the lib/strconv DIRECTORY (pulls the full package), not
|
|
// the strconv.ww FILE — same rationale as 922_decimal_run.
|
|
//
|
|
// Hex/oct/bin expected values are written in decimal (ww has no 0x/0o/0b
|
|
// literal form for the expectation side); the original Hare radix form
|
|
// is noted inline.
|
|
|
|
package strconv;
|
|
|
|
import strconv;
|
|
import os;
|
|
|
|
let signalled: i32 = 0;
|
|
fn fail() void = { os.exit(signalled + 10); };
|
|
|
|
fn cki(id: i32, s: str, b: base, want: i64) void = {
|
|
signalled = id;
|
|
match (stoi64(s, b)) {
|
|
case let v: i64 => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn cki_inv(id: i32, s: str, b: base, idx: i32) void = {
|
|
signalled = id;
|
|
match (stoi64(s, b)) {
|
|
case let v: i64 => fail();
|
|
case let e: invalid => if (e: i32 != idx) { fail(); };
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn cki_ovf(id: i32, s: str, b: base) void = {
|
|
signalled = id;
|
|
match (stoi64(s, b)) {
|
|
case let v: i64 => fail();
|
|
case let e: invalid => fail();
|
|
case let e: overflow => { };
|
|
};
|
|
};
|
|
|
|
fn cku(id: i32, s: str, b: base, want: u64) void = {
|
|
signalled = id;
|
|
match (stou64(s, b)) {
|
|
case let v: u64 => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn cku_inv(id: i32, s: str, b: base, idx: i32) void = {
|
|
signalled = id;
|
|
match (stou64(s, b)) {
|
|
case let v: u64 => fail();
|
|
case let e: invalid => if (e: i32 != idx) { fail(); };
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn cku_ovf(id: i32, s: str, b: base) void = {
|
|
signalled = id;
|
|
match (stou64(s, b)) {
|
|
case let v: u64 => fail();
|
|
case let e: invalid => fail();
|
|
case let e: overflow => { };
|
|
};
|
|
};
|
|
|
|
fn cki32_ovf(id: i32, s: str, b: base) void = {
|
|
signalled = id;
|
|
match (stoi32(s, b)) {
|
|
case let v: i32 => fail();
|
|
case let e: invalid => fail();
|
|
case let e: overflow => { };
|
|
};
|
|
};
|
|
|
|
fn cki32(id: i32, s: str, b: base, want: i32) void = {
|
|
signalled = id;
|
|
match (stoi32(s, b)) {
|
|
case let v: i32 => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn ck_int(id: i32, s: str, b: base, want: int) void = {
|
|
signalled = id;
|
|
match (stoi(s, b)) {
|
|
case let v: int => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn ck_uint(id: i32, s: str, b: base, want: uint) void = {
|
|
signalled = id;
|
|
match (stou(s, b)) {
|
|
case let v: uint => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn ck_size(id: i32, s: str, b: base, want: size) void = {
|
|
signalled = id;
|
|
match (stoz(s, b)) {
|
|
case let v: size => if (v != want) { fail(); };
|
|
case let e: invalid => fail();
|
|
case let e: overflow => fail();
|
|
};
|
|
};
|
|
|
|
fn ck_int_ovf(id: i32, s: str, b: base) void = {
|
|
signalled = id;
|
|
match (stoi(s, b)) {
|
|
case let v: int => fail();
|
|
case let e: invalid => fail();
|
|
case let e: overflow => { };
|
|
};
|
|
};
|
|
|
|
fn ck_uint_ovf(id: i32, s: str, b: base) void = {
|
|
signalled = id;
|
|
match (stou(s, b)) {
|
|
case let v: uint => fail();
|
|
case let e: invalid => fail();
|
|
case let e: overflow => { };
|
|
};
|
|
};
|
|
|
|
// ref/hare/strconv/stoi.ha:56-79.
|
|
@test fn test_stoi64() void = {
|
|
cki_inv(1, "", base.DEC, 0);
|
|
cki_inv(2, "abc", base.DEC, 0);
|
|
cki_inv(3, "1a", base.DEC, 1);
|
|
cki_inv(4, "+", base.DEC, 1);
|
|
cki_inv(5, "-+", base.DEC, 1);
|
|
cki_inv(6, "-z", base.DEC, 1);
|
|
|
|
cki_ovf(7, "9223372036854775808", base.DEC);
|
|
cki_ovf(8, "-9223372036854775809", base.DEC);
|
|
|
|
cki(9, "0", base.DEC, 0);
|
|
cki(10, "1", base.DEC, 1);
|
|
cki(11, "+1", base.DEC, 1);
|
|
cki(12, "-1", base.DEC, -1);
|
|
cki(13, "9223372036854775807", base.DEC, 9223372036854775807i64);
|
|
// I64_MIN. Spelled -I64_MAX-1 (Hare's own two's-complement identity,
|
|
// stoi64 comment in stoi.ha:11) because the wwstage mis-lexes the
|
|
// direct literal -9223372036854775808 (and types.I64_MIN) to 0 —
|
|
// proj #245. The INPUT string is unaffected; stoi64 parses it to the
|
|
// correct value on both stages. This isolates the parse test from #245.
|
|
cki(14, "-9223372036854775808", base.DEC, -9223372036854775807i64 - 1i64);
|
|
|
|
// width wrapper boundaries (ref/hare/strconv/stoi.ha:74-78).
|
|
cki32_ovf(15, "2147483648", base.DEC);
|
|
cki32_ovf(16, "-2147483649", base.DEC);
|
|
cki32(17, "2147483647", base.DEC, 2147483647i32);
|
|
cki32(18, "-2147483648", base.DEC, -2147483648i32);
|
|
};
|
|
|
|
// ref/hare/strconv/stoi.ha:81-86.
|
|
@test fn test_stoi64_bases() void = {
|
|
cki(20, "-7f", base.HEX, -127i64); // -0x7f
|
|
cki(21, "7F", base.HEX, 127i64); // 0x7f
|
|
cki(22, "37", base.OCT, 31i64); // 0o37
|
|
cki(23, "-110101", base.BIN, -53i64); // -0b110101
|
|
};
|
|
|
|
// ref/hare/strconv/stou.ha:116-130.
|
|
@test fn test_stou64() void = {
|
|
cku_inv(30, "", base.DEC, 0);
|
|
cku_inv(31, "+", base.DEC, 1);
|
|
cku_inv(32, "+a", base.DEC, 1);
|
|
cku_inv(33, "abc", base.DEC, 0);
|
|
cku_inv(34, "1a", base.DEC, 1);
|
|
|
|
cku_ovf(35, "18446744073709551616", base.DEC);
|
|
cku_ovf(36, "184467440737095516150", base.DEC);
|
|
cku_ovf(37, "-1", base.DEC);
|
|
|
|
cku(38, "0", base.DEC, 0u64);
|
|
cku(39, "1", base.DEC, 1u64);
|
|
cku(40, "18446744073709551615", base.DEC, 18446744073709551615u64);
|
|
};
|
|
|
|
// ref/hare/strconv/stou.ha:132-138.
|
|
@test fn test_stou64_bases() void = {
|
|
cku(41, "f", base.HEX_LOWER, 15u64); // 0xf
|
|
cku(42, "7f", base.HEX, 127u64); // 0x7f
|
|
cku(43, "7F", base.HEX, 127u64); // 0x7f
|
|
cku(44, "37", base.OCT, 31u64); // 0o37
|
|
cku(45, "110101", base.BIN, 53u64); // 0b110101
|
|
};
|
|
|
|
// stoi / stou / stoz — int/uint/size machine-word wrappers
|
|
// (ref/hare/strconv/stoi.ha:53, stou.ha:107,113). ww's int/uint/size are
|
|
// 8B, so the iN/uN clamp is a no-op: the full i64/u64 range parses with
|
|
// no spurious overflow. That no-clamp fidelity is what these check.
|
|
@test fn test_stoi_stou_stoz() void = {
|
|
ck_int(50, "0", base.DEC, 0);
|
|
ck_int(51, "-1", base.DEC, -1);
|
|
ck_int(52, "9223372036854775807", base.DEC, 9223372036854775807i64: int); // I64_MAX fits int
|
|
ck_int_ovf(53, "9223372036854775808", base.DEC);
|
|
ck_int_ovf(54, "-9223372036854775809", base.DEC);
|
|
|
|
ck_uint(55, "0", base.DEC, 0u64: uint);
|
|
ck_uint(56, "18446744073709551615", base.DEC, 18446744073709551615u64: uint); // U64_MAX fits uint
|
|
ck_uint_ovf(57, "18446744073709551616", base.DEC);
|
|
ck_uint_ovf(58, "-1", base.DEC);
|
|
|
|
ck_size(59, "0", base.DEC, 0u64: size);
|
|
ck_size(60, "18446744073709551615", base.DEC, 18446744073709551615u64: size); // U64_MAX fits size
|
|
|
|
// bases route through the same parseint core.
|
|
ck_int(61, "-7f", base.HEX, -127i64: int); // -0x7f
|
|
ck_uint(62, "110101", base.BIN, 53u64: uint); // 0b110101
|
|
};
|
|
|
|
export fn main() i32 = {
|
|
test_stoi64();
|
|
test_stoi64_bases();
|
|
test_stou64();
|
|
test_stou64_bases();
|
|
test_stoi_stou_stoz();
|
|
return 0;
|
|
};
|