ww: add Hare-style is/as postfix ops on tagged unions

`e is T` returns bool (variant tag == T's index); `e as T` unwraps
to T or exit(1) on mismatch. Postfix, same precedence as `:` cast.
TK_IS / N_TYPETEST / N_TYPEASSERT appended at the tail of their
enums so every prior numeric value stays unchanged — the
990_selfhost wwdump-diff stays byte-clean.

Cgen mirrors the match-case slot-based load (tag at +0, value at
+8/+16), so an N_IDENT tagged-union local works just like a
match scrutinee. Selfhost cgen inlines the slot resolution
because the wwstage cgen drops sign bits on `*i32` output
parameters in this position.

Renames `errors.is` -> `errors.equal` (the only naming collision;
the existing comment already noted it shared shape with
strings.equal/bytes.equal).
This commit is contained in:
2026-05-11 23:21:08 +09:00
parent 8899ce5621
commit dd188ca460
16 changed files with 614 additions and 15 deletions

View File

@@ -105,7 +105,12 @@ def TK_LARROW: i32 = 79;
def TK_ARROW: i32 = 80;
def TK_FATARROW: i32 = 81;
def TK_LAST: i32 = 82;
// Appended at the tail (not grouped with the keyword block) so every
// pre-existing TK_* value stays unchanged — the 990_selfhost test
// diffs wwdump output against the C side, byte for byte.
def TK_IS: i32 = 82;
def TK_LAST: i32 = 83;
// ---- Pos / Tok --------------------------------------------------------
//
@@ -164,6 +169,7 @@ export fn kwlookup(p: *u8, n: i32) i32 = {
if (streqn(p, "fn", n)) { return TK_FN; };
if (streqn(p, "for", n)) { return TK_FOR; };
if (streqn(p, "if", n)) { return TK_IF; };
if (streqn(p, "is", n)) { return TK_IS; };
if (streqn(p, "let", n)) { return TK_LET; };
if (streqn(p, "match", n)) { return TK_MATCH; };
if (streqn(p, "nil", n)) { return TK_NIL; };
@@ -215,6 +221,7 @@ export fn tokname(k: i32) str = {
if (k == TK_TRUE) { return "true"; };
if (k == TK_FALSE) { return "false"; };
if (k == TK_AS) { return "as"; };
if (k == TK_IS) { return "is"; };
if (k == TK_STATIC) { return "static"; };
if (k == TK_MATCH) { return "match"; };
if (k == TK_CONST) { return "const"; };