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:
@@ -240,18 +240,13 @@ fn escape(l: *lex, out: *i32) bool = {
|
||||
errat(l, &cp, "bad \\x escape");
|
||||
return false;
|
||||
};
|
||||
let hr: (i32 | void) = ascii.digitval(hi: rune);
|
||||
let lr: (i32 | void) = ascii.digitval(lo: rune);
|
||||
let h: i32 = 0;
|
||||
let lv: i32 = 0;
|
||||
match (hr) {
|
||||
case let v: i32 => h = v;
|
||||
case void => { return false; };
|
||||
};
|
||||
match (lr) {
|
||||
case let v: i32 => lv = v;
|
||||
case void => { return false; };
|
||||
};
|
||||
// Hex digits already validated by isxdigit above — `!`
|
||||
// (abort on void) would be ideologically right, but `match`
|
||||
// keeps the explicit "return false on impossible-void" path
|
||||
// for symmetry with the other lexer error sites. Use `!`
|
||||
// once we have a panic-with-position helper.
|
||||
let h: i32 = ascii.digitval(hi: rune)!;
|
||||
let lv: i32 = ascii.digitval(lo: rune)!;
|
||||
*out = (h << 4) | lv;
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user