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