strconv: graduate to (T | invalid | overflow); add void expression
`type invalid = i32` (payload: byte index of first bad rune; mirrors
Hare's strconv::invalid = !size) and `type overflow = void` (Hare's
overflow = !void). stoi64/stou64 now return these instead of the
str-error placeholder. atoi64 dropped — lib/CLAUDE.md says graduate
in one go, don't keep both shapes around.
To produce the void variant payload, `void` is now a real
expression literal (TK_VOID kw, N_VOIDLIT). It evaluates to ty_void;
codegen emits MOVQ $0, AX. Both kinds are appended at the tail of
their enums to keep prior numeric values byte-stable for the
wwdump-diff fixtures.
check_file reorder: USE declarations are now installed in pass 1
alongside the type-decl placeholders so dotted type references
(`strconv.invalid` from a typedecl body) resolve. DEF/FN/LET silently
overwrite a USE-occupied slot — matches the old behavior where USE
silently no-op'd when a same-name fn/def existed (the conflict
manifested in selfhost main.combined.ww at `use parse;` colliding
with `export fn parse(a)`).
selfhost mirror: lib/ww/lex/tok.ww kwtab+name; lib/ww/ast.ww
N_VOIDLIT def+print; lib/ww/parse/{expr,parse}.ww TK_VOID handling;
selfhost/cmd/wcc/cgenexpr.ww N_VOIDLIT codegen.
This commit is contained in:
@@ -744,46 +744,53 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
" return acc;\n"
|
||||
"};", 13 }, /* 1 byte written to fd 1, plus len(\"write failed\")=12 */
|
||||
/* strconv.stoi64: fallible signed decimal. Two successful
|
||||
* parses contribute their values; one bad parse contributes
|
||||
* the error message length (20 = len(\"parse: invalid digit\")). */
|
||||
/* strconv.stoi64: fallible signed decimal, graduated to
|
||||
* (i64 | invalid | overflow). invalid carries the offending
|
||||
* index; overflow is the void variant. */
|
||||
{ "use strconv;\n"
|
||||
"type r_t = (i64 | strconv.invalid | strconv.overflow);\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let r1: (i64 | str) = strconv.stoi64(\"42\");\n"
|
||||
" let r2: (i64 | str) = strconv.stoi64(\"-7\");\n"
|
||||
" let r3: (i64 | str) = strconv.stoi64(\"abc\");\n"
|
||||
" let r1: r_t = strconv.stoi64(\"42\");\n"
|
||||
" let r2: r_t = strconv.stoi64(\"-7\");\n"
|
||||
" let r3: r_t = strconv.stoi64(\"abc\");\n"
|
||||
" let acc: i32 = 0;\n"
|
||||
" match (r1) {\n"
|
||||
" case let v: i64 => acc += v: i32;\n"
|
||||
" case let e: str => acc += -100;\n"
|
||||
" case let e: strconv.invalid => acc += -100;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" match (r2) {\n"
|
||||
" case let v: i64 => acc += v: i32;\n"
|
||||
" case let e: str => acc += -100;\n"
|
||||
" case let e: strconv.invalid => acc += -100;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" match (r3) {\n"
|
||||
" case let v: i64 => acc += -100;\n"
|
||||
" case let e: str => acc += e.len: i32;\n"
|
||||
" case let e: strconv.invalid => acc += e: i32;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" return acc;\n"
|
||||
"};", 55 }, /* 42 + (-7) + 20 */
|
||||
/* strconv.stou64: success path 123, error path captures
|
||||
* len(\"parse: invalid digit\") = 20 for the leading-sign reject. */
|
||||
"};", 35 }, /* 42 + (-7) + 0 (invalid at index 0 in \"abc\") */
|
||||
/* strconv.stou64: success path; leading-sign rejected with
|
||||
* invalid carrying the offending index. */
|
||||
{ "use strconv;\n"
|
||||
"type r_t = (u64 | strconv.invalid | strconv.overflow);\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let r1: (u64 | str) = strconv.stou64(\"123\");\n"
|
||||
" let r2: (u64 | str) = strconv.stou64(\"-1\");\n"
|
||||
" let r1: r_t = strconv.stou64(\"123\");\n"
|
||||
" let r2: r_t = strconv.stou64(\"-1\");\n"
|
||||
" let acc: i32 = 0;\n"
|
||||
" match (r1) {\n"
|
||||
" case let v: u64 => acc += v: i32;\n"
|
||||
" case let e: str => acc += -100;\n"
|
||||
" case let e: strconv.invalid => acc += -100;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" match (r2) {\n"
|
||||
" case let v: u64 => acc += -100;\n"
|
||||
" case let e: str => acc += e.len: i32;\n"
|
||||
" case let e: strconv.invalid => acc += e: i32;\n"
|
||||
" case let e: strconv.overflow => acc += -200;\n"
|
||||
" };\n"
|
||||
" return acc;\n"
|
||||
"};", 143 }, /* 123 + 20 */
|
||||
"};", 123 }, /* 123 + 0 (invalid at index 0 in \"-1\") */
|
||||
/* strings.byteindex and strings.index: now (i32 | void). */
|
||||
{ "use strings;\n"
|
||||
"fn pick(r: (i32 | void), miss: i32) i32 = {\n"
|
||||
|
||||
Reference in New Issue
Block a user