ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI)
This commit is contained in:
@@ -10,4 +10,4 @@ This directory is **not** a Hare-style stdlib module — it's a compiler-fronten
|
||||
When porting from `cmd/wcc/*.c`:
|
||||
- Keep the same data layout. The selfhost goal is byte-compatible structures so dump/inspect tools work either way.
|
||||
- Read `cmd/wcc/ww.h` first for canonical field names and ordering.
|
||||
- See `selfhost/CLAUDE.md` for the wwstage cgen traps to avoid (two-level field write, `(scalar,str)` tuple return, `def : str`, undersized `amalloc`).
|
||||
- See `selfhost/CLAUDE.md` for the wwstage cgen traps to avoid (undersized `amalloc`).
|
||||
|
||||
@@ -281,9 +281,17 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
|
||||
advance(p);
|
||||
let n: *node = newnode(p.a, N_DOT, pf, pl, pc);
|
||||
n.lhs = cur;
|
||||
let id: str;
|
||||
expectident(p, &id);
|
||||
n.str = id;
|
||||
// Hare-style tuple field access: `t.0`, `t.1`. The
|
||||
// numeric literal becomes the field name string so the
|
||||
// cgen tuple-positional path matches `cmd/wcc/parse.c`.
|
||||
if (p.curkind == TK_INT) {
|
||||
n.str = p.curtext;
|
||||
advance(p);
|
||||
} else {
|
||||
let id: str;
|
||||
expectident(p, &id);
|
||||
n.str = id;
|
||||
};
|
||||
cur = n;
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,42 @@ fn parseletlocal(p: *parser) *node = {
|
||||
let is_const: i32 = 0;
|
||||
if (p.curkind == TK_CONST) { is_const = 1; };
|
||||
advance(p);
|
||||
|
||||
// Hare-style tuple destructure: `let (a, b) = expr;`.
|
||||
// Types are optional per binding (matches C parser; Hare itself
|
||||
// doesn't allow types here, but cmd/wcc/parse.c does).
|
||||
if (p.curkind == TK_LPAREN) {
|
||||
advance(p);
|
||||
let m: *node = newnode(p.a, N_MLET, pf, pl, pc);
|
||||
let head: *node = nil;
|
||||
let tail: *node = nil;
|
||||
for (true) {
|
||||
let lpf: str = p.curfile;
|
||||
let lpl: i32 = p.curline;
|
||||
let lpc: i32 = p.curcol;
|
||||
let l: *node = newnode(p.a, N_LET, lpf, lpl, lpc);
|
||||
let id: str;
|
||||
expectbindname(p, &id);
|
||||
l.str = id;
|
||||
if (accepttok(p, TK_COLON)) { l.lhs = parsetype(p); };
|
||||
if (head == nil) { head = l; }
|
||||
else { tail.next = l; };
|
||||
tail = l;
|
||||
if (!accepttok(p, TK_COMMA)) { break; };
|
||||
};
|
||||
expecttok(p, TK_RPAREN, "expected ')' in let destructure");
|
||||
expecttok(p, TK_ASSIGN, "expected '=' after let destructure");
|
||||
m.rhs = parseexpr(p);
|
||||
expecttok(p, TK_SEMI, "expected ';' after let");
|
||||
m.list = head;
|
||||
if (is_const != 0) {
|
||||
m.op = TK_CONST;
|
||||
let lc: *node = head;
|
||||
for (lc != nil) { lc.op = TK_CONST; lc = lc.next; };
|
||||
};
|
||||
return m;
|
||||
};
|
||||
|
||||
let n: *node = newnode(p.a, N_LET, pf, pl, pc);
|
||||
let id: str;
|
||||
expectbindname(p, &id);
|
||||
@@ -19,6 +55,36 @@ fn parseletlocal(p: *parser) *node = {
|
||||
if (accepttok(p, TK_COLON)) {
|
||||
n.lhs = parsetype(p);
|
||||
};
|
||||
// Comma-multi-let: `let n, s = call();` (ww extension over Hare).
|
||||
// Collects (name, type) pairs, then '=' rhs. Each binding gets
|
||||
// its own N_LET; the wrapping N_MLET carries the rhs.
|
||||
if (p.curkind == TK_COMMA) {
|
||||
let m: *node = newnode(p.a, N_MLET, pf, pl, pc);
|
||||
let head: *node = n;
|
||||
let tail: *node = n;
|
||||
for (accepttok(p, TK_COMMA)) {
|
||||
let lpf: str = p.curfile;
|
||||
let lpl: i32 = p.curline;
|
||||
let lpc: i32 = p.curcol;
|
||||
let l: *node = newnode(p.a, N_LET, lpf, lpl, lpc);
|
||||
let id2: str;
|
||||
expectbindname(p, &id2);
|
||||
l.str = id2;
|
||||
if (accepttok(p, TK_COLON)) { l.lhs = parsetype(p); };
|
||||
tail.next = l;
|
||||
tail = l;
|
||||
};
|
||||
expecttok(p, TK_ASSIGN, "expected '=' after let names");
|
||||
m.rhs = parseexpr(p);
|
||||
expecttok(p, TK_SEMI, "expected ';' after let");
|
||||
m.list = head;
|
||||
if (is_const != 0) {
|
||||
m.op = TK_CONST;
|
||||
let lc: *node = head;
|
||||
for (lc != nil) { lc.op = TK_CONST; lc = lc.next; };
|
||||
};
|
||||
return m;
|
||||
};
|
||||
if (accepttok(p, TK_ASSIGN)) {
|
||||
n.rhs = parseexpr(p);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user