selfhost: ?/! postfix in parser + cgen; use ! in lex.ww escape path

Selfhost parser (lib/ww/parse/expr.ww) recognises postfix `?` and
`!` at the same level as `as`/`is`/`:`. Selfhost cgen
(selfhost/cmd/wcc/cgenexpr.ww) emits matching code: cmp AX against
the success tag (0 in legacy mode), branch over the propagate /
abort path, then unwrap (DX → AX, CX → BX for str). Mirrors the C
cgen but without the tag-remap loop — none of the selfhost code
that uses `?` today needs cross-shape remapping.

lib/ww/lex/lex.ww \\x escape handling switched from 5-line match
blocks to one-liners: ascii.digitval(c: rune)!. Both digits are
already validated by isxdigit above; the void variant is
unreachable, so `!` collapses correctly. 995 fixed-point gate
verifies the selfhost cgen produces the same `!` codegen as C cgen.
This commit is contained in:
2026-05-12 02:45:27 +09:00
parent d9041ab45e
commit dc8405429e
8 changed files with 396 additions and 72 deletions

View File

@@ -330,6 +330,22 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
cur = n;
continue;
};
// `e?` — propagate error variant up the stack.
// `e!` — abort on error variant.
if (p.curkind == TK_QUESTION) {
advance(p);
let n: *node = newnode(p.a, N_TRYPROP, pf, pl, pc);
n.lhs = cur;
cur = n;
continue;
};
if (p.curkind == TK_NOT) {
advance(p);
let n: *node = newnode(p.a, N_TRYUNW, pf, pl, pc);
n.lhs = cur;
cur = n;
continue;
};
break;
};
return cur;