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:
@@ -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); };
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user