lib/ww/parse: drop redundant type annotations (Wave-1)

Drop 112 redundant `let x: T = rhs` annotations where the rhs already
infers T (newnode→*node, p.curfile/curtext→str, p.curline/curcol→i32,
accepttok/== →bool, parse*→*node). stmt.ww (75) + parse.ww (37).
Regenerate the two embedders' combined.ww (w6c, wwdump). Byte-id-neutral:
cstage-w6c asm of each combined.ww is identical pre/post.
This commit is contained in:
2026-06-02 21:27:09 +09:00
parent b45f7c40ac
commit 79e647b34d
4 changed files with 336 additions and 336 deletions

View File

@@ -73,7 +73,7 @@ fn accepttok(p: *parser, k: tkind) bool = {
};
fn errmsg(p: *parser, msg: str) void = {
let pre: str = "parse: ";
let pre = "parse: ";
os.write(2, pre.ptr, pre.len: u64);
os.write(2, msg.ptr, msg.len: u64);
os.write(2, "\n".ptr, 1u64);
@@ -138,21 +138,21 @@ fn joindotted(head: str, tail: str) str = {
};
fn parsetype(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
if (p.curkind == tkind.TK_NOT) {
// `!T` — Hare error-flagged type wrapper.
advance(p);
let n: *node = newnode(nkind.N_TBANG, pf, pl, pc);
let n = newnode(nkind.N_TBANG, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
if (p.curkind == tkind.TK_STAR) {
advance(p);
let n: *node = newnode(nkind.N_TPTR, pf, pl, pc);
let n = newnode(nkind.N_TPTR, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
@@ -161,11 +161,11 @@ fn parsetype(p: *parser) *node = {
advance(p);
if (p.curkind == tkind.TK_RBRACK) {
advance(p);
let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc);
let n = newnode(nkind.N_TSLICE, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc);
let n = newnode(nkind.N_TARRAY, pf, pl, pc);
// `[_]T` — length inferred from initialiser. n.rhs stays nil
// as the sentinel; the cgen path for nkind.N_LET fills it from the
// array literal's element count.
@@ -182,15 +182,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_STRUCT) {
advance(p);
expecttok(p, tkind.TK_LBRACE, "expected '{' after struct");
let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let n = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let fhead: *node = nil;
let ftail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let fpf: str = p.curfile;
let fpl: i32 = p.curline;
let fpc: i32 = p.curcol;
let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fpf = p.curfile;
let fpl = p.curline;
let fpc = p.curcol;
let f = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fid: str;
expectident(p, &fid);
f.str = fid;
@@ -211,7 +211,7 @@ fn parsetype(p: *parser) *node = {
// nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil
// (auto-increment when omitted).
advance(p);
let n: *node = newnode(nkind.N_TENUM, pf, pl, pc);
let n = newnode(nkind.N_TENUM, pf, pl, pc);
if (p.curkind != tkind.TK_LBRACE) {
n.lhs = parsetype(p);
};
@@ -220,10 +220,10 @@ fn parsetype(p: *parser) *node = {
let mtail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let mpf: str = p.curfile;
let mpl: i32 = p.curline;
let mpc: i32 = p.curcol;
let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mpf = p.curfile;
let mpl = p.curline;
let mpc = p.curcol;
let m = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mid: str;
expectident(p, &mid);
m.str = mid;
@@ -242,15 +242,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_VOID) {
// `void` keyword in type-expr context — emit as nkind.N_TNAME so
// resolution treats it like any other primitive name.
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let n = newnode(nkind.N_TNAME, pf, pl, pc);
n.str = "void";
advance(p);
return n;
};
if (p.curkind == tkind.TK_IDENT) {
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let acc: str = p.curtext;
let n = newnode(nkind.N_TNAME, pf, pl, pc);
let acc = p.curtext;
advance(p);
// Dotted path collapse: pkg.Type → single TNAME with the
// joined string. Mirrors C parsetype's loop.
@@ -273,16 +273,16 @@ fn parsetype(p: *parser) *node = {
// tag the spread on node.op = TK_ELLIPSIS so resolve_type
// can distinguish intent. Mirrors C parsetype.
advance(p);
let firstspread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let first: *node = parsetype(p);
let firstspread = accepttok(p, tkind.TK_ELLIPSIS);
let first = parsetype(p);
if (firstspread) { first.op = tkind.TK_ELLIPSIS; };
if (accepttok(p, tkind.TK_PIPE)) {
let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head: *node = first;
let tail: *node = first;
let n = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head = first;
let tail = first;
for (true) {
let spread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let e: *node = parsetype(p);
let spread = accepttok(p, tkind.TK_ELLIPSIS);
let e = parsetype(p);
if (spread) { e.op = tkind.TK_ELLIPSIS; };
tail.next = e;
tail = e;
@@ -305,14 +305,14 @@ fn parsetype(p: *parser) *node = {
// layer, and exprtype must return shared element-type nodes
// (sym.decl.lhs, struct field's .lhs, another N_TTUPLE element)
// without corrupting source ASTs.
let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap: *node = newnode(nkind.N_TPARAM, pf, pl, pc);
let n = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap = newnode(nkind.N_TPARAM, pf, pl, pc);
firstwrap.lhs = first;
let head: *node = firstwrap;
let tail: *node = firstwrap;
let head = firstwrap;
let tail = firstwrap;
for (true) {
let e: *node = parsetype(p);
let w: *node = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
let e = parsetype(p);
let w = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
w.lhs = e;
tail.next = w;
tail = w;
@@ -327,7 +327,7 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_FN) {
advance(p);
expecttok(p, tkind.TK_LPAREN, "expected '(' after fn in type");
let n: *node = newnode(nkind.N_TFN, pf, pl, pc);
let n = newnode(nkind.N_TFN, pf, pl, pc);
// Anonymous-or-named params: parseparams handles named only;
// for fn-type expressions the C parser allows IDENT-less
// (anonymous) params. Stub: only named params for now.
@@ -390,7 +390,7 @@ fn isassignop(k: tkind) bool = {
// are resolved by the two-pass checker — no body-less prototypes needed.
export fn parsefile(p: *parser) *node = {
let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let f = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_EOF) {
@@ -411,7 +411,7 @@ export fn parsefile(p: *parser) *node = {
p.curmod = name;
continue;
};
let attrs: *node = parseattrs(p);
let attrs = parseattrs(p);
let exported: i32 = 0;
if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); };

View File

@@ -6,9 +6,9 @@ import os;
import tok;
fn parseletlocal(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `let` or `const`. Const-bound locals are marked via n.op = tkind.TK_CONST.
let is_const: i32 = 0;
if (p.curkind == tkind.TK_CONST) { is_const = 1; };
@@ -19,14 +19,14 @@ fn parseletlocal(p: *parser) *node = {
// doesn't allow types here, but cmd/wcc/parse.c does).
if (p.curkind == tkind.TK_LPAREN) {
advance(p);
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let m = newnode(nkind.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(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id: str;
expectbindname(p, &id);
l.str = id;
@@ -43,13 +43,13 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
};
let n: *node = newnode(nkind.N_LET, pf, pl, pc);
let n = newnode(nkind.N_LET, pf, pl, pc);
let id: str;
expectbindname(p, &id);
n.str = id;
@@ -60,14 +60,14 @@ fn parseletlocal(p: *parser) *node = {
// Collects (name, type) pairs, then '=' rhs. Each binding gets
// its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs.
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let head: *node = n;
let tail: *node = n;
let m = newnode(nkind.N_MLET, pf, pl, pc);
let head = n;
let tail = n;
for (accepttok(p, tkind.TK_COMMA)) {
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id2: str;
expectbindname(p, &id2);
l.str = id2;
@@ -81,7 +81,7 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
@@ -95,16 +95,16 @@ fn parseletlocal(p: *parser) *node = {
};
fn parseblock(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
expecttok(p, tkind.TK_LBRACE, "expected '{' to open block");
let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc);
let blk = newnode(nkind.N_BLOCK, pf, pl, pc);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (head == nil) { head = s; tail = s; }
else { tail.next = s; tail = s; };
@@ -116,12 +116,12 @@ fn parseblock(p: *parser) *node = {
};
fn parseif(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `if`
expecttok(p, tkind.TK_LPAREN, "expected '(' after if");
let n: *node = newnode(nkind.N_IF, pf, pl, pc);
let n = newnode(nkind.N_IF, pf, pl, pc);
n.cond = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition");
n.body = parseblock(p);
@@ -136,9 +136,9 @@ fn parseif(p: *parser) *node = {
};
fn parsefor(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `for`
expecttok(p, tkind.TK_LPAREN, "expected '(' after for");
@@ -158,10 +158,10 @@ fn parsefor(p: *parser) *node = {
let names: *node = nil;
let ntail: *node = nil;
for (true) {
let npf: str = p.curfile;
let npl: i32 = p.curline;
let npc: i32 = p.curcol;
let e: *node = newnode(nkind.N_IDENT, npf, npl, npc);
let npf = p.curfile;
let npl = p.curline;
let npc = p.curcol;
let e = newnode(nkind.N_IDENT, npf, npl, npc);
let nm: str;
expectbindname(p, &nm);
e.str = nm;
@@ -172,7 +172,7 @@ fn parsefor(p: *parser) *node = {
};
expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names");
expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names");
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.list = names;
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -186,18 +186,18 @@ fn parsefor(p: *parser) *node = {
// range; otherwise build a synthetic LET for the C-style for-init
// with the consumed name baked in.
if (p.curkind == tkind.TK_IDENT || p.curkind == tkind.TK_UNDER) {
let isunder: bool = (p.curkind == tkind.TK_UNDER);
let isunder = (p.curkind == tkind.TK_UNDER);
let nm: str;
nm.ptr = nil; nm.len = 0;
if (!isunder) { nm = p.curtext; };
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
advance(p); // consume IDENT/UNDER
if (p.curkind == tkind.TK_DOTDOT) {
advance(p);
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.str = nm; // "" for `_`
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -208,12 +208,12 @@ fn parsefor(p: *parser) *node = {
// Not a range — finish the let manually and continue as
// a 3-clause for-init.
let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let first = newnode(nkind.N_LET, lpf, lpl, lpc);
first.str = nm;
if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); };
if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); };
expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let");
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let n = newnode(nkind.N_FOR, pf, pl, pc);
n.lhs = first;
n.cond = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for cond");
@@ -228,8 +228,8 @@ fn parsefor(p: *parser) *node = {
};
// for (cond) or for (cond; post)
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let first: *node = parseexpr(p);
let n = newnode(nkind.N_FOR, pf, pl, pc);
let first = parseexpr(p);
if (accepttok(p, tkind.TK_SEMI)) {
n.cond = first;
n.rhs = parseexpr(p);
@@ -247,29 +247,29 @@ fn parsefor(p: *parser) *node = {
};
fn parseswitch(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `switch`
expecttok(p, tkind.TK_LPAREN, "expected '(' after switch");
let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc);
let n = newnode(nkind.N_SWITCH, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression");
expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body");
let head: *node = nil;
let tail: *node = nil;
for (p.curkind == tkind.TK_CASE) {
let cpf: str = p.curfile;
let cpl: i32 = p.curline;
let cpc: i32 = p.curcol;
let cpf = p.curfile;
let cpl = p.curline;
let cpc = p.curcol;
advance(p); // past `case`
let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc);
let cs = newnode(nkind.N_CASE, cpf, cpl, cpc);
let eh: *node = nil;
let et: *node = nil;
if (p.curkind != tkind.TK_COLON) {
p.nocast = 1;
for (true) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (eh == nil) { eh = e; }
else { et.next = e; };
et = e;
@@ -284,14 +284,14 @@ fn parseswitch(p: *parser) *node = {
for (p.curkind != tkind.TK_CASE) {
if (p.curkind == tkind.TK_RBRACE) { break; };
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (bh == nil) { bh = s; }
else { bt.next = s; };
bt = s;
};
};
let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
let blk = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
blk.list = bh;
cs.body = blk;
if (head == nil) { head = cs; }
@@ -304,49 +304,49 @@ fn parseswitch(p: *parser) *node = {
};
fn parsestmt(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `static` is allowed on local lets per Hare; we accept and skip
// it (it doesn't change the AST shape).
if (p.curkind == tkind.TK_STATIC) { advance(p); };
if (p.curkind == tkind.TK_LBRACE) {
let b: *node = parseblock(p);
let b = parseblock(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after block");
return b;
};
if (p.curkind == tkind.TK_LET) { return parseletlocal(p); };
if (p.curkind == tkind.TK_CONST) { return parseletlocal(p); };
if (p.curkind == tkind.TK_IF) {
let n: *node = parseif(p);
let n = parseif(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after if");
return n;
};
if (p.curkind == tkind.TK_FOR) {
let n: *node = parsefor(p);
let n = parsefor(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for");
return n;
};
if (p.curkind == tkind.TK_SWITCH) {
let n: *node = parseswitch(p);
let n = parseswitch(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after switch");
return n;
};
if (p.curkind == tkind.TK_RETURN) {
advance(p);
let n: *node = newnode(nkind.N_RETURN, pf, pl, pc);
let n = newnode(nkind.N_RETURN, pf, pl, pc);
if (p.curkind != tkind.TK_SEMI) {
let first: *node = parseexpr(p);
let first = parseexpr(p);
// Hare-style multi-value: `return a, b;` becomes a
// tuple expression so codegen sees one rvalue.
if (p.curkind == tkind.TK_COMMA) {
let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc);
let t = newnode(nkind.N_TUPLE, pf, pl, pc);
t.list = first;
let tail: *node = first;
let tail = first;
for (accepttok(p, tkind.TK_COMMA)) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
tail.next = e;
tail = e;
};
@@ -360,14 +360,14 @@ fn parsestmt(p: *parser) *node = {
};
if (p.curkind == tkind.TK_DEFER) {
advance(p);
let n: *node = newnode(nkind.N_DEFER, pf, pl, pc);
let n = newnode(nkind.N_DEFER, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after defer");
return n;
};
if (p.curkind == tkind.TK_YIELD) {
advance(p);
let n: *node = newnode(nkind.N_YIELD, pf, pl, pc);
let n = newnode(nkind.N_YIELD, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after yield");
return n;
@@ -388,14 +388,14 @@ fn parsestmt(p: *parser) *node = {
// with parseexpr (matches the C side); subsequent lvalues go
// through parsebin(parseunary, 1) so the `=` stays for us to
// consume — parseexpr would absorb it.
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head: *node = e;
let tail: *node = e;
let m = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head = e;
let tail = e;
for (p.curkind == tkind.TK_COMMA) {
advance(p);
let lv: *node = parsebin(p, parseunary(p), 1);
let lv = parsebin(p, parseunary(p), 1);
tail.next = lv;
tail = lv;
};
@@ -405,7 +405,7 @@ fn parsestmt(p: *parser) *node = {
expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign");
return m;
};
let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
let n = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
n.lhs = e;
expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement");
return n;

View File

@@ -8716,7 +8716,7 @@ fn accepttok(p: *parser, k: tkind) bool = {
};
fn errmsg(p: *parser, msg: str) void = {
let pre: str = "parse: ";
let pre = "parse: ";
os.write(2, pre.ptr, pre.len: u64);
os.write(2, msg.ptr, msg.len: u64);
os.write(2, "\n".ptr, 1u64);
@@ -8781,21 +8781,21 @@ fn joindotted(head: str, tail: str) str = {
};
fn parsetype(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
if (p.curkind == tkind.TK_NOT) {
// `!T` — Hare error-flagged type wrapper.
advance(p);
let n: *node = newnode(nkind.N_TBANG, pf, pl, pc);
let n = newnode(nkind.N_TBANG, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
if (p.curkind == tkind.TK_STAR) {
advance(p);
let n: *node = newnode(nkind.N_TPTR, pf, pl, pc);
let n = newnode(nkind.N_TPTR, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
@@ -8804,11 +8804,11 @@ fn parsetype(p: *parser) *node = {
advance(p);
if (p.curkind == tkind.TK_RBRACK) {
advance(p);
let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc);
let n = newnode(nkind.N_TSLICE, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc);
let n = newnode(nkind.N_TARRAY, pf, pl, pc);
// `[_]T` — length inferred from initialiser. n.rhs stays nil
// as the sentinel; the cgen path for nkind.N_LET fills it from the
// array literal's element count.
@@ -8825,15 +8825,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_STRUCT) {
advance(p);
expecttok(p, tkind.TK_LBRACE, "expected '{' after struct");
let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let n = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let fhead: *node = nil;
let ftail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let fpf: str = p.curfile;
let fpl: i32 = p.curline;
let fpc: i32 = p.curcol;
let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fpf = p.curfile;
let fpl = p.curline;
let fpc = p.curcol;
let f = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fid: str;
expectident(p, &fid);
f.str = fid;
@@ -8854,7 +8854,7 @@ fn parsetype(p: *parser) *node = {
// nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil
// (auto-increment when omitted).
advance(p);
let n: *node = newnode(nkind.N_TENUM, pf, pl, pc);
let n = newnode(nkind.N_TENUM, pf, pl, pc);
if (p.curkind != tkind.TK_LBRACE) {
n.lhs = parsetype(p);
};
@@ -8863,10 +8863,10 @@ fn parsetype(p: *parser) *node = {
let mtail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let mpf: str = p.curfile;
let mpl: i32 = p.curline;
let mpc: i32 = p.curcol;
let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mpf = p.curfile;
let mpl = p.curline;
let mpc = p.curcol;
let m = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mid: str;
expectident(p, &mid);
m.str = mid;
@@ -8885,15 +8885,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_VOID) {
// `void` keyword in type-expr context — emit as nkind.N_TNAME so
// resolution treats it like any other primitive name.
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let n = newnode(nkind.N_TNAME, pf, pl, pc);
n.str = "void";
advance(p);
return n;
};
if (p.curkind == tkind.TK_IDENT) {
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let acc: str = p.curtext;
let n = newnode(nkind.N_TNAME, pf, pl, pc);
let acc = p.curtext;
advance(p);
// Dotted path collapse: pkg.Type → single TNAME with the
// joined string. Mirrors C parsetype's loop.
@@ -8916,16 +8916,16 @@ fn parsetype(p: *parser) *node = {
// tag the spread on node.op = TK_ELLIPSIS so resolve_type
// can distinguish intent. Mirrors C parsetype.
advance(p);
let firstspread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let first: *node = parsetype(p);
let firstspread = accepttok(p, tkind.TK_ELLIPSIS);
let first = parsetype(p);
if (firstspread) { first.op = tkind.TK_ELLIPSIS; };
if (accepttok(p, tkind.TK_PIPE)) {
let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head: *node = first;
let tail: *node = first;
let n = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head = first;
let tail = first;
for (true) {
let spread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let e: *node = parsetype(p);
let spread = accepttok(p, tkind.TK_ELLIPSIS);
let e = parsetype(p);
if (spread) { e.op = tkind.TK_ELLIPSIS; };
tail.next = e;
tail = e;
@@ -8948,14 +8948,14 @@ fn parsetype(p: *parser) *node = {
// layer, and exprtype must return shared element-type nodes
// (sym.decl.lhs, struct field's .lhs, another N_TTUPLE element)
// without corrupting source ASTs.
let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap: *node = newnode(nkind.N_TPARAM, pf, pl, pc);
let n = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap = newnode(nkind.N_TPARAM, pf, pl, pc);
firstwrap.lhs = first;
let head: *node = firstwrap;
let tail: *node = firstwrap;
let head = firstwrap;
let tail = firstwrap;
for (true) {
let e: *node = parsetype(p);
let w: *node = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
let e = parsetype(p);
let w = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
w.lhs = e;
tail.next = w;
tail = w;
@@ -8970,7 +8970,7 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_FN) {
advance(p);
expecttok(p, tkind.TK_LPAREN, "expected '(' after fn in type");
let n: *node = newnode(nkind.N_TFN, pf, pl, pc);
let n = newnode(nkind.N_TFN, pf, pl, pc);
// Anonymous-or-named params: parseparams handles named only;
// for fn-type expressions the C parser allows IDENT-less
// (anonymous) params. Stub: only named params for now.
@@ -9033,7 +9033,7 @@ fn isassignop(k: tkind) bool = {
// are resolved by the two-pass checker — no body-less prototypes needed.
export fn parsefile(p: *parser) *node = {
let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let f = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_EOF) {
@@ -9054,7 +9054,7 @@ export fn parsefile(p: *parser) *node = {
p.curmod = name;
continue;
};
let attrs: *node = parseattrs(p);
let attrs = parseattrs(p);
let exported: i32 = 0;
if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); };
@@ -9119,9 +9119,9 @@ import os;
import tok;
fn parseletlocal(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `let` or `const`. Const-bound locals are marked via n.op = tkind.TK_CONST.
let is_const: i32 = 0;
if (p.curkind == tkind.TK_CONST) { is_const = 1; };
@@ -9132,14 +9132,14 @@ fn parseletlocal(p: *parser) *node = {
// doesn't allow types here, but cmd/wcc/parse.c does).
if (p.curkind == tkind.TK_LPAREN) {
advance(p);
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let m = newnode(nkind.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(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id: str;
expectbindname(p, &id);
l.str = id;
@@ -9156,13 +9156,13 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
};
let n: *node = newnode(nkind.N_LET, pf, pl, pc);
let n = newnode(nkind.N_LET, pf, pl, pc);
let id: str;
expectbindname(p, &id);
n.str = id;
@@ -9173,14 +9173,14 @@ fn parseletlocal(p: *parser) *node = {
// Collects (name, type) pairs, then '=' rhs. Each binding gets
// its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs.
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let head: *node = n;
let tail: *node = n;
let m = newnode(nkind.N_MLET, pf, pl, pc);
let head = n;
let tail = n;
for (accepttok(p, tkind.TK_COMMA)) {
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id2: str;
expectbindname(p, &id2);
l.str = id2;
@@ -9194,7 +9194,7 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
@@ -9208,16 +9208,16 @@ fn parseletlocal(p: *parser) *node = {
};
fn parseblock(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
expecttok(p, tkind.TK_LBRACE, "expected '{' to open block");
let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc);
let blk = newnode(nkind.N_BLOCK, pf, pl, pc);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (head == nil) { head = s; tail = s; }
else { tail.next = s; tail = s; };
@@ -9229,12 +9229,12 @@ fn parseblock(p: *parser) *node = {
};
fn parseif(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `if`
expecttok(p, tkind.TK_LPAREN, "expected '(' after if");
let n: *node = newnode(nkind.N_IF, pf, pl, pc);
let n = newnode(nkind.N_IF, pf, pl, pc);
n.cond = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition");
n.body = parseblock(p);
@@ -9249,9 +9249,9 @@ fn parseif(p: *parser) *node = {
};
fn parsefor(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `for`
expecttok(p, tkind.TK_LPAREN, "expected '(' after for");
@@ -9271,10 +9271,10 @@ fn parsefor(p: *parser) *node = {
let names: *node = nil;
let ntail: *node = nil;
for (true) {
let npf: str = p.curfile;
let npl: i32 = p.curline;
let npc: i32 = p.curcol;
let e: *node = newnode(nkind.N_IDENT, npf, npl, npc);
let npf = p.curfile;
let npl = p.curline;
let npc = p.curcol;
let e = newnode(nkind.N_IDENT, npf, npl, npc);
let nm: str;
expectbindname(p, &nm);
e.str = nm;
@@ -9285,7 +9285,7 @@ fn parsefor(p: *parser) *node = {
};
expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names");
expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names");
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.list = names;
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -9299,18 +9299,18 @@ fn parsefor(p: *parser) *node = {
// range; otherwise build a synthetic LET for the C-style for-init
// with the consumed name baked in.
if (p.curkind == tkind.TK_IDENT || p.curkind == tkind.TK_UNDER) {
let isunder: bool = (p.curkind == tkind.TK_UNDER);
let isunder = (p.curkind == tkind.TK_UNDER);
let nm: str;
nm.ptr = nil; nm.len = 0;
if (!isunder) { nm = p.curtext; };
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
advance(p); // consume IDENT/UNDER
if (p.curkind == tkind.TK_DOTDOT) {
advance(p);
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.str = nm; // "" for `_`
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -9321,12 +9321,12 @@ fn parsefor(p: *parser) *node = {
// Not a range — finish the let manually and continue as
// a 3-clause for-init.
let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let first = newnode(nkind.N_LET, lpf, lpl, lpc);
first.str = nm;
if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); };
if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); };
expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let");
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let n = newnode(nkind.N_FOR, pf, pl, pc);
n.lhs = first;
n.cond = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for cond");
@@ -9341,8 +9341,8 @@ fn parsefor(p: *parser) *node = {
};
// for (cond) or for (cond; post)
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let first: *node = parseexpr(p);
let n = newnode(nkind.N_FOR, pf, pl, pc);
let first = parseexpr(p);
if (accepttok(p, tkind.TK_SEMI)) {
n.cond = first;
n.rhs = parseexpr(p);
@@ -9360,29 +9360,29 @@ fn parsefor(p: *parser) *node = {
};
fn parseswitch(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `switch`
expecttok(p, tkind.TK_LPAREN, "expected '(' after switch");
let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc);
let n = newnode(nkind.N_SWITCH, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression");
expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body");
let head: *node = nil;
let tail: *node = nil;
for (p.curkind == tkind.TK_CASE) {
let cpf: str = p.curfile;
let cpl: i32 = p.curline;
let cpc: i32 = p.curcol;
let cpf = p.curfile;
let cpl = p.curline;
let cpc = p.curcol;
advance(p); // past `case`
let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc);
let cs = newnode(nkind.N_CASE, cpf, cpl, cpc);
let eh: *node = nil;
let et: *node = nil;
if (p.curkind != tkind.TK_COLON) {
p.nocast = 1;
for (true) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (eh == nil) { eh = e; }
else { et.next = e; };
et = e;
@@ -9397,14 +9397,14 @@ fn parseswitch(p: *parser) *node = {
for (p.curkind != tkind.TK_CASE) {
if (p.curkind == tkind.TK_RBRACE) { break; };
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (bh == nil) { bh = s; }
else { bt.next = s; };
bt = s;
};
};
let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
let blk = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
blk.list = bh;
cs.body = blk;
if (head == nil) { head = cs; }
@@ -9417,49 +9417,49 @@ fn parseswitch(p: *parser) *node = {
};
fn parsestmt(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `static` is allowed on local lets per Hare; we accept and skip
// it (it doesn't change the AST shape).
if (p.curkind == tkind.TK_STATIC) { advance(p); };
if (p.curkind == tkind.TK_LBRACE) {
let b: *node = parseblock(p);
let b = parseblock(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after block");
return b;
};
if (p.curkind == tkind.TK_LET) { return parseletlocal(p); };
if (p.curkind == tkind.TK_CONST) { return parseletlocal(p); };
if (p.curkind == tkind.TK_IF) {
let n: *node = parseif(p);
let n = parseif(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after if");
return n;
};
if (p.curkind == tkind.TK_FOR) {
let n: *node = parsefor(p);
let n = parsefor(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for");
return n;
};
if (p.curkind == tkind.TK_SWITCH) {
let n: *node = parseswitch(p);
let n = parseswitch(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after switch");
return n;
};
if (p.curkind == tkind.TK_RETURN) {
advance(p);
let n: *node = newnode(nkind.N_RETURN, pf, pl, pc);
let n = newnode(nkind.N_RETURN, pf, pl, pc);
if (p.curkind != tkind.TK_SEMI) {
let first: *node = parseexpr(p);
let first = parseexpr(p);
// Hare-style multi-value: `return a, b;` becomes a
// tuple expression so codegen sees one rvalue.
if (p.curkind == tkind.TK_COMMA) {
let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc);
let t = newnode(nkind.N_TUPLE, pf, pl, pc);
t.list = first;
let tail: *node = first;
let tail = first;
for (accepttok(p, tkind.TK_COMMA)) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
tail.next = e;
tail = e;
};
@@ -9473,14 +9473,14 @@ fn parsestmt(p: *parser) *node = {
};
if (p.curkind == tkind.TK_DEFER) {
advance(p);
let n: *node = newnode(nkind.N_DEFER, pf, pl, pc);
let n = newnode(nkind.N_DEFER, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after defer");
return n;
};
if (p.curkind == tkind.TK_YIELD) {
advance(p);
let n: *node = newnode(nkind.N_YIELD, pf, pl, pc);
let n = newnode(nkind.N_YIELD, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after yield");
return n;
@@ -9501,14 +9501,14 @@ fn parsestmt(p: *parser) *node = {
// with parseexpr (matches the C side); subsequent lvalues go
// through parsebin(parseunary, 1) so the `=` stays for us to
// consume — parseexpr would absorb it.
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head: *node = e;
let tail: *node = e;
let m = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head = e;
let tail = e;
for (p.curkind == tkind.TK_COMMA) {
advance(p);
let lv: *node = parsebin(p, parseunary(p), 1);
let lv = parsebin(p, parseunary(p), 1);
tail.next = lv;
tail = lv;
};
@@ -9518,7 +9518,7 @@ fn parsestmt(p: *parser) *node = {
expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign");
return m;
};
let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
let n = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
n.lhs = e;
expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement");
return n;

View File

@@ -8716,7 +8716,7 @@ fn accepttok(p: *parser, k: tkind) bool = {
};
fn errmsg(p: *parser, msg: str) void = {
let pre: str = "parse: ";
let pre = "parse: ";
os.write(2, pre.ptr, pre.len: u64);
os.write(2, msg.ptr, msg.len: u64);
os.write(2, "\n".ptr, 1u64);
@@ -8781,21 +8781,21 @@ fn joindotted(head: str, tail: str) str = {
};
fn parsetype(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
if (p.curkind == tkind.TK_NOT) {
// `!T` — Hare error-flagged type wrapper.
advance(p);
let n: *node = newnode(nkind.N_TBANG, pf, pl, pc);
let n = newnode(nkind.N_TBANG, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
if (p.curkind == tkind.TK_STAR) {
advance(p);
let n: *node = newnode(nkind.N_TPTR, pf, pl, pc);
let n = newnode(nkind.N_TPTR, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
@@ -8804,11 +8804,11 @@ fn parsetype(p: *parser) *node = {
advance(p);
if (p.curkind == tkind.TK_RBRACK) {
advance(p);
let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc);
let n = newnode(nkind.N_TSLICE, pf, pl, pc);
n.lhs = parsetype(p);
return n;
};
let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc);
let n = newnode(nkind.N_TARRAY, pf, pl, pc);
// `[_]T` — length inferred from initialiser. n.rhs stays nil
// as the sentinel; the cgen path for nkind.N_LET fills it from the
// array literal's element count.
@@ -8825,15 +8825,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_STRUCT) {
advance(p);
expecttok(p, tkind.TK_LBRACE, "expected '{' after struct");
let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let n = newnode(nkind.N_TSTRUCT, pf, pl, pc);
let fhead: *node = nil;
let ftail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let fpf: str = p.curfile;
let fpl: i32 = p.curline;
let fpc: i32 = p.curcol;
let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fpf = p.curfile;
let fpl = p.curline;
let fpc = p.curcol;
let f = newnode(nkind.N_TFIELD, fpf, fpl, fpc);
let fid: str;
expectident(p, &fid);
f.str = fid;
@@ -8854,7 +8854,7 @@ fn parsetype(p: *parser) *node = {
// nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil
// (auto-increment when omitted).
advance(p);
let n: *node = newnode(nkind.N_TENUM, pf, pl, pc);
let n = newnode(nkind.N_TENUM, pf, pl, pc);
if (p.curkind != tkind.TK_LBRACE) {
n.lhs = parsetype(p);
};
@@ -8863,10 +8863,10 @@ fn parsetype(p: *parser) *node = {
let mtail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let mpf: str = p.curfile;
let mpl: i32 = p.curline;
let mpc: i32 = p.curcol;
let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mpf = p.curfile;
let mpl = p.curline;
let mpc = p.curcol;
let m = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc);
let mid: str;
expectident(p, &mid);
m.str = mid;
@@ -8885,15 +8885,15 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_VOID) {
// `void` keyword in type-expr context — emit as nkind.N_TNAME so
// resolution treats it like any other primitive name.
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let n = newnode(nkind.N_TNAME, pf, pl, pc);
n.str = "void";
advance(p);
return n;
};
if (p.curkind == tkind.TK_IDENT) {
let n: *node = newnode(nkind.N_TNAME, pf, pl, pc);
let acc: str = p.curtext;
let n = newnode(nkind.N_TNAME, pf, pl, pc);
let acc = p.curtext;
advance(p);
// Dotted path collapse: pkg.Type → single TNAME with the
// joined string. Mirrors C parsetype's loop.
@@ -8916,16 +8916,16 @@ fn parsetype(p: *parser) *node = {
// tag the spread on node.op = TK_ELLIPSIS so resolve_type
// can distinguish intent. Mirrors C parsetype.
advance(p);
let firstspread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let first: *node = parsetype(p);
let firstspread = accepttok(p, tkind.TK_ELLIPSIS);
let first = parsetype(p);
if (firstspread) { first.op = tkind.TK_ELLIPSIS; };
if (accepttok(p, tkind.TK_PIPE)) {
let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head: *node = first;
let tail: *node = first;
let n = newnode(nkind.N_TTAGGED, pf, pl, pc);
let head = first;
let tail = first;
for (true) {
let spread: bool = accepttok(p, tkind.TK_ELLIPSIS);
let e: *node = parsetype(p);
let spread = accepttok(p, tkind.TK_ELLIPSIS);
let e = parsetype(p);
if (spread) { e.op = tkind.TK_ELLIPSIS; };
tail.next = e;
tail = e;
@@ -8948,14 +8948,14 @@ fn parsetype(p: *parser) *node = {
// layer, and exprtype must return shared element-type nodes
// (sym.decl.lhs, struct field's .lhs, another N_TTUPLE element)
// without corrupting source ASTs.
let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap: *node = newnode(nkind.N_TPARAM, pf, pl, pc);
let n = newnode(nkind.N_TTUPLE, pf, pl, pc);
let firstwrap = newnode(nkind.N_TPARAM, pf, pl, pc);
firstwrap.lhs = first;
let head: *node = firstwrap;
let tail: *node = firstwrap;
let head = firstwrap;
let tail = firstwrap;
for (true) {
let e: *node = parsetype(p);
let w: *node = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
let e = parsetype(p);
let w = newnode(nkind.N_TPARAM, e.file, e.line, e.col);
w.lhs = e;
tail.next = w;
tail = w;
@@ -8970,7 +8970,7 @@ fn parsetype(p: *parser) *node = {
if (p.curkind == tkind.TK_FN) {
advance(p);
expecttok(p, tkind.TK_LPAREN, "expected '(' after fn in type");
let n: *node = newnode(nkind.N_TFN, pf, pl, pc);
let n = newnode(nkind.N_TFN, pf, pl, pc);
// Anonymous-or-named params: parseparams handles named only;
// for fn-type expressions the C parser allows IDENT-less
// (anonymous) params. Stub: only named params for now.
@@ -9033,7 +9033,7 @@ fn isassignop(k: tkind) bool = {
// are resolved by the two-pass checker — no body-less prototypes needed.
export fn parsefile(p: *parser) *node = {
let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let f = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_EOF) {
@@ -9054,7 +9054,7 @@ export fn parsefile(p: *parser) *node = {
p.curmod = name;
continue;
};
let attrs: *node = parseattrs(p);
let attrs = parseattrs(p);
let exported: i32 = 0;
if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); };
@@ -9119,9 +9119,9 @@ import os;
import tok;
fn parseletlocal(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `let` or `const`. Const-bound locals are marked via n.op = tkind.TK_CONST.
let is_const: i32 = 0;
if (p.curkind == tkind.TK_CONST) { is_const = 1; };
@@ -9132,14 +9132,14 @@ fn parseletlocal(p: *parser) *node = {
// doesn't allow types here, but cmd/wcc/parse.c does).
if (p.curkind == tkind.TK_LPAREN) {
advance(p);
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let m = newnode(nkind.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(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id: str;
expectbindname(p, &id);
l.str = id;
@@ -9156,13 +9156,13 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
};
let n: *node = newnode(nkind.N_LET, pf, pl, pc);
let n = newnode(nkind.N_LET, pf, pl, pc);
let id: str;
expectbindname(p, &id);
n.str = id;
@@ -9173,14 +9173,14 @@ fn parseletlocal(p: *parser) *node = {
// Collects (name, type) pairs, then '=' rhs. Each binding gets
// its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs.
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MLET, pf, pl, pc);
let head: *node = n;
let tail: *node = n;
let m = newnode(nkind.N_MLET, pf, pl, pc);
let head = n;
let tail = n;
for (accepttok(p, tkind.TK_COMMA)) {
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
let l = newnode(nkind.N_LET, lpf, lpl, lpc);
let id2: str;
expectbindname(p, &id2);
l.str = id2;
@@ -9194,7 +9194,7 @@ fn parseletlocal(p: *parser) *node = {
m.list = head;
if (is_const != 0) {
m.op = tkind.TK_CONST;
let lc: *node = head;
let lc = head;
for (lc != nil) { lc.op = tkind.TK_CONST; lc = lc.next; };
};
return m;
@@ -9208,16 +9208,16 @@ fn parseletlocal(p: *parser) *node = {
};
fn parseblock(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
expecttok(p, tkind.TK_LBRACE, "expected '{' to open block");
let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc);
let blk = newnode(nkind.N_BLOCK, pf, pl, pc);
let head: *node = nil;
let tail: *node = nil;
for (p.curkind != tkind.TK_RBRACE) {
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (head == nil) { head = s; tail = s; }
else { tail.next = s; tail = s; };
@@ -9229,12 +9229,12 @@ fn parseblock(p: *parser) *node = {
};
fn parseif(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `if`
expecttok(p, tkind.TK_LPAREN, "expected '(' after if");
let n: *node = newnode(nkind.N_IF, pf, pl, pc);
let n = newnode(nkind.N_IF, pf, pl, pc);
n.cond = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition");
n.body = parseblock(p);
@@ -9249,9 +9249,9 @@ fn parseif(p: *parser) *node = {
};
fn parsefor(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `for`
expecttok(p, tkind.TK_LPAREN, "expected '(' after for");
@@ -9271,10 +9271,10 @@ fn parsefor(p: *parser) *node = {
let names: *node = nil;
let ntail: *node = nil;
for (true) {
let npf: str = p.curfile;
let npl: i32 = p.curline;
let npc: i32 = p.curcol;
let e: *node = newnode(nkind.N_IDENT, npf, npl, npc);
let npf = p.curfile;
let npl = p.curline;
let npc = p.curcol;
let e = newnode(nkind.N_IDENT, npf, npl, npc);
let nm: str;
expectbindname(p, &nm);
e.str = nm;
@@ -9285,7 +9285,7 @@ fn parsefor(p: *parser) *node = {
};
expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names");
expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names");
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.list = names;
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -9299,18 +9299,18 @@ fn parsefor(p: *parser) *node = {
// range; otherwise build a synthetic LET for the C-style for-init
// with the consumed name baked in.
if (p.curkind == tkind.TK_IDENT || p.curkind == tkind.TK_UNDER) {
let isunder: bool = (p.curkind == tkind.TK_UNDER);
let isunder = (p.curkind == tkind.TK_UNDER);
let nm: str;
nm.ptr = nil; nm.len = 0;
if (!isunder) { nm = p.curtext; };
let lpf: str = p.curfile;
let lpl: i32 = p.curline;
let lpc: i32 = p.curcol;
let lpf = p.curfile;
let lpl = p.curline;
let lpc = p.curcol;
advance(p); // consume IDENT/UNDER
if (p.curkind == tkind.TK_DOTDOT) {
advance(p);
let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc);
let rng = newnode(nkind.N_FORRANGE, pf, pl, pc);
rng.str = nm; // "" for `_`
rng.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after for");
@@ -9321,12 +9321,12 @@ fn parsefor(p: *parser) *node = {
// Not a range — finish the let manually and continue as
// a 3-clause for-init.
let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc);
let first = newnode(nkind.N_LET, lpf, lpl, lpc);
first.str = nm;
if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); };
if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); };
expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let");
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let n = newnode(nkind.N_FOR, pf, pl, pc);
n.lhs = first;
n.cond = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for cond");
@@ -9341,8 +9341,8 @@ fn parsefor(p: *parser) *node = {
};
// for (cond) or for (cond; post)
let n: *node = newnode(nkind.N_FOR, pf, pl, pc);
let first: *node = parseexpr(p);
let n = newnode(nkind.N_FOR, pf, pl, pc);
let first = parseexpr(p);
if (accepttok(p, tkind.TK_SEMI)) {
n.cond = first;
n.rhs = parseexpr(p);
@@ -9360,29 +9360,29 @@ fn parsefor(p: *parser) *node = {
};
fn parseswitch(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
advance(p); // past `switch`
expecttok(p, tkind.TK_LPAREN, "expected '(' after switch");
let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc);
let n = newnode(nkind.N_SWITCH, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression");
expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body");
let head: *node = nil;
let tail: *node = nil;
for (p.curkind == tkind.TK_CASE) {
let cpf: str = p.curfile;
let cpl: i32 = p.curline;
let cpc: i32 = p.curcol;
let cpf = p.curfile;
let cpl = p.curline;
let cpc = p.curcol;
advance(p); // past `case`
let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc);
let cs = newnode(nkind.N_CASE, cpf, cpl, cpc);
let eh: *node = nil;
let et: *node = nil;
if (p.curkind != tkind.TK_COLON) {
p.nocast = 1;
for (true) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (eh == nil) { eh = e; }
else { et.next = e; };
et = e;
@@ -9397,14 +9397,14 @@ fn parseswitch(p: *parser) *node = {
for (p.curkind != tkind.TK_CASE) {
if (p.curkind == tkind.TK_RBRACE) { break; };
if (p.curkind == tkind.TK_EOF) { break; };
let s: *node = parsestmt(p);
let s = parsestmt(p);
if (s != nil) {
if (bh == nil) { bh = s; }
else { bt.next = s; };
bt = s;
};
};
let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
let blk = newnode(nkind.N_BLOCK, cpf, cpl, cpc);
blk.list = bh;
cs.body = blk;
if (head == nil) { head = cs; }
@@ -9417,49 +9417,49 @@ fn parseswitch(p: *parser) *node = {
};
fn parsestmt(p: *parser) *node = {
let pf: str = p.curfile;
let pl: i32 = p.curline;
let pc: i32 = p.curcol;
let pf = p.curfile;
let pl = p.curline;
let pc = p.curcol;
// `static` is allowed on local lets per Hare; we accept and skip
// it (it doesn't change the AST shape).
if (p.curkind == tkind.TK_STATIC) { advance(p); };
if (p.curkind == tkind.TK_LBRACE) {
let b: *node = parseblock(p);
let b = parseblock(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after block");
return b;
};
if (p.curkind == tkind.TK_LET) { return parseletlocal(p); };
if (p.curkind == tkind.TK_CONST) { return parseletlocal(p); };
if (p.curkind == tkind.TK_IF) {
let n: *node = parseif(p);
let n = parseif(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after if");
return n;
};
if (p.curkind == tkind.TK_FOR) {
let n: *node = parsefor(p);
let n = parsefor(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after for");
return n;
};
if (p.curkind == tkind.TK_SWITCH) {
let n: *node = parseswitch(p);
let n = parseswitch(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after switch");
return n;
};
if (p.curkind == tkind.TK_RETURN) {
advance(p);
let n: *node = newnode(nkind.N_RETURN, pf, pl, pc);
let n = newnode(nkind.N_RETURN, pf, pl, pc);
if (p.curkind != tkind.TK_SEMI) {
let first: *node = parseexpr(p);
let first = parseexpr(p);
// Hare-style multi-value: `return a, b;` becomes a
// tuple expression so codegen sees one rvalue.
if (p.curkind == tkind.TK_COMMA) {
let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc);
let t = newnode(nkind.N_TUPLE, pf, pl, pc);
t.list = first;
let tail: *node = first;
let tail = first;
for (accepttok(p, tkind.TK_COMMA)) {
let e: *node = parseexpr(p);
let e = parseexpr(p);
tail.next = e;
tail = e;
};
@@ -9473,14 +9473,14 @@ fn parsestmt(p: *parser) *node = {
};
if (p.curkind == tkind.TK_DEFER) {
advance(p);
let n: *node = newnode(nkind.N_DEFER, pf, pl, pc);
let n = newnode(nkind.N_DEFER, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after defer");
return n;
};
if (p.curkind == tkind.TK_YIELD) {
advance(p);
let n: *node = newnode(nkind.N_YIELD, pf, pl, pc);
let n = newnode(nkind.N_YIELD, pf, pl, pc);
n.lhs = parseexpr(p);
expecttok(p, tkind.TK_SEMI, "expected ';' after yield");
return n;
@@ -9501,14 +9501,14 @@ fn parsestmt(p: *parser) *node = {
// with parseexpr (matches the C side); subsequent lvalues go
// through parsebin(parseunary, 1) so the `=` stays for us to
// consume — parseexpr would absorb it.
let e: *node = parseexpr(p);
let e = parseexpr(p);
if (p.curkind == tkind.TK_COMMA) {
let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head: *node = e;
let tail: *node = e;
let m = newnode(nkind.N_MASSIGN, pf, pl, pc);
let head = e;
let tail = e;
for (p.curkind == tkind.TK_COMMA) {
advance(p);
let lv: *node = parsebin(p, parseunary(p), 1);
let lv = parsebin(p, parseunary(p), 1);
tail.next = lv;
tail = lv;
};
@@ -9518,7 +9518,7 @@ fn parsestmt(p: *parser) *node = {
expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign");
return m;
};
let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
let n = newnode(nkind.N_EXPRSTMT, pf, pl, pc);
n.lhs = e;
expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement");
return n;