lib/strconv: parseint sign+overflow core; stoi64/stou64 fidelity (strconv-int fold-1 C1)
Port ref/hare/strconv/stou.ha:8-65 (rune_to_integer + parseint) and the stoi64/stou64 fidelity rewrite (stoi.ha:9-17, stou.ha:70-76) over the old digval loop. parseint is the shared sign + per-digit + multiply-overflow core returning ((bool, u64) | invalid | overflow); stoi64/stou64 destructure its `(sign, u)` tuple-in-union result — the shape unblocked by #242/#241. Wins over the prior ad-hoc parse: leading '+' accepted, '-' on stou64 is overflow (not silently dropped), wraparound overflow detection (n < old), and the invalid payload carries the offending byte index per Hare. Tests: lib/strconv/test/inttest.ww (run via test/wcc/922_strconv_int_run.c), inline per-case checks mirroring Hare's assert sequences stoi.ha:56-86 / stou.ha:116-138 (Hare's strconv int tests are flat sequences, not row tables; feedback_test_match_hare_source). Covers valid dec/hex/oct/bin, +/- sign, invalid+index, overflow, and U64_MAX / I64_MAX / I64_MIN boundaries. The I64_MIN expectation is spelled -I64_MAX-1 (Hare's own two's-complement identity) to isolate the test from #245 (wwstage mis-lexes the literal 9223372036854775808 -> 0); the parse INPUT is unaffected and yields the correct value on both stages. combined.ww regen: strconv is compiler-imported (via fmt), so w6c + wwdump main.combined.ww are regenerated.
This commit is contained in:
@@ -1258,8 +1258,11 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
" return acc;\n"
|
||||
"};", 35 }, /* 42 + (-7) + 0 (invalid at index 0 in \"abc\") */
|
||||
/* strconv.stou64: success path; leading-sign rejected with
|
||||
* invalid carrying the offending index. */
|
||||
/* strconv.stou64: success path; a leading '-' is rejected with
|
||||
* overflow per Hare (ref/hare/strconv/stou.ha:72-74 — parseint
|
||||
* accepts the sign, stou64 then rejects sign==true as overflow).
|
||||
* Updated from the prior ad-hoc parse, which mis-reported it as
|
||||
* invalid(index 0) (strconv-int fold-1 fidelity fix). */
|
||||
{ "import strconv;\n"
|
||||
"type r_t = (u64 | strconv.invalid | strconv.overflow);\n"
|
||||
"fn main() i32 = {\n"
|
||||
@@ -1272,12 +1275,12 @@ static const struct row rows[] = {
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" match (r2) {\n"
|
||||
" case let v: u64 => acc += -100;\n"
|
||||
" case let e: strconv.invalid => acc += e: i32;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" case let v: u64 => acc += 100;\n"
|
||||
" case let e: strconv.invalid => acc += 200;\n"
|
||||
" case let e: strconv.overflow => acc += 7;\n"
|
||||
" };\n"
|
||||
" return acc;\n"
|
||||
"};", 123 }, /* 123 + 0 (invalid at index 0 in \"-1\") */
|
||||
"};", 130 }, /* 123 + 7: \"-1\" is overflow (not invalid/success) */
|
||||
/* strings.byteindex with (str | rune) needle: returns (i32 | void). */
|
||||
{ "import strings;\n"
|
||||
"fn pick(r: (i32 | void), miss: i32) i32 = {\n"
|
||||
|
||||
54
test/wcc/922_strconv_int_run.c
Normal file
54
test/wcc/922_strconv_int_run.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 922_strconv_int_run — execute the lib/strconv/test/inttest fixture
|
||||
* under the C-side `ww run` driver and assert exit 0.
|
||||
*
|
||||
* Same thin-wrapper shape as 922_decimal_run / 909_stof_run: inttest.ww
|
||||
* carries its own `export fn main()` that drives the @test fns and
|
||||
* signals which case failed via the exit code (signalled + 10), so a
|
||||
* non-zero exit pinpoints the failing scenario.
|
||||
*
|
||||
* The fixture lives in lib/strconv/test/ (not lib/strconv/) so
|
||||
* `import strconv` resolves to the lib/strconv DIRECTORY rather than
|
||||
* shadowing on the strconv.ww FILE — same rationale as 922_decimal_run.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[1024];
|
||||
if (bin[0] != '/') {
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||||
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
|
||||
bin = absbin;
|
||||
}
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||||
|
||||
const char *src = "lib/strconv/test/inttest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "strconv_int_run FAIL: %s exited %d\n", src, rc);
|
||||
return 1;
|
||||
}
|
||||
printf("strconv_int_run: %s ok\n", src);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user