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:
@@ -222,6 +222,16 @@ parsetype(Parser *p)
|
||||
n->lhs = parsetype(p);
|
||||
return n;
|
||||
}
|
||||
case TK_VOID: {
|
||||
/* `void` keyword in type-expr context. Synthesise an
|
||||
* N_TNAME so type-resolution treats it like any other
|
||||
* primitive name. */
|
||||
Node *n = newnode(p->a, N_TNAME, pp);
|
||||
n->str = "void";
|
||||
n->strlen = 4;
|
||||
advance(p);
|
||||
return n;
|
||||
}
|
||||
case TK_IDENT: {
|
||||
Node *n = newnode(p->a, N_TNAME, pp);
|
||||
n->str = p->cur.text;
|
||||
@@ -455,6 +465,7 @@ parseprimary(Parser *p)
|
||||
case TK_TRUE: advance(p); return newnode(p->a, N_TRUE, pp);
|
||||
case TK_FALSE: advance(p); return newnode(p->a, N_FALSE, pp);
|
||||
case TK_NIL: advance(p); return newnode(p->a, N_NIL, pp);
|
||||
case TK_VOID: advance(p); return newnode(p->a, N_VOIDLIT, pp);
|
||||
case TK_UNDER: {
|
||||
/* Bare `_` — valid only as a discard lvalue. We yield an N_IDENT
|
||||
* with empty str; the checker rejects it outside assignment
|
||||
|
||||
Reference in New Issue
Block a user