diff --git a/lib/ww/ast.ww b/lib/ww/ast.ww index 77700d81..50920367 100644 --- a/lib/ww/ast.ww +++ b/lib/ww/ast.ww @@ -17,84 +17,88 @@ use tok; // Mirror of cmd/wcc/ww.h Nkind. Values must stay numerically equal so // the AST diff probe in 990_selfhost works. -def N_NONE: i32 = 0; +// Mirror of the C `Nkind` enum in cmd/wcc/ww.h. Numeric values are +// explicit and must stay in sync — the 990_selfhost test diffs +// astprint against the C side byte-for-byte. Tail-appended entries +// (TYPETEST onward) preserve every prior N_* value. +type nkind = enum i32 { + N_NONE = 0, -def N_INTLIT: i32 = 1; -def N_FLOATLIT: i32 = 2; -def N_STRLIT: i32 = 3; -def N_RUNELIT: i32 = 4; -def N_TRUE: i32 = 5; -def N_FALSE: i32 = 6; -def N_NIL: i32 = 7; -def N_IDENT: i32 = 8; + N_INTLIT = 1, + N_FLOATLIT = 2, + N_STRLIT = 3, + N_RUNELIT = 4, + N_TRUE = 5, + N_FALSE = 6, + N_NIL = 7, + N_IDENT = 8, -def N_BIN: i32 = 9; -def N_UN: i32 = 10; -def N_CALL: i32 = 11; -def N_INDEX: i32 = 12; -def N_DOT: i32 = 13; -def N_CAST: i32 = 14; -def N_STRUCTLIT:i32 = 15; -def N_ARRLIT: i32 = 16; -def N_FIELD: i32 = 17; -def N_ASSIGN: i32 = 18; -def N_ALLOC: i32 = 19; -def N_FREE: i32 = 20; -def N_RECV: i32 = 21; -def N_SLICE: i32 = 22; -def N_SPREAD: i32 = 23; + N_BIN = 9, + N_UN = 10, + N_CALL = 11, + N_INDEX = 12, + N_DOT = 13, + N_CAST = 14, + N_STRUCTLIT = 15, + N_ARRLIT = 16, + N_FIELD = 17, + N_ASSIGN = 18, + N_ALLOC = 19, + N_FREE = 20, + N_RECV = 21, + N_SLICE = 22, + N_SPREAD = 23, -def N_BLOCK: i32 = 24; -def N_EXPRSTMT: i32 = 25; -def N_LET: i32 = 26; -def N_RETURN: i32 = 27; -def N_IF: i32 = 28; -def N_FOR: i32 = 29; -def N_FORRANGE: i32 = 30; -def N_DEFER: i32 = 31; -def N_BREAK: i32 = 32; -def N_CONTINUE: i32 = 33; -def N_SWITCH: i32 = 34; -def N_CASE: i32 = 35; + N_BLOCK = 24, + N_EXPRSTMT = 25, + N_LET = 26, + N_RETURN = 27, + N_IF = 28, + N_FOR = 29, + N_FORRANGE = 30, + N_DEFER = 31, + N_BREAK = 32, + N_CONTINUE = 33, + N_SWITCH = 34, + N_CASE = 35, -def N_FILE: i32 = 36; -def N_USE: i32 = 37; -def N_DEF: i32 = 38; -def N_TYPEDECL: i32 = 39; -def N_FNDECL: i32 = 40; -def N_PARAM: i32 = 41; + N_FILE = 36, + N_USE = 37, + N_DEF = 38, + N_TYPEDECL = 39, + N_FNDECL = 40, + N_PARAM = 41, -def N_TNAME: i32 = 42; -def N_TPTR: i32 = 43; -def N_TSLICE: i32 = 44; -def N_TARRAY: i32 = 45; -def N_TFN: i32 = 46; -def N_TSTRUCT: i32 = 47; -def N_TFIELD: i32 = 48; -def N_TCHAN: i32 = 49; + N_TNAME = 42, + N_TPTR = 43, + N_TSLICE = 44, + N_TARRAY = 45, + N_TFN = 46, + N_TSTRUCT = 47, + N_TFIELD = 48, + N_TCHAN = 49, -def N_ATTR: i32 = 50; -def N_TTUPLE: i32 = 51; -def N_TTAGGED: i32 = 52; -def N_TUPLE: i32 = 53; -def N_MATCH: i32 = 54; -def N_MCASE: i32 = 55; -def N_TRYPROP: i32 = 56; -def N_TRYUNW: i32 = 57; -def N_MLET: i32 = 58; -def N_MASSIGN: i32 = 59; + N_ATTR = 50, + N_TTUPLE = 51, + N_TTAGGED = 52, + N_TUPLE = 53, + N_MATCH = 54, + N_MCASE = 55, + N_TRYPROP = 56, + N_TRYUNW = 57, + N_MLET = 58, + N_MASSIGN = 59, -// Appended at the tail to keep all prior N_* values stable. The -// 990_selfhost test diffs astprint against the C side byte-for-byte. -def N_TYPETEST: i32 = 60; -def N_TYPEASSERT: i32 = 61; -def N_VOIDLIT: i32 = 62; -def N_TBANG: i32 = 63; -def N_YIELD: i32 = 64; -def N_TENUM: i32 = 65; -def N_TENUMMEMBER: i32 = 66; + N_TYPETEST = 60, + N_TYPEASSERT = 61, + N_VOIDLIT = 62, + N_TBANG = 63, + N_YIELD = 64, + N_TENUM = 65, + N_TENUMMEMBER = 66, -def N_LAST: i32 = 67; + N_LAST = 67, +}; // ---- Node ------------------------------------------------------------- @@ -103,7 +107,7 @@ type node = struct { file: str, line: i32, col: i32, - op: i32, // for N_BIN / N_UN / N_ASSIGN + op: i32, // for nkind.N_BIN / nkind.N_UN / nkind.N_ASSIGN str: str, uval: u64, fval: f64, @@ -133,74 +137,74 @@ export fn newnode(a: *arena, k: i32, file: str, line: i32, col: i32) *node = { // ---- printer ---------------------------------------------------------- fn nkname(k: i32) str = { - if (k == N_NONE) { return "none"; }; - if (k == N_INTLIT) { return "int"; }; - if (k == N_FLOATLIT) { return "float"; }; - if (k == N_STRLIT) { return "str"; }; - if (k == N_RUNELIT) { return "rune"; }; - if (k == N_TRUE) { return "true"; }; - if (k == N_FALSE) { return "false"; }; - if (k == N_NIL) { return "nil"; }; - if (k == N_IDENT) { return "id"; }; - if (k == N_BIN) { return "bin"; }; - if (k == N_UN) { return "un"; }; - if (k == N_CALL) { return "call"; }; - if (k == N_INDEX) { return "index"; }; - if (k == N_DOT) { return "dot"; }; - if (k == N_CAST) { return "cast"; }; - if (k == N_STRUCTLIT) { return "structlit"; }; - if (k == N_ARRLIT) { return "arrlit"; }; - if (k == N_FIELD) { return "field"; }; - if (k == N_ASSIGN) { return "assign"; }; - if (k == N_ALLOC) { return "alloc"; }; - if (k == N_FREE) { return "free"; }; - if (k == N_RECV) { return "recv"; }; - if (k == N_SLICE) { return "slice"; }; - if (k == N_SPREAD) { return "spread"; }; - if (k == N_BLOCK) { return "block"; }; - if (k == N_EXPRSTMT) { return "exprstmt"; }; - if (k == N_LET) { return "let"; }; - if (k == N_RETURN) { return "return"; }; - if (k == N_IF) { return "if"; }; - if (k == N_FOR) { return "for"; }; - if (k == N_FORRANGE) { return "forrange"; }; - if (k == N_DEFER) { return "defer"; }; - if (k == N_BREAK) { return "break"; }; - if (k == N_CONTINUE) { return "continue"; }; - if (k == N_SWITCH) { return "switch"; }; - if (k == N_CASE) { return "case"; }; - if (k == N_FILE) { return "file"; }; - if (k == N_USE) { return "use"; }; - if (k == N_DEF) { return "def"; }; - if (k == N_TYPEDECL) { return "typedecl"; }; - if (k == N_FNDECL) { return "fn"; }; - if (k == N_PARAM) { return "param"; }; - if (k == N_TNAME) { return "tname"; }; - if (k == N_TPTR) { return "tptr"; }; - if (k == N_TSLICE) { return "tslice"; }; - if (k == N_TARRAY) { return "tarray"; }; - if (k == N_TFN) { return "tfn"; }; - if (k == N_TSTRUCT) { return "tstruct"; }; - if (k == N_TFIELD) { return "tfield"; }; - if (k == N_TCHAN) { return "tchan"; }; - if (k == N_ATTR) { return "attr"; }; - if (k == N_TTUPLE) { return "ttuple"; }; - if (k == N_TTAGGED) { return "ttagged"; }; - if (k == N_TUPLE) { return "tuple"; }; - if (k == N_MATCH) { return "match"; }; - if (k == N_MCASE) { return "mcase"; }; - if (k == N_TRYPROP) { return "tryprop"; }; - if (k == N_TRYUNW) { return "tryunw"; }; - if (k == N_MLET) { return "mlet"; }; - if (k == N_MASSIGN) { return "massign"; }; - if (k == N_TYPETEST) { return "typetest"; }; - if (k == N_TYPEASSERT) { return "typeassert"; }; - if (k == N_VOIDLIT) { return "voidlit"; }; - if (k == N_TBANG) { return "tbang"; }; - if (k == N_YIELD) { return "yield"; }; - if (k == N_TENUM) { return "tenum"; }; - if (k == N_TENUMMEMBER) { return "tenummember"; }; - if (k == N_LAST) { return "last"; }; + if (k == nkind.N_NONE) { return "none"; }; + if (k == nkind.N_INTLIT) { return "int"; }; + if (k == nkind.N_FLOATLIT) { return "float"; }; + if (k == nkind.N_STRLIT) { return "str"; }; + if (k == nkind.N_RUNELIT) { return "rune"; }; + if (k == nkind.N_TRUE) { return "true"; }; + if (k == nkind.N_FALSE) { return "false"; }; + if (k == nkind.N_NIL) { return "nil"; }; + if (k == nkind.N_IDENT) { return "id"; }; + if (k == nkind.N_BIN) { return "bin"; }; + if (k == nkind.N_UN) { return "un"; }; + if (k == nkind.N_CALL) { return "call"; }; + if (k == nkind.N_INDEX) { return "index"; }; + if (k == nkind.N_DOT) { return "dot"; }; + if (k == nkind.N_CAST) { return "cast"; }; + if (k == nkind.N_STRUCTLIT) { return "structlit"; }; + if (k == nkind.N_ARRLIT) { return "arrlit"; }; + if (k == nkind.N_FIELD) { return "field"; }; + if (k == nkind.N_ASSIGN) { return "assign"; }; + if (k == nkind.N_ALLOC) { return "alloc"; }; + if (k == nkind.N_FREE) { return "free"; }; + if (k == nkind.N_RECV) { return "recv"; }; + if (k == nkind.N_SLICE) { return "slice"; }; + if (k == nkind.N_SPREAD) { return "spread"; }; + if (k == nkind.N_BLOCK) { return "block"; }; + if (k == nkind.N_EXPRSTMT) { return "exprstmt"; }; + if (k == nkind.N_LET) { return "let"; }; + if (k == nkind.N_RETURN) { return "return"; }; + if (k == nkind.N_IF) { return "if"; }; + if (k == nkind.N_FOR) { return "for"; }; + if (k == nkind.N_FORRANGE) { return "forrange"; }; + if (k == nkind.N_DEFER) { return "defer"; }; + if (k == nkind.N_BREAK) { return "break"; }; + if (k == nkind.N_CONTINUE) { return "continue"; }; + if (k == nkind.N_SWITCH) { return "switch"; }; + if (k == nkind.N_CASE) { return "case"; }; + if (k == nkind.N_FILE) { return "file"; }; + if (k == nkind.N_USE) { return "use"; }; + if (k == nkind.N_DEF) { return "def"; }; + if (k == nkind.N_TYPEDECL) { return "typedecl"; }; + if (k == nkind.N_FNDECL) { return "fn"; }; + if (k == nkind.N_PARAM) { return "param"; }; + if (k == nkind.N_TNAME) { return "tname"; }; + if (k == nkind.N_TPTR) { return "tptr"; }; + if (k == nkind.N_TSLICE) { return "tslice"; }; + if (k == nkind.N_TARRAY) { return "tarray"; }; + if (k == nkind.N_TFN) { return "tfn"; }; + if (k == nkind.N_TSTRUCT) { return "tstruct"; }; + if (k == nkind.N_TFIELD) { return "tfield"; }; + if (k == nkind.N_TCHAN) { return "tchan"; }; + if (k == nkind.N_ATTR) { return "attr"; }; + if (k == nkind.N_TTUPLE) { return "ttuple"; }; + if (k == nkind.N_TTAGGED) { return "ttagged"; }; + if (k == nkind.N_TUPLE) { return "tuple"; }; + if (k == nkind.N_MATCH) { return "match"; }; + if (k == nkind.N_MCASE) { return "mcase"; }; + if (k == nkind.N_TRYPROP) { return "tryprop"; }; + if (k == nkind.N_TRYUNW) { return "tryunw"; }; + if (k == nkind.N_MLET) { return "mlet"; }; + if (k == nkind.N_MASSIGN) { return "massign"; }; + if (k == nkind.N_TYPETEST) { return "typetest"; }; + if (k == nkind.N_TYPEASSERT) { return "typeassert"; }; + if (k == nkind.N_VOIDLIT) { return "voidlit"; }; + if (k == nkind.N_TBANG) { return "tbang"; }; + if (k == nkind.N_YIELD) { return "yield"; }; + if (k == nkind.N_TENUM) { return "tenum"; }; + if (k == nkind.N_TENUMMEMBER) { return "tenummember"; }; + if (k == nkind.N_LAST) { return "last"; }; return "?"; }; @@ -263,31 +267,31 @@ fn pr(fd: i32, n: *node, d: i32) void = { let nm: str = nkname(n.kind); os.write(fd, nm.ptr, nm.len: u64); - if (n.kind == N_INTLIT) { + if (n.kind == nkind.N_INTLIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); - } else { if (n.kind == N_RUNELIT) { + } else { if (n.kind == nkind.N_RUNELIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); } else { if ( - n.kind == N_STRLIT || - n.kind == N_IDENT || - n.kind == N_USE || - n.kind == N_DOT || - n.kind == N_DEF || - n.kind == N_TYPEDECL || - n.kind == N_FNDECL || - n.kind == N_PARAM || - n.kind == N_LET || - n.kind == N_TNAME || - n.kind == N_TFIELD || - n.kind == N_TENUMMEMBER || - n.kind == N_FIELD || - n.kind == N_ATTR + n.kind == nkind.N_STRLIT || + n.kind == nkind.N_IDENT || + n.kind == nkind.N_USE || + n.kind == nkind.N_DOT || + n.kind == nkind.N_DEF || + n.kind == nkind.N_TYPEDECL || + n.kind == nkind.N_FNDECL || + n.kind == nkind.N_PARAM || + n.kind == nkind.N_LET || + n.kind == nkind.N_TNAME || + n.kind == nkind.N_TFIELD || + n.kind == nkind.N_TENUMMEMBER || + n.kind == nkind.N_FIELD || + n.kind == nkind.N_ATTR ) { // Match C ast.c: print the str field whenever it's non-nil, // even if its length is zero (e.g. an empty STRLIT prints @@ -298,22 +302,22 @@ fn pr(fd: i32, n: *node, d: i32) void = { putq(fd, s); }; } else { if ( - n.kind == N_BIN || - n.kind == N_UN || - n.kind == N_ASSIGN + n.kind == nkind.N_BIN || + n.kind == nkind.N_UN || + n.kind == nkind.N_ASSIGN ) { putc1(fd, 32u8); let on: str = tokname(n.op); os.write(fd, on.ptr, on.len: u64); };};};}; - if (n.kind == N_FNDECL) { + if (n.kind == nkind.N_FNDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_DEF) { + if (n.kind == nkind.N_DEF) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_TYPEDECL) { + if (n.kind == nkind.N_TYPEDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; putc1(fd, 10u8); // '\n' diff --git a/lib/ww/parse/decl.ww b/lib/ww/parse/decl.ww index 45009c49..a2f5dc7c 100644 --- a/lib/ww/parse/decl.ww +++ b/lib/ww/parse/decl.ww @@ -9,7 +9,7 @@ fn parseuse(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `use` - let n: *node = newnode(p.a, N_USE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_USE, pf, pl, pc); let id: str; expectident(p, &id); n.str = id; @@ -22,7 +22,7 @@ fn parsedef(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `def` - let n: *node = newnode(p.a, N_DEF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DEF, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -45,7 +45,7 @@ fn parselet(p: *parser, exported: i32) *node = { let is_const: i32 = 0; if (p.curkind == tkind.TK_CONST) { is_const = 1; }; advance(p); - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); n.module = p.l.module; let id: str; expectbindname(p, &id); @@ -70,7 +70,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, N_ATTR, pf, pl, pc); + let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -96,7 +96,7 @@ fn parseparams(p: *parser) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - let n: *node = newnode(p.a, N_PARAM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_PARAM, pf, pl, pc); // Param form: (IDENT|'_') ':' type. Anonymous-type-only params // (used in fn type expressions) aren't yet wired here. let id: str; @@ -117,7 +117,7 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `fn` - let n: *node = newnode(p.a, N_FNDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FNDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -147,7 +147,7 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `type` - let n: *node = newnode(p.a, N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); diff --git a/lib/ww/parse/expr.ww b/lib/ww/parse/expr.ww index 08917b06..ef335c25 100644 --- a/lib/ww/parse/expr.ww +++ b/lib/ww/parse/expr.ww @@ -22,56 +22,56 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, N_INTLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, N_STRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_RUNE) { - let n: *node = newnode(p.a, N_RUNELIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RUNELIT, pf, pl, pc); n.uval = p.curuval; advance(p); return n; }; if (p.curkind == tkind.TK_TRUE) { advance(p); - return newnode(p.a, N_TRUE, pf, pl, pc); + return newnode(p.a, nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, N_FALSE, pf, pl, pc); + return newnode(p.a, nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, N_NIL, pf, pl, pc); + return newnode(p.a, nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, N_VOIDLIT, pf, pl, pc); + return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { - // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT + // Bare `_` — valid only as a discard lvalue. Emit an nkind.N_IDENT // with empty str; the checker rejects it outside lvalue // positions. advance(p); - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); let empty: str; n.str = empty; return n; }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). - // The repeat marker is an N_FIELD node with str = "..." + // The repeat marker is an nkind.N_FIELD node with str = "..." // appended to the element list so cgen can detect it. advance(p); - let n: *node = newnode(p.a, N_ARRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -80,7 +80,7 @@ fn parseprimary(p: *parser) *node = { if (head == nil) { head = e; tail = e; } else { tail.next = e; tail = e; }; if (accepttok(p, tkind.TK_ELLIPSIS)) { - let rep: *node = newnode(p.a, N_FIELD, + let rep: *node = newnode(p.a, nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -98,7 +98,7 @@ fn parseprimary(p: *parser) *node = { let e: *node = parseexpr(p); // Tuple literal: (a, b, ...) if (accepttok(p, tkind.TK_COMMA)) { - let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -115,7 +115,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -126,7 +126,7 @@ fn parseprimary(p: *parser) *node = { // own paren/cond, so this is safe. if (p.curkind == tkind.TK_LBRACE) { advance(p); - let s: *node = newnode(p.a, N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(p.a, nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -146,7 +146,7 @@ fn parseprimary(p: *parser) *node = { expectident(p, &id); expecttok(p, tkind.TK_ASSIGN, "expected '=' in struct lit field"); let v: *node = parseexpr(p); - let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -163,7 +163,7 @@ fn parseprimary(p: *parser) *node = { // match (e) { case let v: T => stmt; case T => stmt; case => stmt; }; advance(p); expecttok(p, tkind.TK_LPAREN, "expected '(' after match"); - let m: *node = newnode(p.a, N_MATCH, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MATCH, pf, pl, pc); m.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after match scrutinee"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open match body"); @@ -174,7 +174,7 @@ fn parseprimary(p: *parser) *node = { let cl: i32 = p.curline; let cc: i32 = p.curcol; advance(p); // past `case` - let mc: *node = newnode(p.a, N_MCASE, cf, cl, cc); + let mc: *node = newnode(p.a, nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -196,7 +196,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, N_NONE, pf, pl, pc); + return newnode(p.a, nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: i32, headout: **node) void = { @@ -222,12 +222,12 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_LPAREN) { advance(p); - let n: *node = newnode(p.a, N_CALL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CALL, pf, pl, pc); n.lhs = cur; // size(T)/align(T): the single arg is a type expression, // not a regular expression. Special-case at the parser. let is_typeop: i32 = 0; - if (cur.kind == N_IDENT) { + if (cur.kind == nkind.N_IDENT) { if (streqlocal(cur.str, "size")) { is_typeop = 1; }; if (streqlocal(cur.str, "align")) { is_typeop = 1; }; }; @@ -247,7 +247,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `[ : hi ]` — slice with implicit lo = 0. if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -264,7 +264,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { p.nocast = prev; if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -274,7 +274,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, N_INDEX, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -283,7 +283,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, N_DOT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); n.lhs = cur; // Hare-style tuple field access: `t.0`, `t.1`. The // numeric literal becomes the field name string so the @@ -304,7 +304,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, N_CAST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -316,7 +316,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // Same precedence level as the `:` cast. if (p.curkind == tkind.TK_AS) { advance(p); - let n: *node = newnode(p.a, N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -324,7 +324,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, N_TYPETEST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -334,14 +334,14 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `e!` — abort on error variant. if (p.curkind == tkind.TK_QUESTION) { advance(p); - let n: *node = newnode(p.a, N_TRYPROP, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYPROP, pf, pl, pc); n.lhs = cur; cur = n; continue; }; if (p.curkind == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_TRYUNW, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -358,37 +358,37 @@ fn parseunary(p: *parser) *node = { let k: i32 = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_MINUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_PLUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_PLUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_NOT; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_TILDE) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_TILDE; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_STAR; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_AMP) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -412,7 +412,7 @@ fn parsebin(p: *parser, lhs: *node, minp: i32) *node = { if (np <= pr) { break; }; rhs = parsebin(p, rhs, np); }; - let n: *node = newnode(p.a, N_BIN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -427,7 +427,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: i32 = p.curkind; advance(p); - let n: *node = newnode(p.a, N_ASSIGN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); n.op = op; n.lhs = e; n.rhs = parseexpr(p); // right-associative diff --git a/lib/ww/parse/parse.ww b/lib/ww/parse/parse.ww index da905a0b..2bb1ab21 100644 --- a/lib/ww/parse/parse.ww +++ b/lib/ww/parse/parse.ww @@ -132,14 +132,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_NOT) { // `!T` — Hare error-flagged type wrapper. advance(p); - let n: *node = newnode(p.a, N_TBANG, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_TPTR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -148,13 +148,13 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, N_TSLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil - // as the sentinel; the cgen path for 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. if (p.curkind == tkind.TK_UNDER) { advance(p); @@ -169,7 +169,7 @@ 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(p.a, N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -177,7 +177,7 @@ fn parsetype(p: *parser) *node = { let fpf: str = p.curfile; let fpl: i32 = p.curline; let fpc: i32 = p.curcol; - let f: *node = newnode(p.a, N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -195,10 +195,10 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_ENUM) { // `enum [storage] { NAME [= expr], ... }` // Storage defaults to i32 (lhs == nil). Each member is an - // 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). advance(p); - let n: *node = newnode(p.a, N_TENUM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -210,7 +210,7 @@ fn parsetype(p: *parser) *node = { let mpf: str = p.curfile; let mpl: i32 = p.curline; let mpc: i32 = p.curcol; - let m: *node = newnode(p.a, N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(p.a, nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -227,16 +227,16 @@ fn parsetype(p: *parser) *node = { }; if (p.curkind == tkind.TK_VOID) { - // `void` keyword in type-expr context — emit as N_TNAME so + // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); n.str = "void"; advance(p); return n; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -256,7 +256,7 @@ fn parsetype(p: *parser) *node = { advance(p); let first: *node = parsetype(p); if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, N_TTAGGED, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -273,7 +273,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, N_TTUPLE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -291,7 +291,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(p.a, N_TFN, pf, pl, pc); + let n: *node = newnode(p.a, 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. @@ -303,7 +303,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, N_TNAME, pf, pl, pc); + return newnode(p.a, nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -354,7 +354,7 @@ fn isassignop(k: i32) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; diff --git a/lib/ww/parse/stmt.ww b/lib/ww/parse/stmt.ww index 2d4f7063..b62097b7 100644 --- a/lib/ww/parse/stmt.ww +++ b/lib/ww/parse/stmt.ww @@ -18,14 +18,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(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -48,7 +48,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -57,16 +57,16 @@ fn parseletlocal(p: *parser) *node = { }; // Comma-multi-let: `let n, s = call();` (ww extension over Hare). // Collects (name, type) pairs, then '=' rhs. Each binding gets - // its own N_LET; the wrapping N_MLET carries the rhs. + // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); let head: *node = n; let tail: *node = 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -98,7 +98,7 @@ fn parseblock(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; expecttok(p, tkind.TK_LBRACE, "expected '{' to open block"); - let blk: *node = newnode(p.a, N_BLOCK, pf, pl, pc); + let blk: *node = newnode(p.a, nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -120,7 +120,7 @@ fn parseif(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `if` expecttok(p, tkind.TK_LPAREN, "expected '(' after if"); - let n: *node = newnode(p.a, N_IF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -140,11 +140,11 @@ fn parsefor(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `for` expecttok(p, tkind.TK_LPAREN, "expected '(' after for"); - let n: *node = newnode(p.a, N_FOR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); // Three forms (matching C parser): // for (cond) — only cond // for (init; cond; post) — full - // for (true) — infinite (cond is N_TRUE) + // for (true) — infinite (cond is nkind.N_TRUE) // Distinguish by counting ';'. Look at first chunk: if it's a // `let` stmt that's the init. Otherwise, parse expr; if next is // ';' it was cond. If we see two ';' total after init, post is @@ -204,13 +204,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, N_RETURN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); if (p.curkind != tkind.TK_SEMI) { let first: *node = 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(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -228,14 +228,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, N_DEFER, pf, pl, pc); + let n: *node = newnode(p.a, 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(p.a, N_YIELD, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -243,12 +243,12 @@ fn parsestmt(p: *parser) *node = { if (p.curkind == tkind.TK_BREAK) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after break"); - return newnode(p.a, N_BREAK, pf, pl, pc); + return newnode(p.a, nkind.N_BREAK, pf, pl, pc); }; if (p.curkind == tkind.TK_CONTINUE) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after continue"); - return newnode(p.a, N_CONTINUE, pf, pl, pc); + return newnode(p.a, nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -258,7 +258,7 @@ fn parsestmt(p: *parser) *node = { // consume — parseexpr would absorb it. let e: *node = parseexpr(p); if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MASSIGN, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -273,7 +273,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index d146f930..b512a136 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -1680,84 +1680,88 @@ use tok; // Mirror of cmd/wcc/ww.h Nkind. Values must stay numerically equal so // the AST diff probe in 990_selfhost works. -def N_NONE: i32 = 0; +// Mirror of the C `Nkind` enum in cmd/wcc/ww.h. Numeric values are +// explicit and must stay in sync — the 990_selfhost test diffs +// astprint against the C side byte-for-byte. Tail-appended entries +// (TYPETEST onward) preserve every prior N_* value. +type nkind = enum i32 { + N_NONE = 0, -def N_INTLIT: i32 = 1; -def N_FLOATLIT: i32 = 2; -def N_STRLIT: i32 = 3; -def N_RUNELIT: i32 = 4; -def N_TRUE: i32 = 5; -def N_FALSE: i32 = 6; -def N_NIL: i32 = 7; -def N_IDENT: i32 = 8; + N_INTLIT = 1, + N_FLOATLIT = 2, + N_STRLIT = 3, + N_RUNELIT = 4, + N_TRUE = 5, + N_FALSE = 6, + N_NIL = 7, + N_IDENT = 8, -def N_BIN: i32 = 9; -def N_UN: i32 = 10; -def N_CALL: i32 = 11; -def N_INDEX: i32 = 12; -def N_DOT: i32 = 13; -def N_CAST: i32 = 14; -def N_STRUCTLIT:i32 = 15; -def N_ARRLIT: i32 = 16; -def N_FIELD: i32 = 17; -def N_ASSIGN: i32 = 18; -def N_ALLOC: i32 = 19; -def N_FREE: i32 = 20; -def N_RECV: i32 = 21; -def N_SLICE: i32 = 22; -def N_SPREAD: i32 = 23; + N_BIN = 9, + N_UN = 10, + N_CALL = 11, + N_INDEX = 12, + N_DOT = 13, + N_CAST = 14, + N_STRUCTLIT = 15, + N_ARRLIT = 16, + N_FIELD = 17, + N_ASSIGN = 18, + N_ALLOC = 19, + N_FREE = 20, + N_RECV = 21, + N_SLICE = 22, + N_SPREAD = 23, -def N_BLOCK: i32 = 24; -def N_EXPRSTMT: i32 = 25; -def N_LET: i32 = 26; -def N_RETURN: i32 = 27; -def N_IF: i32 = 28; -def N_FOR: i32 = 29; -def N_FORRANGE: i32 = 30; -def N_DEFER: i32 = 31; -def N_BREAK: i32 = 32; -def N_CONTINUE: i32 = 33; -def N_SWITCH: i32 = 34; -def N_CASE: i32 = 35; + N_BLOCK = 24, + N_EXPRSTMT = 25, + N_LET = 26, + N_RETURN = 27, + N_IF = 28, + N_FOR = 29, + N_FORRANGE = 30, + N_DEFER = 31, + N_BREAK = 32, + N_CONTINUE = 33, + N_SWITCH = 34, + N_CASE = 35, -def N_FILE: i32 = 36; -def N_USE: i32 = 37; -def N_DEF: i32 = 38; -def N_TYPEDECL: i32 = 39; -def N_FNDECL: i32 = 40; -def N_PARAM: i32 = 41; + N_FILE = 36, + N_USE = 37, + N_DEF = 38, + N_TYPEDECL = 39, + N_FNDECL = 40, + N_PARAM = 41, -def N_TNAME: i32 = 42; -def N_TPTR: i32 = 43; -def N_TSLICE: i32 = 44; -def N_TARRAY: i32 = 45; -def N_TFN: i32 = 46; -def N_TSTRUCT: i32 = 47; -def N_TFIELD: i32 = 48; -def N_TCHAN: i32 = 49; + N_TNAME = 42, + N_TPTR = 43, + N_TSLICE = 44, + N_TARRAY = 45, + N_TFN = 46, + N_TSTRUCT = 47, + N_TFIELD = 48, + N_TCHAN = 49, -def N_ATTR: i32 = 50; -def N_TTUPLE: i32 = 51; -def N_TTAGGED: i32 = 52; -def N_TUPLE: i32 = 53; -def N_MATCH: i32 = 54; -def N_MCASE: i32 = 55; -def N_TRYPROP: i32 = 56; -def N_TRYUNW: i32 = 57; -def N_MLET: i32 = 58; -def N_MASSIGN: i32 = 59; + N_ATTR = 50, + N_TTUPLE = 51, + N_TTAGGED = 52, + N_TUPLE = 53, + N_MATCH = 54, + N_MCASE = 55, + N_TRYPROP = 56, + N_TRYUNW = 57, + N_MLET = 58, + N_MASSIGN = 59, -// Appended at the tail to keep all prior N_* values stable. The -// 990_selfhost test diffs astprint against the C side byte-for-byte. -def N_TYPETEST: i32 = 60; -def N_TYPEASSERT: i32 = 61; -def N_VOIDLIT: i32 = 62; -def N_TBANG: i32 = 63; -def N_YIELD: i32 = 64; -def N_TENUM: i32 = 65; -def N_TENUMMEMBER: i32 = 66; + N_TYPETEST = 60, + N_TYPEASSERT = 61, + N_VOIDLIT = 62, + N_TBANG = 63, + N_YIELD = 64, + N_TENUM = 65, + N_TENUMMEMBER = 66, -def N_LAST: i32 = 67; + N_LAST = 67, +}; // ---- Node ------------------------------------------------------------- @@ -1766,7 +1770,7 @@ type node = struct { file: str, line: i32, col: i32, - op: i32, // for N_BIN / N_UN / N_ASSIGN + op: i32, // for nkind.N_BIN / nkind.N_UN / nkind.N_ASSIGN str: str, uval: u64, fval: f64, @@ -1796,74 +1800,74 @@ export fn newnode(a: *arena, k: i32, file: str, line: i32, col: i32) *node = { // ---- printer ---------------------------------------------------------- fn nkname(k: i32) str = { - if (k == N_NONE) { return "none"; }; - if (k == N_INTLIT) { return "int"; }; - if (k == N_FLOATLIT) { return "float"; }; - if (k == N_STRLIT) { return "str"; }; - if (k == N_RUNELIT) { return "rune"; }; - if (k == N_TRUE) { return "true"; }; - if (k == N_FALSE) { return "false"; }; - if (k == N_NIL) { return "nil"; }; - if (k == N_IDENT) { return "id"; }; - if (k == N_BIN) { return "bin"; }; - if (k == N_UN) { return "un"; }; - if (k == N_CALL) { return "call"; }; - if (k == N_INDEX) { return "index"; }; - if (k == N_DOT) { return "dot"; }; - if (k == N_CAST) { return "cast"; }; - if (k == N_STRUCTLIT) { return "structlit"; }; - if (k == N_ARRLIT) { return "arrlit"; }; - if (k == N_FIELD) { return "field"; }; - if (k == N_ASSIGN) { return "assign"; }; - if (k == N_ALLOC) { return "alloc"; }; - if (k == N_FREE) { return "free"; }; - if (k == N_RECV) { return "recv"; }; - if (k == N_SLICE) { return "slice"; }; - if (k == N_SPREAD) { return "spread"; }; - if (k == N_BLOCK) { return "block"; }; - if (k == N_EXPRSTMT) { return "exprstmt"; }; - if (k == N_LET) { return "let"; }; - if (k == N_RETURN) { return "return"; }; - if (k == N_IF) { return "if"; }; - if (k == N_FOR) { return "for"; }; - if (k == N_FORRANGE) { return "forrange"; }; - if (k == N_DEFER) { return "defer"; }; - if (k == N_BREAK) { return "break"; }; - if (k == N_CONTINUE) { return "continue"; }; - if (k == N_SWITCH) { return "switch"; }; - if (k == N_CASE) { return "case"; }; - if (k == N_FILE) { return "file"; }; - if (k == N_USE) { return "use"; }; - if (k == N_DEF) { return "def"; }; - if (k == N_TYPEDECL) { return "typedecl"; }; - if (k == N_FNDECL) { return "fn"; }; - if (k == N_PARAM) { return "param"; }; - if (k == N_TNAME) { return "tname"; }; - if (k == N_TPTR) { return "tptr"; }; - if (k == N_TSLICE) { return "tslice"; }; - if (k == N_TARRAY) { return "tarray"; }; - if (k == N_TFN) { return "tfn"; }; - if (k == N_TSTRUCT) { return "tstruct"; }; - if (k == N_TFIELD) { return "tfield"; }; - if (k == N_TCHAN) { return "tchan"; }; - if (k == N_ATTR) { return "attr"; }; - if (k == N_TTUPLE) { return "ttuple"; }; - if (k == N_TTAGGED) { return "ttagged"; }; - if (k == N_TUPLE) { return "tuple"; }; - if (k == N_MATCH) { return "match"; }; - if (k == N_MCASE) { return "mcase"; }; - if (k == N_TRYPROP) { return "tryprop"; }; - if (k == N_TRYUNW) { return "tryunw"; }; - if (k == N_MLET) { return "mlet"; }; - if (k == N_MASSIGN) { return "massign"; }; - if (k == N_TYPETEST) { return "typetest"; }; - if (k == N_TYPEASSERT) { return "typeassert"; }; - if (k == N_VOIDLIT) { return "voidlit"; }; - if (k == N_TBANG) { return "tbang"; }; - if (k == N_YIELD) { return "yield"; }; - if (k == N_TENUM) { return "tenum"; }; - if (k == N_TENUMMEMBER) { return "tenummember"; }; - if (k == N_LAST) { return "last"; }; + if (k == nkind.N_NONE) { return "none"; }; + if (k == nkind.N_INTLIT) { return "int"; }; + if (k == nkind.N_FLOATLIT) { return "float"; }; + if (k == nkind.N_STRLIT) { return "str"; }; + if (k == nkind.N_RUNELIT) { return "rune"; }; + if (k == nkind.N_TRUE) { return "true"; }; + if (k == nkind.N_FALSE) { return "false"; }; + if (k == nkind.N_NIL) { return "nil"; }; + if (k == nkind.N_IDENT) { return "id"; }; + if (k == nkind.N_BIN) { return "bin"; }; + if (k == nkind.N_UN) { return "un"; }; + if (k == nkind.N_CALL) { return "call"; }; + if (k == nkind.N_INDEX) { return "index"; }; + if (k == nkind.N_DOT) { return "dot"; }; + if (k == nkind.N_CAST) { return "cast"; }; + if (k == nkind.N_STRUCTLIT) { return "structlit"; }; + if (k == nkind.N_ARRLIT) { return "arrlit"; }; + if (k == nkind.N_FIELD) { return "field"; }; + if (k == nkind.N_ASSIGN) { return "assign"; }; + if (k == nkind.N_ALLOC) { return "alloc"; }; + if (k == nkind.N_FREE) { return "free"; }; + if (k == nkind.N_RECV) { return "recv"; }; + if (k == nkind.N_SLICE) { return "slice"; }; + if (k == nkind.N_SPREAD) { return "spread"; }; + if (k == nkind.N_BLOCK) { return "block"; }; + if (k == nkind.N_EXPRSTMT) { return "exprstmt"; }; + if (k == nkind.N_LET) { return "let"; }; + if (k == nkind.N_RETURN) { return "return"; }; + if (k == nkind.N_IF) { return "if"; }; + if (k == nkind.N_FOR) { return "for"; }; + if (k == nkind.N_FORRANGE) { return "forrange"; }; + if (k == nkind.N_DEFER) { return "defer"; }; + if (k == nkind.N_BREAK) { return "break"; }; + if (k == nkind.N_CONTINUE) { return "continue"; }; + if (k == nkind.N_SWITCH) { return "switch"; }; + if (k == nkind.N_CASE) { return "case"; }; + if (k == nkind.N_FILE) { return "file"; }; + if (k == nkind.N_USE) { return "use"; }; + if (k == nkind.N_DEF) { return "def"; }; + if (k == nkind.N_TYPEDECL) { return "typedecl"; }; + if (k == nkind.N_FNDECL) { return "fn"; }; + if (k == nkind.N_PARAM) { return "param"; }; + if (k == nkind.N_TNAME) { return "tname"; }; + if (k == nkind.N_TPTR) { return "tptr"; }; + if (k == nkind.N_TSLICE) { return "tslice"; }; + if (k == nkind.N_TARRAY) { return "tarray"; }; + if (k == nkind.N_TFN) { return "tfn"; }; + if (k == nkind.N_TSTRUCT) { return "tstruct"; }; + if (k == nkind.N_TFIELD) { return "tfield"; }; + if (k == nkind.N_TCHAN) { return "tchan"; }; + if (k == nkind.N_ATTR) { return "attr"; }; + if (k == nkind.N_TTUPLE) { return "ttuple"; }; + if (k == nkind.N_TTAGGED) { return "ttagged"; }; + if (k == nkind.N_TUPLE) { return "tuple"; }; + if (k == nkind.N_MATCH) { return "match"; }; + if (k == nkind.N_MCASE) { return "mcase"; }; + if (k == nkind.N_TRYPROP) { return "tryprop"; }; + if (k == nkind.N_TRYUNW) { return "tryunw"; }; + if (k == nkind.N_MLET) { return "mlet"; }; + if (k == nkind.N_MASSIGN) { return "massign"; }; + if (k == nkind.N_TYPETEST) { return "typetest"; }; + if (k == nkind.N_TYPEASSERT) { return "typeassert"; }; + if (k == nkind.N_VOIDLIT) { return "voidlit"; }; + if (k == nkind.N_TBANG) { return "tbang"; }; + if (k == nkind.N_YIELD) { return "yield"; }; + if (k == nkind.N_TENUM) { return "tenum"; }; + if (k == nkind.N_TENUMMEMBER) { return "tenummember"; }; + if (k == nkind.N_LAST) { return "last"; }; return "?"; }; @@ -1926,31 +1930,31 @@ fn pr(fd: i32, n: *node, d: i32) void = { let nm: str = nkname(n.kind); os.write(fd, nm.ptr, nm.len: u64); - if (n.kind == N_INTLIT) { + if (n.kind == nkind.N_INTLIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); - } else { if (n.kind == N_RUNELIT) { + } else { if (n.kind == nkind.N_RUNELIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); } else { if ( - n.kind == N_STRLIT || - n.kind == N_IDENT || - n.kind == N_USE || - n.kind == N_DOT || - n.kind == N_DEF || - n.kind == N_TYPEDECL || - n.kind == N_FNDECL || - n.kind == N_PARAM || - n.kind == N_LET || - n.kind == N_TNAME || - n.kind == N_TFIELD || - n.kind == N_TENUMMEMBER || - n.kind == N_FIELD || - n.kind == N_ATTR + n.kind == nkind.N_STRLIT || + n.kind == nkind.N_IDENT || + n.kind == nkind.N_USE || + n.kind == nkind.N_DOT || + n.kind == nkind.N_DEF || + n.kind == nkind.N_TYPEDECL || + n.kind == nkind.N_FNDECL || + n.kind == nkind.N_PARAM || + n.kind == nkind.N_LET || + n.kind == nkind.N_TNAME || + n.kind == nkind.N_TFIELD || + n.kind == nkind.N_TENUMMEMBER || + n.kind == nkind.N_FIELD || + n.kind == nkind.N_ATTR ) { // Match C ast.c: print the str field whenever it's non-nil, // even if its length is zero (e.g. an empty STRLIT prints @@ -1961,22 +1965,22 @@ fn pr(fd: i32, n: *node, d: i32) void = { putq(fd, s); }; } else { if ( - n.kind == N_BIN || - n.kind == N_UN || - n.kind == N_ASSIGN + n.kind == nkind.N_BIN || + n.kind == nkind.N_UN || + n.kind == nkind.N_ASSIGN ) { putc1(fd, 32u8); let on: str = tokname(n.op); os.write(fd, on.ptr, on.len: u64); };};};}; - if (n.kind == N_FNDECL) { + if (n.kind == nkind.N_FNDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_DEF) { + if (n.kind == nkind.N_DEF) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_TYPEDECL) { + if (n.kind == nkind.N_TYPEDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; putc1(fd, 10u8); // '\n' @@ -2041,56 +2045,56 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, N_INTLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, N_STRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_RUNE) { - let n: *node = newnode(p.a, N_RUNELIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RUNELIT, pf, pl, pc); n.uval = p.curuval; advance(p); return n; }; if (p.curkind == tkind.TK_TRUE) { advance(p); - return newnode(p.a, N_TRUE, pf, pl, pc); + return newnode(p.a, nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, N_FALSE, pf, pl, pc); + return newnode(p.a, nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, N_NIL, pf, pl, pc); + return newnode(p.a, nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, N_VOIDLIT, pf, pl, pc); + return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { - // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT + // Bare `_` — valid only as a discard lvalue. Emit an nkind.N_IDENT // with empty str; the checker rejects it outside lvalue // positions. advance(p); - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); let empty: str; n.str = empty; return n; }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). - // The repeat marker is an N_FIELD node with str = "..." + // The repeat marker is an nkind.N_FIELD node with str = "..." // appended to the element list so cgen can detect it. advance(p); - let n: *node = newnode(p.a, N_ARRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -2099,7 +2103,7 @@ fn parseprimary(p: *parser) *node = { if (head == nil) { head = e; tail = e; } else { tail.next = e; tail = e; }; if (accepttok(p, tkind.TK_ELLIPSIS)) { - let rep: *node = newnode(p.a, N_FIELD, + let rep: *node = newnode(p.a, nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -2117,7 +2121,7 @@ fn parseprimary(p: *parser) *node = { let e: *node = parseexpr(p); // Tuple literal: (a, b, ...) if (accepttok(p, tkind.TK_COMMA)) { - let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -2134,7 +2138,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -2145,7 +2149,7 @@ fn parseprimary(p: *parser) *node = { // own paren/cond, so this is safe. if (p.curkind == tkind.TK_LBRACE) { advance(p); - let s: *node = newnode(p.a, N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(p.a, nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -2165,7 +2169,7 @@ fn parseprimary(p: *parser) *node = { expectident(p, &id); expecttok(p, tkind.TK_ASSIGN, "expected '=' in struct lit field"); let v: *node = parseexpr(p); - let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -2182,7 +2186,7 @@ fn parseprimary(p: *parser) *node = { // match (e) { case let v: T => stmt; case T => stmt; case => stmt; }; advance(p); expecttok(p, tkind.TK_LPAREN, "expected '(' after match"); - let m: *node = newnode(p.a, N_MATCH, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MATCH, pf, pl, pc); m.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after match scrutinee"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open match body"); @@ -2193,7 +2197,7 @@ fn parseprimary(p: *parser) *node = { let cl: i32 = p.curline; let cc: i32 = p.curcol; advance(p); // past `case` - let mc: *node = newnode(p.a, N_MCASE, cf, cl, cc); + let mc: *node = newnode(p.a, nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -2215,7 +2219,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, N_NONE, pf, pl, pc); + return newnode(p.a, nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: i32, headout: **node) void = { @@ -2241,12 +2245,12 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_LPAREN) { advance(p); - let n: *node = newnode(p.a, N_CALL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CALL, pf, pl, pc); n.lhs = cur; // size(T)/align(T): the single arg is a type expression, // not a regular expression. Special-case at the parser. let is_typeop: i32 = 0; - if (cur.kind == N_IDENT) { + if (cur.kind == nkind.N_IDENT) { if (streqlocal(cur.str, "size")) { is_typeop = 1; }; if (streqlocal(cur.str, "align")) { is_typeop = 1; }; }; @@ -2266,7 +2270,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `[ : hi ]` — slice with implicit lo = 0. if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -2283,7 +2287,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { p.nocast = prev; if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -2293,7 +2297,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, N_INDEX, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -2302,7 +2306,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, N_DOT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); n.lhs = cur; // Hare-style tuple field access: `t.0`, `t.1`. The // numeric literal becomes the field name string so the @@ -2323,7 +2327,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, N_CAST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2335,7 +2339,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // Same precedence level as the `:` cast. if (p.curkind == tkind.TK_AS) { advance(p); - let n: *node = newnode(p.a, N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2343,7 +2347,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, N_TYPETEST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2353,14 +2357,14 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `e!` — abort on error variant. if (p.curkind == tkind.TK_QUESTION) { advance(p); - let n: *node = newnode(p.a, N_TRYPROP, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYPROP, pf, pl, pc); n.lhs = cur; cur = n; continue; }; if (p.curkind == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_TRYUNW, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -2377,37 +2381,37 @@ fn parseunary(p: *parser) *node = { let k: i32 = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_MINUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_PLUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_PLUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_NOT; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_TILDE) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_TILDE; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_STAR; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_AMP) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -2431,7 +2435,7 @@ fn parsebin(p: *parser, lhs: *node, minp: i32) *node = { if (np <= pr) { break; }; rhs = parsebin(p, rhs, np); }; - let n: *node = newnode(p.a, N_BIN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -2446,7 +2450,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: i32 = p.curkind; advance(p); - let n: *node = newnode(p.a, N_ASSIGN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); n.op = op; n.lhs = e; n.rhs = parseexpr(p); // right-associative @@ -2477,14 +2481,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(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -2507,7 +2511,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -2516,16 +2520,16 @@ fn parseletlocal(p: *parser) *node = { }; // Comma-multi-let: `let n, s = call();` (ww extension over Hare). // Collects (name, type) pairs, then '=' rhs. Each binding gets - // its own N_LET; the wrapping N_MLET carries the rhs. + // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); let head: *node = n; let tail: *node = 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -2557,7 +2561,7 @@ fn parseblock(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; expecttok(p, tkind.TK_LBRACE, "expected '{' to open block"); - let blk: *node = newnode(p.a, N_BLOCK, pf, pl, pc); + let blk: *node = newnode(p.a, nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -2579,7 +2583,7 @@ fn parseif(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `if` expecttok(p, tkind.TK_LPAREN, "expected '(' after if"); - let n: *node = newnode(p.a, N_IF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -2599,11 +2603,11 @@ fn parsefor(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `for` expecttok(p, tkind.TK_LPAREN, "expected '(' after for"); - let n: *node = newnode(p.a, N_FOR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); // Three forms (matching C parser): // for (cond) — only cond // for (init; cond; post) — full - // for (true) — infinite (cond is N_TRUE) + // for (true) — infinite (cond is nkind.N_TRUE) // Distinguish by counting ';'. Look at first chunk: if it's a // `let` stmt that's the init. Otherwise, parse expr; if next is // ';' it was cond. If we see two ';' total after init, post is @@ -2663,13 +2667,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, N_RETURN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); if (p.curkind != tkind.TK_SEMI) { let first: *node = 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(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -2687,14 +2691,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, N_DEFER, pf, pl, pc); + let n: *node = newnode(p.a, 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(p.a, N_YIELD, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -2702,12 +2706,12 @@ fn parsestmt(p: *parser) *node = { if (p.curkind == tkind.TK_BREAK) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after break"); - return newnode(p.a, N_BREAK, pf, pl, pc); + return newnode(p.a, nkind.N_BREAK, pf, pl, pc); }; if (p.curkind == tkind.TK_CONTINUE) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after continue"); - return newnode(p.a, N_CONTINUE, pf, pl, pc); + return newnode(p.a, nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -2717,7 +2721,7 @@ fn parsestmt(p: *parser) *node = { // consume — parseexpr would absorb it. let e: *node = parseexpr(p); if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MASSIGN, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -2732,7 +2736,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; @@ -2751,7 +2755,7 @@ fn parseuse(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `use` - let n: *node = newnode(p.a, N_USE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_USE, pf, pl, pc); let id: str; expectident(p, &id); n.str = id; @@ -2764,7 +2768,7 @@ fn parsedef(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `def` - let n: *node = newnode(p.a, N_DEF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DEF, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -2787,7 +2791,7 @@ fn parselet(p: *parser, exported: i32) *node = { let is_const: i32 = 0; if (p.curkind == tkind.TK_CONST) { is_const = 1; }; advance(p); - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); n.module = p.l.module; let id: str; expectbindname(p, &id); @@ -2812,7 +2816,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, N_ATTR, pf, pl, pc); + let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -2838,7 +2842,7 @@ fn parseparams(p: *parser) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - let n: *node = newnode(p.a, N_PARAM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_PARAM, pf, pl, pc); // Param form: (IDENT|'_') ':' type. Anonymous-type-only params // (used in fn type expressions) aren't yet wired here. let id: str; @@ -2859,7 +2863,7 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `fn` - let n: *node = newnode(p.a, N_FNDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FNDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -2889,7 +2893,7 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `type` - let n: *node = newnode(p.a, N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -3037,14 +3041,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_NOT) { // `!T` — Hare error-flagged type wrapper. advance(p); - let n: *node = newnode(p.a, N_TBANG, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_TPTR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -3053,13 +3057,13 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, N_TSLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil - // as the sentinel; the cgen path for 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. if (p.curkind == tkind.TK_UNDER) { advance(p); @@ -3074,7 +3078,7 @@ 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(p.a, N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -3082,7 +3086,7 @@ fn parsetype(p: *parser) *node = { let fpf: str = p.curfile; let fpl: i32 = p.curline; let fpc: i32 = p.curcol; - let f: *node = newnode(p.a, N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -3100,10 +3104,10 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_ENUM) { // `enum [storage] { NAME [= expr], ... }` // Storage defaults to i32 (lhs == nil). Each member is an - // 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). advance(p); - let n: *node = newnode(p.a, N_TENUM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -3115,7 +3119,7 @@ fn parsetype(p: *parser) *node = { let mpf: str = p.curfile; let mpl: i32 = p.curline; let mpc: i32 = p.curcol; - let m: *node = newnode(p.a, N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(p.a, nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -3132,16 +3136,16 @@ fn parsetype(p: *parser) *node = { }; if (p.curkind == tkind.TK_VOID) { - // `void` keyword in type-expr context — emit as N_TNAME so + // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); n.str = "void"; advance(p); return n; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -3161,7 +3165,7 @@ fn parsetype(p: *parser) *node = { advance(p); let first: *node = parsetype(p); if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, N_TTAGGED, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -3178,7 +3182,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, N_TTUPLE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -3196,7 +3200,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(p.a, N_TFN, pf, pl, pc); + let n: *node = newnode(p.a, 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. @@ -3208,7 +3212,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, N_TNAME, pf, pl, pc); + return newnode(p.a, nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -3259,7 +3263,7 @@ fn isassignop(k: i32) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; @@ -3795,7 +3799,7 @@ export fn scopedefine(s: *scope, name: str, k: i32, t: *tinfo, decl: *node) *sym // `i32`, `str`, `*u8` etc. resolve. // 2. Walks the file's top-level decls (use/def/type/fn/let) and // installs Sym entries for each. -// 3. Recursively walks fn bodies; for every N_IDENT used as an +// 3. Recursively walks fn bodies; for every nkind.N_IDENT used as an // expression or as a type name, looks it up and counts the // resolved vs. unresolved. // 4. Returns a summary the caller (wwdump -r) prints; the test @@ -3855,15 +3859,15 @@ fn installdecl(c: *checker, d: *node) void = { if (d == nil) { return; }; let k: i32 = d.kind; let nm: str = d.str; - if (k == N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; - if (k == N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; - if (k == N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; - if (k == N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; - if (k == N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; + if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; + if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; + if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; + if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; + if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; }; -// resolvewalk — recursive AST walk that, for every N_IDENT and -// N_TNAME seen, looks up the name and bumps the resolved/unresolved +// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and +// nkind.N_TNAME seen, looks up the name and bumps the resolved/unresolved // counters. Local lets are installed in the current scope as soon as // their init/type expressions have been walked (forward use of a let // before its declaration would resolve to nothing — same semantics as @@ -3876,17 +3880,17 @@ fn resolvewalk(c: *checker, n: *node) void = { // Typed checks fire on the way down so the scrutinee/operand // is examined before the arm bodies install new bindings. - if (k == N_MATCH) { checkmatchexhaust(c, n); }; - if (k == N_TRYPROP) { checktryprop(c, n); }; - if (k == N_TYPETEST) { checkisas(c, n); }; - if (k == N_TYPEASSERT) { checkisas(c, n); }; - if (k == N_LET) { checkletassign(c, n); }; - if (k == N_RETURN) { checkretassign(c, n); }; + if (k == nkind.N_MATCH) { checkmatchexhaust(c, n); }; + if (k == nkind.N_TRYPROP) { checktryprop(c, n); }; + if (k == nkind.N_TYPETEST) { checkisas(c, n); }; + if (k == nkind.N_TYPEASSERT) { checkisas(c, n); }; + if (k == nkind.N_LET) { checkletassign(c, n); }; + if (k == nkind.N_RETURN) { checkretassign(c, n); }; // `use IDENT;` — name is a module label, not a free ident. - if (k == N_USE) { return; }; + if (k == nkind.N_USE) { return; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -3901,7 +3905,7 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -3940,7 +3944,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `match (e) { case let v: T => stmt; ... }` — the binding `v` // is declared by the case arm and visible inside its body. - if (k == N_MCASE) { + if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let nm: str = n.str; if (nm.len > 0) { @@ -3950,19 +3954,19 @@ fn resolvewalk(c: *checker, n: *node) void = { return; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { // Walk only the base; the .field name is a member, not a // free identifier. if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_FIELD) { + if (k == nkind.N_FIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_TFIELD) { + if (k == nkind.N_TFIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; @@ -3986,7 +3990,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `X` so subsequent statements can resolve it. Top-level lets // are installed in installdecl, so this duplicate install at // the file scope just no-ops (scopedefine returns nil on dup). - if (k == N_LET) { + if (k == nkind.N_LET) { let nm: str = n.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_VAR, nil, n); @@ -4002,21 +4006,21 @@ fn resolvewalk(c: *checker, n: *node) void = { // needs to enforce: tagged-union exhaustiveness, ? subset // propagation, and !-flag semantics. -// unwrapbang — strip an N_TBANG wrapper; leaves other nodes alone. +// unwrapbang — strip an nkind.N_TBANG wrapper; leaves other nodes alone. fn unwrapbang(n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind == N_TBANG) { return n.lhs; }; + if (n.kind == nkind.N_TBANG) { return n.lhs; }; return n; }; -// resolvealias — if n is an N_TNAME pointing at a typedecl, return +// resolvealias — if n is an nkind.N_TNAME pointing at a typedecl, return // the typedecl's body (possibly recursively). Pass-through for any -// other node. The chain stops once we hit a non-N_TNAME node or a +// other node. The chain stops once we hit a non-nkind.N_TNAME node or a // name we can't resolve. fn resolvealias(c: *checker, n: *node) *node = { let cur: *node = n; for (cur != nil) { - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let s: *sym = scopelookup(c.cur, cur.str); if (s == nil) { return cur; }; if (s.skind != skind.SK_TYPE) { return cur; }; @@ -4039,10 +4043,10 @@ fn typeeqast(a: *node, b: *node) bool = { if (bb == nil) { return false; }; if (aa.kind != bb.kind) { return false; }; let k: i32 = aa.kind; - if (k == N_TNAME) { return streq(aa.str, bb.str); }; - if (k == N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TNAME) { return streq(aa.str, bb.str); }; + if (k == nkind.N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; // Conservative: anything else (struct/fn/tagged/tuple/array) // fails the cheap check. Selfhost code doesn't currently rely // on equality at these shapes for the targeted checks. @@ -4050,18 +4054,18 @@ fn typeeqast(a: *node, b: *node) bool = { }; // varianterr — does this variant carry the `!` mark? Either -// the variant itself is N_TBANG or it's an alias whose typedecl +// the variant itself is nkind.N_TBANG or it's an alias whose typedecl // body is `!T`. Mirrors C check.c's iserror-after-NAMED rule. fn varianterr(c: *checker, v: *node) bool = { if (v == nil) { return false; }; - if (v.kind == N_TBANG) { return true; }; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TBANG) { return true; }; + if (v.kind == nkind.N_TNAME) { let s: *sym = scopelookup(c.cur, v.str); if (s != nil) { if (s.skind == skind.SK_TYPE) { if (s.decl != nil) { if (s.decl.lhs != nil) { - if (s.decl.lhs.kind == N_TBANG) { + if (s.decl.lhs.kind == nkind.N_TBANG) { return true; }; }; @@ -4073,7 +4077,7 @@ fn varianterr(c: *checker, v: *node) bool = { }; // taggedhaserr — true iff any variant of `n` (assumed -// N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over +// nkind.N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over // the legacy "first variant = success" rule. fn taggedhaserr(c: *checker, n: *node) bool = { let v: *node = n.list; @@ -4097,26 +4101,26 @@ fn iserrvariant(c: *checker, tagged: *node, v: *node) bool = { }; // scruttype — resolve the type expression for a match's -// scrutinee. Handles N_IDENT (look up local/param's declared -// type) and N_DOT (struct-field access). Returns nil if we +// scrutinee. Handles nkind.N_IDENT (look up local/param's declared +// type) and nkind.N_DOT (struct-field access). Returns nil if we // can't statically determine the type. Used by exhaustiveness. fn scruttype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; - // For N_LET / N_PARAM: declared type is decl.lhs. + // For nkind.N_LET / nkind.N_PARAM: declared type is decl.lhs. return s.decl.lhs; }; return nil; }; -// mktname — fabricate an N_TNAME node with str = `nm`. Used by +// mktname — fabricate an nkind.N_TNAME node with str = `nm`. Used by // exprtype to return primitive type nodes for literal // expressions. The arena keeps them around as long as the checker. fn mktname(c: *checker, nm: str) *node = { - let n: *node = newnode(c.a, N_TNAME, "", 0, 0); + let n: *node = newnode(c.a, nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -4128,31 +4132,31 @@ fn mktname(c: *checker, nm: str) *node = { fn exprtype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; let k: i32 = e.kind; - if (k == N_INTLIT) { return mktname(c, "untyped_int"); }; - if (k == N_FLOATLIT) { return mktname(c, "untyped_float"); }; - if (k == N_STRLIT) { return mktname(c, "str"); }; - if (k == N_RUNELIT) { return mktname(c, "rune"); }; - if (k == N_TRUE) { return mktname(c, "bool"); }; - if (k == N_FALSE) { return mktname(c, "bool"); }; - if (k == N_VOIDLIT) { return mktname(c, "void"); }; - if (k == N_NIL) { return mktname(c, "untyped_nil"); }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { return mktname(c, "untyped_int"); }; + if (k == nkind.N_FLOATLIT) { return mktname(c, "untyped_float"); }; + if (k == nkind.N_STRLIT) { return mktname(c, "str"); }; + if (k == nkind.N_RUNELIT) { return mktname(c, "rune"); }; + if (k == nkind.N_TRUE) { return mktname(c, "bool"); }; + if (k == nkind.N_FALSE) { return mktname(c, "bool"); }; + if (k == nkind.N_VOIDLIT) { return mktname(c, "void"); }; + if (k == nkind.N_NIL) { return mktname(c, "untyped_nil"); }; + if (k == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // `expr: T` — explicit cast; the type expr is e.rhs. return e.rhs; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -4160,13 +4164,13 @@ fn exprtype(c: *checker, e: *node) *node = { if (s.decl == nil) { return nil; }; return s.decl.lhs; // fn-decl's lhs is the return type }; - if (k == N_TRYPROP) { + if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union. let opt: *node = exprtype(c, e.lhs); let ou: *node = resolvealias(c, unwrapbang(opt)); if (ou == nil) { return nil; }; - if (ou.kind != N_TTAGGED) { return nil; }; + if (ou.kind != nkind.N_TTAGGED) { return nil; }; // Hare semantics: success = first non-error variant if // any !-flag is present; else first variant. if (taggedhaserr(c, ou)) { @@ -4179,11 +4183,11 @@ fn exprtype(c: *checker, e: *node) *node = { }; return ou.list; }; - if (k == N_TYPEASSERT) { + if (k == nkind.N_TYPEASSERT) { // `e as T` → T return e.rhs; }; - if (k == N_TYPETEST) { + if (k == nkind.N_TYPETEST) { // `e is T` → bool return mktname(c, "bool"); }; @@ -4195,25 +4199,25 @@ fn exprtype(c: *checker, e: *node) *node = { // through without needing real type inference. fn isuntypedint(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_int"); }; fn isuntypedfloat(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_float"); }; fn isuntypednil(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_nil"); }; fn isnumerictname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; let s: str = t.str; if (streq(s, "i8")) { return true; }; if (streq(s, "i16")) { return true; }; @@ -4234,7 +4238,7 @@ fn isnumerictname(t: *node) bool = { fn isstrtname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "str"); }; @@ -4259,7 +4263,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { if (isuntypedint(su)) { if (isnumerictname(du)) { return true; }; // (T | ...) tagged: only OK if some variant accepts untyped_int. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -4272,7 +4276,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Known non-numeric primitive: confidently wrong. - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -4283,7 +4287,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypedfloat(su)) { if (isnumerictname(du)) { return true; }; - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -4293,17 +4297,17 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypednil(su)) { // nil → ptr/slice/chan/fn/nullable - if (du.kind == N_TPTR) { return true; }; - if (du.kind == N_TSLICE) { return true; }; - if (du.kind == N_TCHAN) { return true; }; - if (du.kind == N_TFN) { return true; }; + if (du.kind == nkind.N_TPTR) { return true; }; + if (du.kind == nkind.N_TSLICE) { return true; }; + if (du.kind == nkind.N_TCHAN) { return true; }; + if (du.kind == nkind.N_TFN) { return true; }; // nullable `(*T | void)` — already accepted by typeeqast // when matched whole; nil is OK there too. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { - if (v.kind == N_TPTR) { return true; }; - if (v.kind == N_TSLICE){ return true; }; + if (v.kind == nkind.N_TPTR) { return true; }; + if (v.kind == nkind.N_TSLICE){ return true; }; v = v.next; }; }; @@ -4311,7 +4315,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Tagged-union variant inclusion: src is one of dst's variants. - if (du.kind == N_TTAGGED && su.kind != N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind != nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -4326,13 +4330,13 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { // (don't be confident) — common when forwarding a fallible // return through another fn with the same shape but possibly // a different surface spelling. - if (du.kind == N_TTAGGED && su.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind == nkind.N_TTAGGED) { *confident = false; return true; }; // Two known primitives with different names are confidently // incompatible. `i32 ↔ bool`, `str ↔ i32`, etc. - if (du.kind == N_TNAME && su.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME && su.kind == nkind.N_TNAME) { let known_d: bool = isnumerictname(du) || isstrtname(du); if (!known_d) { if (streq(du.str, "bool")) { known_d = true; }; }; if (!known_d) { if (streq(du.str, "void")) { known_d = true; }; }; @@ -4372,7 +4376,7 @@ fn casecovers(c: *checker, cs: *node, want: *node) bool = { fn errmatchvariant(c: *checker, n: *node, vname: *node) void = { os.write(2, "match: variant not handled".ptr, 26u64); if (vname != nil) { - if (vname.kind == N_TNAME) { + if (vname.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, vname.str.ptr, vname.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4397,7 +4401,7 @@ fn casevariantin(tagged: *node, pat: *node) bool = { fn errbadcase(c: *checker, pat: *node) void = { os.write(2, "case: not a variant of scrutinee".ptr, 32u64); if (pat != nil) { - if (pat.kind == N_TNAME) { + if (pat.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, pat.str.ptr, pat.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4413,7 +4417,7 @@ fn checkmatchexhaust(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Validity: every `case T` pattern (and multi-pattern alts) // must name a variant of u. Catches typos and dead arms that // the dispatch would never reach. @@ -4469,12 +4473,12 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = { os.write(2, where.ptr, where.len: u64); os.write(2, ": not assignable".ptr, 16u64); if (src != nil) { - if (src.kind == N_TNAME) { + if (src.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, src.str.ptr, src.str.len: u64); os.write(2, " → ".ptr, 5u64); if (dst != nil) { - if (dst.kind == N_TNAME) { + if (dst.kind == nkind.N_TNAME) { os.write(2, dst.str.ptr, dst.str.len: u64); }; }; @@ -4526,7 +4530,7 @@ fn checkisas(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { + if (u.kind != nkind.N_TTAGGED) { os.write(2, "is/as: operand is not a tagged union\n".ptr, 37u64); c.errs += 1; return; @@ -4535,7 +4539,7 @@ fn checkisas(c: *checker, n: *node) void = { if (want == nil) { return; }; if (!casevariantin(u, want)) { os.write(2, "is/as: not a variant of operand".ptr, 31u64); - if (want.kind == N_TNAME) { + if (want.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, want.str.ptr, want.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4549,26 +4553,26 @@ fn checkisas(c: *checker, n: *node) void = { // // For `expr?`, the operand's error subset must be a subset of the // enclosing fn's return-type variants. Mirrors C check.c. Operand -// is N_TRYPROP; its lhs is the value-bearing expr; we look at the -// expr's *declared* type for N_IDENT/N_CALL cases. +// is nkind.N_TRYPROP; its lhs is the value-bearing expr; we look at the +// expr's *declared* type for nkind.N_IDENT/nkind.N_CALL cases. fn exprtypeoftry(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (e.kind == N_CALL) { - // callee return type lookup: callee is e.lhs (N_IDENT or - // N_DOT). We need the fn-decl's lhs (return-type AST). + if (e.kind == nkind.N_CALL) { + // callee return type lookup: callee is e.lhs (nkind.N_IDENT or + // nkind.N_DOT). We need the fn-decl's lhs (return-type AST). let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -4584,7 +4588,7 @@ fn checktryprop(c: *checker, n: *node) void = { let t: *node = exprtypeoftry(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(t)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Does the operand have any error variants? let haserr: bool = false; let v: *node = u.list; @@ -4601,7 +4605,7 @@ fn checktryprop(c: *checker, n: *node) void = { c.errs += 1; return; }; - if (r.kind != N_TTAGGED) { + if (r.kind != nkind.N_TTAGGED) { os.write(2, "?: enclosing fn return is not tagged\n".ptr, 37u64); c.errs += 1; return; @@ -4631,7 +4635,7 @@ fn checktryprop(c: *checker, n: *node) void = { fn installparams(c: *checker, params: *node) void = { let p: *node = params; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_PARAM, nil, p); @@ -4673,7 +4677,7 @@ export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { export fn checkfile(c: *checker, file: *node) void = { if (file == nil) { return; }; - if (file.kind != N_FILE) { return; }; + if (file.kind != nkind.N_FILE) { return; }; // Pass 1: install all top-level names. let d: *node = file.list; @@ -4686,15 +4690,15 @@ export fn checkfile(c: *checker, file: *node) void = { d = file.list; for (d != nil) { let k: i32 = d.kind; - if (k == N_FNDECL) { + if (k == nkind.N_FNDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type resolvefnbody(c, d); - } else { if (k == N_DEF) { + } else { if (k == nkind.N_DEF) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; - } else { if (k == N_TYPEDECL) { + } else { if (k == nkind.N_TYPEDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; - } else { if (k == N_LET) { + } else { if (k == nkind.N_LET) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; };};};}; @@ -4736,16 +4740,16 @@ use strconv; fn pushargsrev(c: *cgen, arg: *node) i32 = { if (arg == nil) { return 0; }; let rest: i32 = pushargsrev(c, arg.next); - // N_SLICE expression as arg: `buf[lo:hi]` builds a slice header + // nkind.N_SLICE expression as arg: `buf[lo:hi]` builds a slice header // on the stack matching C cgen's sequence — push base, push hi, // compute lo, pop into BX/CX, derive len/ptr, push (cap, len, ptr). - if (arg.kind == N_SLICE) { + if (arg.kind == nkind.N_SLICE) { let base: *node = arg.lhs; let lo: *node = arg.rhs; let hi: *node = arg.cond; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); }; @@ -4754,7 +4758,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); emitline("(BP), AX\n"); @@ -4778,20 +4782,20 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { } else { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { let lenn: *node = tn.rhs; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { + if (lenn.kind == nkind.N_INTLIT) { emitline("\tMOVQ\t$"); emituint(lenn.uval); emitline(", AX\n"); }; }; - } else { if (tn.kind == N_TSLICE) { + } else { if (tn.kind == nkind.N_TSLICE) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); emitline("(BP), AX\n"); - } else { if (tn.kind == N_TNAME) { + } else { if (tn.kind == nkind.N_TNAME) { if (streq(tn.str, "str")) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); @@ -4819,7 +4823,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { // Slice/tagged ident args: emit per-register MOVQ+PUSHQ pairs in // reverse order (cap/v1, len/v0, ptr/tag) so a left-to-right pop // into argregs lands the canonical (ptr/tag, len/v0, cap/v1). - if (arg.kind == N_IDENT) { + if (arg.kind == nkind.N_IDENT) { let nm: str = arg.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -4860,13 +4864,13 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { fn nodeisslice(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return isslicetype(c, lc.tnode); }; return false; }; - if (k == N_SLICE) { return true; }; + if (k == nkind.N_SLICE) { return true; }; return false; }; @@ -4876,14 +4880,14 @@ fn nodeisslice(c: *cgen, n: *node) bool = { fn nodeisstr(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_STRLIT) { return true; }; - if (k == N_IDENT) { + if (k == nkind.N_STRLIT) { return true; }; + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { + if (tn.kind == nkind.N_TNAME) { let tnm: str = tn.str; if (streq(tnm, "str")) { return true; }; }; @@ -4891,10 +4895,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = n.lhs; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cnm: str = callee.str; let rt: *node = fnretlookup(c, cnm); return isstrtype(c, rt); @@ -4902,7 +4906,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; // `.ptr` is *u8 not str; `.len` is i32 not str. @@ -4912,17 +4916,17 @@ fn nodeisstr(c: *cgen, n: *node) bool = { if (base != nil) { let sname: str; sname.ptr = nil; sname.len = 0; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; }; @@ -4930,10 +4934,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { // Chained dot (`p.foo.bar`): use dotinnerstructptr // to resolve the inner chain to the *struct it lands // on, then look up `fld` in that struct. - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { - if (innert.kind == N_TNAME) { sname = innert.str; }; + if (innert.kind == nkind.N_TNAME) { sname = innert.str; }; }; }; if (sname.len > 0) { @@ -4952,7 +4956,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { return isstrtype(c, n.rhs); }; return false; @@ -4972,13 +4976,13 @@ fn typenameisunsigned(nm: str) bool = { // typenodeisunsigned — recurse through TNAME / TPTR / TSLICE etc. fn typenodeisunsigned(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { return typenameisunsigned(t.str); }; + if (t.kind == nkind.N_TNAME) { return typenameisunsigned(t.str); }; return false; }; // typeis8byteprimitive — does this type take exactly one 8-byte // slot (pointer / fn-ptr / 64-bit int / chan / scalar primitive -// padded up to 8) rather than a wider aggregate? Used by N_LET +// padded up to 8) rather than a wider aggregate? Used by nkind.N_LET // zero-init to mirror C cgen's "only zero if sz == 8 at the type // level" rule. Strings (16), slices (24), tagged unions (>=16), // tuples (16), structs (varies), arrays — all fall through to @@ -4986,14 +4990,14 @@ fn typenodeisunsigned(t: *node) bool = { fn typeis8byteprimitive(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; let k: i32 = t.kind; - if (k == N_TPTR) { return true; }; - if (k == N_TFN) { return true; }; - if (k == N_TCHAN) { return true; }; - if (k == N_TSLICE) { return false; }; - if (k == N_TARRAY) { return false; }; - if (k == N_TTUPLE) { return false; }; - if (k == N_TTAGGED){ return false; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { return true; }; + if (k == nkind.N_TFN) { return true; }; + if (k == nkind.N_TCHAN) { return true; }; + if (k == nkind.N_TSLICE) { return false; }; + if (k == nkind.N_TARRAY) { return false; }; + if (k == nkind.N_TTUPLE) { return false; }; + if (k == nkind.N_TTAGGED){ return false; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return false; }; // Struct alias: not a primitive even if the slot is 8B. @@ -5028,7 +5032,7 @@ fn fieldloadop(f: *fieldinfo) str = { if (sz == 4) { let t: *node = f.tnode; if (t != nil) { - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { if (typenameissigned(t.str)) { return "MOVSXD"; }; }; }; @@ -5053,11 +5057,11 @@ fn fieldstoreop(f: *fieldinfo) str = { // the slice element type. fn indexbaseesz(c: *cgen, base: *node) i32 = { if (base == nil) { return 8; }; - if (base.kind != N_DOT) { return 8; }; + if (base.kind != nkind.N_DOT) { return 8; }; let fld: str = base.str; let inner: *node = base.lhs; if (inner == nil) { return 8; }; - if (inner.kind != N_IDENT) { return 8; }; + if (inner.kind != nkind.N_IDENT) { return 8; }; let nm: str = inner.str; let lc: *local = localfindnode(c, nm); if (lc == nil) { return 8; }; @@ -5067,12 +5071,12 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { // `.ptr` pseudo-field on str/slice → element of the str/slice. if (streq(fld, "ptr")) { let innert: *node = tn; - if (tn.kind == N_TPTR) { innert = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { innert = tn.lhs; }; if (innert == nil) { return 8; }; - if (innert.kind == N_TNAME) { + if (innert.kind == nkind.N_TNAME) { if (streq(innert.str, "str")) { return 1; }; }; - if (innert.kind == N_TSLICE) { return elemsizeof(innert); }; + if (innert.kind == nkind.N_TSLICE) { return elemsizeof(innert); }; return 8; }; @@ -5080,11 +5084,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let pinner: *node = tn.lhs; if (pinner != nil) { - if (pinner.kind == N_TNAME) { sname = pinner.str; }; + if (pinner.kind == nkind.N_TNAME) { sname = pinner.str; }; }; }; if (sname.len == 0) { return 8; }; @@ -5096,10 +5100,10 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return 8; }; - if (ft.kind == N_TPTR) { + if (ft.kind == nkind.N_TPTR) { let elem: *node = ft.lhs; if (elem != nil) { - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { if (streq(elem.str, "str")) { return 16; }; let ps: i32 = primsize(elem.str); if (ps > 0) { return ps; }; @@ -5107,11 +5111,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { }; return 8; }; - if (ft.kind == N_TSLICE) { return elemsizeof(ft); }; + if (ft.kind == nkind.N_TSLICE) { return elemsizeof(ft); }; // str-typed field: indexing yields one byte // (`n.s[i]` where .s is str — matches C cgen's // MOVZBQ for byte indexing). - if (ft.kind == N_TNAME) { + if (ft.kind == nkind.N_TNAME) { if (streq(ft.str, "str")) { return 1; }; }; return 8; @@ -5121,36 +5125,36 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { return 8; }; -// dotinnerstructptr — for an N_DOT whose lhs is a chain of dots -// or an N_IDENT, walk the chain and return the N_TNAME tnode of the +// dotinnerstructptr — for an nkind.N_DOT whose lhs is a chain of dots +// or an nkind.N_IDENT, walk the chain and return the nkind.N_TNAME tnode of the // struct that the chain dereferences to (i.e., for `r.sym` where -// .sym is *lsym, return N_TNAME("lsym")). Returns nil if the chain +// .sym is *lsym, return nkind.N_TNAME("lsym")). Returns nil if the chain // doesn't resolve to a *struct. // // Used by the chained-DOT cgen path so `r.sym.val` knows the outer // is a field of `lsym`. fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind != N_DOT) { return nil; }; + if (n.kind != nkind.N_DOT) { return nil; }; let base: *node = n.lhs; let fld: str = n.str; if (base == nil) { return nil; }; // Resolve base's struct tnode. let baset: *node = nil; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc == nil) { return nil; }; let tn: *node = lc.tnode; if (tn == nil) { return nil; }; - // base could be either struct-by-value (N_TNAME) or *struct (N_TPTR). - if (tn.kind == N_TNAME) { baset = tn; }; - if (tn.kind == N_TPTR) { baset = tn.lhs; }; - } else { if (base.kind == N_DOT) { + // base could be either struct-by-value (nkind.N_TNAME) or *struct (nkind.N_TPTR). + if (tn.kind == nkind.N_TNAME) { baset = tn; }; + if (tn.kind == nkind.N_TPTR) { baset = tn.lhs; }; + } else { if (base.kind == nkind.N_DOT) { baset = dotinnerstructptr(c, base); };}; if (baset == nil) { return nil; }; - if (baset.kind != N_TNAME) { return nil; }; + if (baset.kind != nkind.N_TNAME) { return nil; }; // Look up the struct, find the field, return the field's *struct. let si: *structinfo = structlookup(c, baset.str); @@ -5160,10 +5164,10 @@ fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (streq(fi.fname, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return nil; }; - if (ft.kind != N_TPTR) { return nil; }; + if (ft.kind != nkind.N_TPTR) { return nil; }; let inner: *node = ft.lhs; if (inner == nil) { return nil; }; - if (inner.kind != N_TNAME) { return nil; }; + if (inner.kind != nkind.N_TNAME) { return nil; }; return inner; }; fi = fi.finext; @@ -5178,10 +5182,10 @@ fn elemsizeof(t: *node) i32 = { if (t == nil) { return 1; }; let k: i32 = t.kind; let elem: *node = nil; - if (k == N_TPTR) { elem = t.lhs; }; - if (k == N_TSLICE) { elem = t.lhs; }; - if (k == N_TARRAY) { elem = t.lhs; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { elem = t.lhs; }; + if (k == nkind.N_TSLICE) { elem = t.lhs; }; + if (k == nkind.N_TARRAY) { elem = t.lhs; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return 1; }; // Indexing a primitive name (rare): element size = the prim. @@ -5190,7 +5194,7 @@ fn elemsizeof(t: *node) i32 = { return 1; }; if (elem == nil) { return 1; }; - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { let nm: str = elem.str; // str element is 16B (ptr+len). primsize returns 0 for it. if (streq(nm, "str")) { return 16; }; @@ -5202,28 +5206,28 @@ fn elemsizeof(t: *node) i32 = { // nodeisunsigned — best-effort cgen-time inference from the AST. We // don't have a typed AST yet, so we walk surface nodes: -// N_INTLIT — never marked unsigned (no tsuffix plumbing yet) -// N_IDENT — look up the local's declared type -// N_DOT — look up the field's declared type via struct reg -// N_BIN / N_UN — recurse: unsigned if either operand is unsigned -// N_CAST — use the cast target type +// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet) +// nkind.N_IDENT — look up the local's declared type +// nkind.N_DOT — look up the field's declared type via struct reg +// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned +// nkind.N_CAST — use the cast target type // // Conservative: if we can't tell, return false (signed). The cost of // being wrong here is byte-different asm vs C, not bad runtime. fn nodeisunsigned(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return typenodeisunsigned(lc.tnode); }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -5232,13 +5236,13 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { if (tn != nil) { lkind = tn.kind; }; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; - if (lkind == N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TNAME) { sname = tn.str; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -5257,29 +5261,29 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { return typenodeisunsigned(n.rhs); }; - if (k == N_BIN) { + if (k == nkind.N_CAST) { return typenodeisunsigned(n.rhs); }; + if (k == nkind.N_BIN) { if (nodeisunsigned(c, n.lhs)) { return true; }; return nodeisunsigned(c, n.rhs); }; - if (k == N_UN) { return nodeisunsigned(c, n.lhs); }; - // N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. + if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; + // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. // Walks the base local's declared type and pulls the element // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the // compare-codegen for `p[i] >= 48u8` falls back to signed JGE // instead of JAE, diverging from C w6c on byte indexing. - if (k == N_INDEX) { + if (k == nkind.N_INDEX) { let base: *node = n.lhs; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { let elem: *node = nil; - if (tn.kind == N_TPTR) { elem = tn.lhs; }; - if (tn.kind == N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == N_TSLICE) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; if (elem != nil) { return typenodeisunsigned(elem); }; @@ -5307,7 +5311,7 @@ fn structlookup(c: *cgen, name: str) *structinfo = { // recognised as a primitive — the caller falls back to other paths). // fldnumidx — parse a tuple field name like "0" / "1" / "12" into an // index, or -1 if not all-digits. Used by cgdot to dispatch -// `t.0` / `t.1` against an N_TTUPLE local without pulling in strconv. +// `t.0` / `t.1` against an nkind.N_TTUPLE local without pulling in strconv. fn fldnumidx(s: str) i32 = { if (s.len == 0) { return -1; }; let r: i32 = 0; @@ -5352,14 +5356,14 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { // return elem_size * 1 (treating missing length as 1); intercept // and compute the real count first. if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs == nil) { if (n.rhs != nil) { - if (n.rhs.kind == N_ARRLIT) { + if (n.rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -5368,7 +5372,7 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { let e: *node = n.rhs.list; for (e != nil) { let adv: bool = true; - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { e = nil; adv = false; @@ -5391,11 +5395,11 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let k: i32 = typn.kind; - if (k == N_TPTR) { return 8; }; - if (k == N_TFN) { return 8; }; - if (k == N_TCHAN) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TTUPLE) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TFN) { return 8; }; + if (k == nkind.N_TCHAN) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TTUPLE) { // Sum element sizes. Mirrors C cgen which uses raw type // sizes; padding to 8 happens inside slotsize for primitives, // so a `(i64, str)` resolves to 8 + 16 = 24 (matches the C @@ -5408,13 +5412,13 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return total; }; - if (k == N_TTAGGED){ + if (k == nkind.N_TTAGGED){ // Nullable `(*T | void)` collapses to a single 8B pointer. if (isnullabletype(typn)) { return 8; }; // Slot = 8 (tag) + max(variant payload sizes), rounded up // to an 8-byte multiple so the reg-passing ABI (size/8 // words) doesn't drop the last value register. Mirrors C - // cgen's resolve_type for N_TTAGGED. + // cgen's resolve_type for nkind.N_TTAGGED. let v: *node = typn.list; let maxsz: i32 = 0; for (v != nil) { @@ -5425,7 +5429,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { let pad: i32 = (maxsz + 7) & ~7; return 8 + pad; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = typn.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -5439,16 +5443,16 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TARRAY) { + if (k == nkind.N_TARRAY) { let lenn: *node = typn.rhs; let elemn: *node = typn.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let en: str = elemn.str; let ps: i32 = primsize(en); if (ps > 0) { esz = ps; }; @@ -5456,12 +5460,12 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return (esz: i64 * elen): i32; }; - if (k == N_TSTRUCT) { + if (k == nkind.N_TSTRUCT) { // Inline anonymous struct — sum of field sizes. let f: *node = typn.list; let total: i32 = 0; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { total += slotsize(c, f.lhs); }; f = f.next; @@ -5478,7 +5482,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let k: i32 = tnode.kind; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = tnode.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -5487,15 +5491,15 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TPTR) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TARRAY) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TARRAY) { // Same shape as slotsize's TARRAY branch. let lenn: *node = tnode.rhs; let elemn: *node = tnode.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = fieldsize(c, elemn); return (esz: i64 * elen): i32; @@ -5513,7 +5517,7 @@ fn registerstruct(c: *cgen, name: str, tstruct: *node) void = { let off: i32 = 0; let f: *node = tstruct.list; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { let sz: i32 = fieldsize(c, f.lhs); // Align to 8 for any field >= 4 bytes (matches our other // cgen choices). i8/u8/bool may sit on odd byte offsets; @@ -5549,10 +5553,10 @@ fn collectstructs(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TSTRUCT) { + if (body.kind == nkind.N_TSTRUCT) { registerstruct(c, d.str, body); }; }; @@ -5565,7 +5569,7 @@ fn collectstructs(c: *cgen, file: *node) void = { // alias chain registered at file load. fn isstrtyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return true; }; }; @@ -5581,7 +5585,7 @@ fn isstrtype(c: *cgen, t: *node) bool = { fn isslicetyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TSLICE) { return true; }; + if (t.kind == nkind.N_TSLICE) { return true; }; return false; }; @@ -5594,26 +5598,26 @@ fn isslicetype(c: *cgen, t: *node) bool = { fn istaggedtype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TTAGGED) { return true; }; + if (t.kind == nkind.N_TTAGGED) { return true; }; return false; }; -// isnullabletype — N_TTAGGED with exactly two children, one *T and +// isnullabletype — nkind.N_TTAGGED with exactly two children, one *T and // one `void`. Folds to a single 8-byte pointer slot per Hare's // `(*T | null)` semantics. Mirrors check.c's resolve_type detection. export fn isnullabletype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TTAGGED) { return false; }; + if (t.kind != nkind.N_TTAGGED) { return false; }; let a: *node = t.list; if (a == nil) { return false; }; let b: *node = a.next; if (b == nil) { return false; }; if (b.next != nil) { return false; }; - let aptr: bool = (a.kind == N_TPTR); - let bptr: bool = (b.kind == N_TPTR); - let avoid: bool = (a.kind == N_TNAME); + let aptr: bool = (a.kind == nkind.N_TPTR); + let bptr: bool = (b.kind == nkind.N_TPTR); + let avoid: bool = (a.kind == nkind.N_TNAME); if (avoid) { avoid = streq(a.str, "void"); }; - let bvoid: bool = (b.kind == N_TNAME); + let bvoid: bool = (b.kind == nkind.N_TNAME); if (bvoid) { bvoid = streq(b.str, "void"); }; if (aptr) { if (bvoid) { return true; }; }; if (avoid) { if (bptr) { return true; }; }; @@ -5624,9 +5628,9 @@ export fn isnullabletype(t: *node) bool = { // union. The void variant takes the other slot (0 or 1). export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; - if (t.kind != N_TTAGGED) { return 0; }; + if (t.kind != nkind.N_TTAGGED) { return 0; }; let a: *node = t.list; - if (a != nil) { if (a.kind == N_TPTR) { return 0; }; }; + if (a != nil) { if (a.kind == nkind.N_TPTR) { return 0; }; }; return 1; }; @@ -5635,11 +5639,11 @@ export fn nullableptrtag(t: *node) i32 = { // `return;` in a tagged-union-returning fn to the void variant's tag. fn voidvariantindex(tagged: *node) i32 = { if (tagged == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, "void")) { return idx; }; }; v = v.next; @@ -5655,20 +5659,20 @@ fn rhstargetname(c: *cgen, rhs: *node) str = { let nm: str; nm.ptr = nil; nm.len = 0; if (rhs == nil) { return nm; }; - if (rhs.kind == N_CAST) { + if (rhs.kind == nkind.N_CAST) { let t: *node = rhs.rhs; if (t != nil) { - if (t.kind == N_TNAME) { return t.str; }; + if (t.kind == nkind.N_TNAME) { return t.str; }; }; return nm; }; - if (rhs.kind == N_STRLIT) { return "str"; }; - if (rhs.kind == N_IDENT) { + if (rhs.kind == nkind.N_STRLIT) { return "str"; }; + if (rhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, rhs.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { return tn.str; }; + if (tn.kind == nkind.N_TNAME) { return tn.str; }; }; }; }; @@ -5687,7 +5691,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, wantname)) { return idx; }; }; v = v.next; @@ -5700,7 +5704,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let idx: i32 = 0; for (v != nil) { let visstr: bool = false; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (isstrtype(c, v)) { visstr = true; }; }; if (visstr == wantstr) { return idx; }; @@ -5716,7 +5720,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { // cgexpr is a thin dispatcher over n.kind; each non-trivial branch // lives in a per-kind helper (cgstrlit, cgident, cgindex, cgmatch, // cgdot, cgun, cgbin, cgcall, cgassign). Trivial literal loads -// (N_INTLIT, N_RUNELIT, N_TRUE/FALSE/NIL, N_CAST) stay inline. +// (nkind.N_INTLIT, nkind.N_RUNELIT, nkind.N_TRUE/FALSE/NIL, nkind.N_CAST) stay inline. // // The remainder of cgen lives in cgen.ww (foundation: types, emit // primitives, the collect* tables, FFI/module maps) and cgenstmt.ww @@ -5737,7 +5741,7 @@ fn cgexpr(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_INTLIT) { + if (k == nkind.N_INTLIT) { // Print signed (i64), not unsigned (u64). C cgen uses // `$%lld` so 64-bit constants with bit 63 set show up as // negative — e.g. FNV-1a's offset basis prints as @@ -5747,39 +5751,39 @@ fn cgexpr(c: *cgen, n: *node) void = { emitline(", AX\n"); return; }; - if (k == N_RUNELIT) { + if (k == nkind.N_RUNELIT) { emitline("\tMOVQ\t$"); emitint(n.uval: i64); emitline(", AX\n"); return; }; - if (k == N_STRLIT) { cgstrlit(c, n); return; }; - if (k == N_TRUE) { + if (k == nkind.N_STRLIT) { cgstrlit(c, n); return; }; + if (k == nkind.N_TRUE) { emitline("\tMOVQ\t$1, AX\n"); return; }; - if (k == N_FALSE) { + if (k == nkind.N_FALSE) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_NIL) { + if (k == nkind.N_NIL) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_VOIDLIT) { + if (k == nkind.N_VOIDLIT) { // void value: zero-size, but the consumer's ABI expects a // deterministic AX. Emit 0 like nil/false do. emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_IDENT) { cgident(c, n); return; }; + if (k == nkind.N_IDENT) { cgident(c, n); return; }; - if (k == N_INDEX) { cgindex(c, n); return; }; + if (k == nkind.N_INDEX) { cgindex(c, n); return; }; - if (k == N_MATCH) { cgmatch(c, n); return; }; + if (k == nkind.N_MATCH) { cgmatch(c, n); return; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // Type casts are mostly no-ops at the asm level for our // integer-shaped operands. Evaluate the source; AX holds // the bits unchanged. (Sign- or zero-extending narrow loads @@ -5789,38 +5793,38 @@ fn cgexpr(c: *cgen, n: *node) void = { return; }; - if (k == N_DOT) { cgdot(c, n); return; }; + if (k == nkind.N_DOT) { cgdot(c, n); return; }; - if (k == N_UN) { cgun(c, n); return; }; + if (k == nkind.N_UN) { cgun(c, n); return; }; - if (k == N_BIN) { cgbin(c, n); return; }; + if (k == nkind.N_BIN) { cgbin(c, n); return; }; - if (k == N_CALL) { cgcall(c, n); return; }; + if (k == nkind.N_CALL) { cgcall(c, n); return; }; - if (k == N_ASSIGN) { cgassign(c, n); return; }; + if (k == nkind.N_ASSIGN) { cgassign(c, n); return; }; - if (k == N_TRYPROP) { cgtryprop(c, n); return; }; - if (k == N_TRYUNW) { cgtryunw(c, n); return; }; - if (k == N_TYPETEST) { cgtypetest(c, n); return; }; - if (k == N_TYPEASSERT) { cgtypeassert(c, n); return; }; + if (k == nkind.N_TRYPROP) { cgtryprop(c, n); return; }; + if (k == nkind.N_TRYUNW) { cgtryunw(c, n); return; }; + if (k == nkind.N_TYPETEST) { cgtypetest(c, n); return; }; + if (k == nkind.N_TYPEASSERT) { cgtypeassert(c, n); return; }; }; // cgtagvariantidx — find the 0-based variant index of `vt` inside the // tagged-union type expression `tagged`. -1 if `tagged` isn't an -// N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch +// nkind.N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch // does inline; pulled out so `is` / `as` can reuse it. fn cgtagvariantidx(tagged: *node, vt: *node) i32 = { if (tagged == nil) { return -1; }; if (vt == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let want: str; want.ptr = nil; want.len = 0; - if (vt.kind == N_TNAME) { want = vt.str; }; + if (vt.kind == nkind.N_TNAME) { want = vt.str; }; if (want.len == 0) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, want)) { return idx; }; }; v = v.next; @@ -5849,17 +5853,17 @@ fn cgtryprop(c: *cgen, n: *node) void = { // shuffle (DX,CX) → (AX,BX); else move DX → AX. let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -5893,17 +5897,17 @@ fn cgtryunw(c: *cgen, n: *node) void = { // Unwrap success value. (Same shuffle pattern as cgtryprop.) let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -5935,7 +5939,7 @@ fn cgtypetest(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -5966,33 +5970,33 @@ fn cgtypetest(c: *cgen, n: *node) void = { // isenumexpr — does this expression's static type resolve to an enum? // Recognises enum-member access (`Foo.MEMBER`), enum-typed local -// idents, and N_BIN whose either operand is enum (so `R | W` flows +// idents, and nkind.N_BIN whose either operand is enum (so `R | W` flows // through the cast pass-through too). fn isenumexpr(c: *cgen, e: *node) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_DOT) { + if (k == nkind.N_DOT) { if (e.lhs != nil) { - if (e.lhs.kind == N_IDENT) { + if (e.lhs.kind == nkind.N_IDENT) { if (enumlookup(c, e.lhs.str) != nil) { return true; }; }; }; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let lc: *local = localfindnode(c, e.str); if (lc != nil) { if (lc.tnode != nil) { - if (lc.tnode.kind == N_TNAME) { + if (lc.tnode.kind == nkind.N_TNAME) { if (enumlookup(c, lc.tnode.str) != nil) { return true; }; }; }; }; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { if (isenumexpr(c, e.lhs)) { return true; }; if (isenumexpr(c, e.rhs)) { return true; }; }; - if (k == N_UN) { + if (k == nkind.N_UN) { if (isenumexpr(c, e.lhs)) { return true; }; }; return false; @@ -6000,8 +6004,8 @@ fn isenumexpr(c: *cgen, e: *node) bool = { fn isenumtype(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TENUM) { return true; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TENUM) { return true; }; + if (t.kind == nkind.N_TNAME) { if (enumlookup(c, t.str) != nil) { return true; }; }; return false; @@ -6023,7 +6027,7 @@ fn cgtypeassert(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -6125,11 +6129,11 @@ fn cgindex(c: *cgen, n: *node) void = { let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -6143,7 +6147,7 @@ fn cgindex(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -6192,7 +6196,7 @@ fn cgmatch(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (scrut != nil) { - if (scrut.kind == N_IDENT) { + if (scrut.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, scrut.str); if (lc != nil) { scrutoff = lc.off; @@ -6220,7 +6224,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // void arm: skip if ptr != 0. let ptr_tag: i32 = nullableptrtag(scrutt); let cur_tag: i32 = 0; - if (pat.kind == N_TPTR) { cur_tag = ptr_tag; } + if (pat.kind == nkind.N_TPTR) { cur_tag = ptr_tag; } else { if (ptr_tag == 0) { cur_tag = 1; }; }; emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -6236,15 +6240,15 @@ fn cgmatch(c: *cgen, n: *node) void = { } else { let want: i32 = 0; if (scrutt != nil) { - if (scrutt.kind == N_TTAGGED) { + if (scrutt.kind == nkind.N_TTAGGED) { let patname: str; patname.ptr = nil; patname.len = 0; - if (pat.kind == N_TNAME) { patname = pat.str; }; + if (pat.kind == nkind.N_TNAME) { patname = pat.str; }; let v: *node = scrutt.list; let idx: i32 = 0; let found: bool = false; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, patname)) { want = idx; found = true; @@ -6278,7 +6282,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // Bind the pointer (or skip for the // void arm, which has zero-size). The // value IS slot+0. - if (pat.kind == N_TPTR) { + if (pat.kind == nkind.N_TPTR) { let voff: i32 = localalloc(c, bn, 8, pat); emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -6334,12 +6338,12 @@ fn cgdot(c: *cgen, n: *node) void = { if (lhs != nil) { let etname: str; etname.ptr = nil; etname.len = 0; - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { if (lhs.lhs != nil) { - if (lhs.lhs.kind == N_IDENT) { + if (lhs.lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; }; @@ -6358,7 +6362,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -6366,12 +6370,12 @@ fn cgdot(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then field load. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; @@ -6412,7 +6416,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Direct struct local: field load at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -6446,7 +6450,7 @@ fn cgdot(c: *cgen, n: *node) void = { // Array pseudo-fields: `.ptr` is the array's // address (LEAQ); `.len` is the static element // count (immediate). - if (lkind == N_TARRAY) { + if (lkind == nkind.N_TARRAY) { if (streq(fld, "ptr")) { emitline("\tLEAQ\t"); emitoff(lc.off: i64); @@ -6457,7 +6461,7 @@ fn cgdot(c: *cgen, n: *node) void = { let lenn: *node = tn.rhs; let alen: i64 = 0i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { alen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { alen = lenn.uval: i64; }; }; emitline("\tMOVQ\t$"); emitint(alen); @@ -6471,7 +6475,7 @@ fn cgdot(c: *cgen, n: *node) void = { // the scalar in an 8B slot and the str in 16B). For // a str element, load both halves into (AX, BX) so // chains like `t.1.len` propagate correctly. - if (lkind == N_TTUPLE) { + if (lkind == nkind.N_TTUPLE) { let idx: i32 = fldnumidx(fld); if (idx >= 0) { let tp: *node = tn.list; @@ -6518,15 +6522,15 @@ fn cgdot(c: *cgen, n: *node) void = { // Pointer to str/slice (`*[]u8`, `*str`): // deref, then load at delta within the // pointed-to header. C cgen does the same. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { emitline("\tMOVQ\t"); emitoff(lc.off: i64); @@ -6549,12 +6553,12 @@ fn cgdot(c: *cgen, n: *node) void = { // Sdef-backed strs aren't laid out in memory, so falling // through to the SB-load fallback below would mis-emit // `MOVQ (SB), AX` (looking up the field name as a - // symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch. + // symbol). Mirrors cmd/w6c/cgen.c nkind.N_DOT off==0 / Sdef branch. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let drhs: *node = deflookuprhs(c, lhs.str); if (drhs != nil) { - if (drhs.kind == N_STRLIT) { + if (drhs.kind == nkind.N_STRLIT) { let bytes: str = drhs.str; if (streq(fld, "ptr")) { let lab: str = internstrlit(c, bytes); @@ -6574,11 +6578,11 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Module-qualified value reference: `mod.name` where `mod` - // is N_IDENT bound as skind.SK_USE and the leaf isn't a local. + // is nkind.N_IDENT bound as skind.SK_USE and the leaf isn't a local. // Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback // the C cgen takes when bt is NULL/tyerr. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { emitline("\tMOVQ\t"); emitsymname(c, fld); emitline("(SB), AX\n"); @@ -6605,7 +6609,7 @@ fn cgdot(c: *cgen, n: *node) void = { // itself, so reads silently get the pointer value instead of // the field. (Showed up porting w6l/pass.ww.) if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, lhs); if (innert != nil) { let sname: str = innert.str; @@ -6654,7 +6658,7 @@ fn cgun(c: *cgen, n: *node) void = { if (n.op == tkind.TK_AMP) { let opnd: *node = n.lhs; if (opnd != nil) { - if (opnd.kind == N_IDENT) { + if (opnd.kind == nkind.N_IDENT) { let nm: str = opnd.str; let off: i32 = localfind(c, nm); if (off != 0) { @@ -6760,7 +6764,7 @@ fn cgcall(c: *cgen, n: *node) void = { let calleename: str; calleename.ptr = nil; calleename.len = 0; // Detect fn-pointer field call: `w.emit(args)` where `w` is - // a struct local and `emit` is an N_TFN field. Load the + // a struct local and `emit` is an nkind.N_TFN field. Load the // field value into AX and CALL through it. Also detect a // bare `fp(args)` where `fp` is a local holding a function // pointer — mirror C cgen's localfind dispatch (commit @@ -6768,17 +6772,17 @@ fn cgcall(c: *cgen, n: *node) void = { // the linker rightly fails. let isfnptrcall: bool = false; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cn: str = callee.str; if (localfindnode(c, cn) != nil) { isfnptrcall = true; }; }; - if (callee.kind == N_DOT) { + if (callee.kind == nkind.N_DOT) { let base: *node = callee.lhs; let fld: str = callee.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -6787,11 +6791,11 @@ fn cgcall(c: *cgen, n: *node) void = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; if (sname.len > 0) { @@ -6803,7 +6807,7 @@ fn cgcall(c: *cgen, n: *node) void = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft != nil) { - if (ft.kind == N_TFN) { + if (ft.kind == nkind.N_TFN) { isfnptrcall = true; }; }; @@ -6830,10 +6834,10 @@ fn cgcall(c: *cgen, n: *node) void = { } else { emitline("\tCALL\t"); if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; emitsymname(c, calleename); - } else { if (callee.kind == N_DOT) { + } else { if (callee.kind == nkind.N_DOT) { calleename = callee.str; emitsymname(c, calleename); };}; @@ -6854,10 +6858,10 @@ fn cgcall(c: *cgen, n: *node) void = { fn cgassign(c: *cgen, n: *node) void = { let lhs: *node = n.lhs; // Discard lvalue `_ = expr;` — evaluate rhs for side effects, - // write nothing. Detected by lhs being an N_IDENT with empty str + // write nothing. Detected by lhs being an nkind.N_IDENT with empty str // (planted by parseprimary on the tkind.TK_UNDER token). if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { if (lhs.str.len == 0) { if (n.op == tkind.TK_ASSIGN) { cgexpr(c, n.rhs); @@ -6872,22 +6876,22 @@ fn cgassign(c: *cgen, n: *node) void = { // We default to MOVQ (8B) since most fixtures use it; for // `*bool` / `*u8` / `*i32` we narrow via the local's tnode. if (lhs != nil) { - if (lhs.kind == N_UN) { + if (lhs.kind == nkind.N_UN) { if (lhs.op == tkind.TK_STAR) { if (n.op == tkind.TK_ASSIGN) { let inner: *node = lhs.lhs; let elemstr: bool = false; let storeop: str = "MOVQ"; if (inner != nil) { - if (inner.kind == N_IDENT) { + if (inner.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, inner.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TPTR) { + if (tn.kind == nkind.N_TPTR) { let pe: *node = tn.lhs; if (pe != nil) { - if (pe.kind == N_TNAME) { + if (pe.kind == nkind.N_TNAME) { if (streq(pe.str, "str")) { elemstr = true; } else { let ps: i32 = primsize(pe.str); @@ -6931,20 +6935,20 @@ fn cgassign(c: *cgen, n: *node) void = { // Array/slice/ptr index store: `arr[i] = v;`. Element size // from base.tnode picks MOVB vs MOVQ. if (lhs != nil) { - if (lhs.kind == N_INDEX) { + if (lhs.kind == nkind.N_INDEX) { if (n.op == tkind.TK_ASSIGN) { let base: *node = lhs.lhs; let idx: *node = lhs.rhs; let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -6962,7 +6966,7 @@ fn cgassign(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -6995,11 +6999,11 @@ fn cgassign(c: *cgen, n: *node) void = { // `p.f = expr;`. Only plain `=` is wired (compound on field // is rare and not yet needed by our fixtures). if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -7007,12 +7011,12 @@ fn cgassign(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then store. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); @@ -7081,7 +7085,7 @@ fn cgassign(c: *cgen, n: *node) void = { }; }; // Direct struct local: store at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -7108,15 +7112,15 @@ fn cgassign(c: *cgen, n: *node) void = { if (streq(fld, "len")) { delta = 8; }; if (streq(fld, "cap")) { delta = 16; }; if (delta >= 0) { - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { if (n.op != tkind.TK_ASSIGN) { // Compound on `(*str|*slice).field`: load @@ -7175,11 +7179,11 @@ fn cgassign(c: *cgen, n: *node) void = { // store. Only plain `=` is wired here; chained compound on a // pointer-field hasn't surfaced. if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { let sname: str = innert.str; @@ -7235,7 +7239,7 @@ fn cgassign(c: *cgen, n: *node) void = { // forms (+= -= *= /=); other compounds fall back to // "evaluate rhs, replace". Mirrors C cgen's IDENT-assign path. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let off: i32 = localfind(c, nm); if (off == 0) { return; }; @@ -7320,28 +7324,28 @@ fn cgstmt(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_BLOCK) { cgblock(c, n); return; }; + if (k == nkind.N_BLOCK) { cgblock(c, n); return; }; - if (k == N_RETURN) { cgreturn(c, n); return; }; + if (k == nkind.N_RETURN) { cgreturn(c, n); return; }; - if (k == N_EXPRSTMT) { cgexprstmt(c, n); return; }; + if (k == nkind.N_EXPRSTMT) { cgexprstmt(c, n); return; }; - if (k == N_LET) { cglet(c, n); return; }; + if (k == nkind.N_LET) { cglet(c, n); return; }; - if (k == N_IF) { cgif(c, n); return; }; + if (k == nkind.N_IF) { cgif(c, n); return; }; - if (k == N_FOR) { cgfor(c, n); return; }; + if (k == nkind.N_FOR) { cgfor(c, n); return; }; - if (k == N_MASSIGN) { cgmassign(c, n); return; }; + if (k == nkind.N_MASSIGN) { cgmassign(c, n); return; }; - if (k == N_MLET) { cgmlet(c, n); return; }; + if (k == nkind.N_MLET) { cgmlet(c, n); return; }; - if (k == N_BREAK) { cgbreak(c, n); return; }; - if (k == N_CONTINUE) { cgcontinue(c, n); return; }; + if (k == nkind.N_BREAK) { cgbreak(c, n); return; }; + if (k == nkind.N_CONTINUE) { cgcontinue(c, n); return; }; - if (k == N_YIELD) { cgyield(c, n); return; }; + if (k == nkind.N_YIELD) { cgyield(c, n); return; }; - if (k == N_DEFER) { + if (k == nkind.N_DEFER) { if (c.defertop < DEFER_MAX) { c.deferbuf[c.defertop] = n.lhs; c.defertop += 1; @@ -7397,7 +7401,7 @@ fn cgreturn(c: *cgen, n: *node) void = { // DX = str.ptr, CX = str.len. // 24B convention mirrors the tagged-union return below; receive // sites destructure off the same regs regardless of position. - if (rhs.kind == N_TUPLE) { + if (rhs.kind == nkind.N_TUPLE) { let v: *node = rhs.list; if (v != nil) { let v2: *node = v.next; @@ -7519,13 +7523,13 @@ fn cglet(c: *cgen, n: *node) void = { if (istaggedtype(n.lhs)) { let nullable: bool = isnullabletype(n.lhs); let rhsreturnstagged: bool = false; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let calleename: str; calleename.ptr = nil; calleename.len = 0; - if (callee.kind == N_IDENT) { calleename = callee.str; }; - if (callee.kind == N_DOT) { calleename = callee.str; }; + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; }; + if (callee.kind == nkind.N_DOT) { calleename = callee.str; }; if (calleename.len > 0) { let rt: *node = fnretlookup(c, calleename); if (istaggedtype(rt)) { rhsreturnstagged = true; }; @@ -7588,7 +7592,7 @@ fn cglet(c: *cgen, n: *node) void = { // Layout is positional, so we route each register to the // slot dictated by element type, not by AX/DX position. if (n.lhs != nil) { - if (n.lhs.kind == N_TTUPLE) { + if (n.lhs.kind == nkind.N_TTUPLE) { let p0: *node = n.lhs.list; let p1: *node = nil; if (p0 != nil) { p1 = p0.next; }; @@ -7629,13 +7633,13 @@ fn cglet(c: *cgen, n: *node) void = { // Array literal init: `let xs: [N]T = [a, b, c];` (or [_]T). // Walk elements in declaration order, store each at off + i*esz // using the right width for the element type. Trailing `...` - // after the last value (an N_FIELD with str=="...") fills the + // after the last value (an nkind.N_FIELD with str=="...") fills the // remaining slots up to the declared length with that value. - if (rhs.kind == N_ARRLIT) { + if (rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -7647,7 +7651,7 @@ fn cglet(c: *cgen, n: *node) void = { let repeat: bool = false; let e: *node = rhs.list; for (e != nil) { - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { repeat = true; e = nil; @@ -7677,9 +7681,9 @@ fn cglet(c: *cgen, n: *node) void = { if (repeat) { let total: i32 = idx; if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs != nil) { - if (n.lhs.rhs.kind == N_INTLIT) { + if (n.lhs.rhs.kind == nkind.N_INTLIT) { total = n.lhs.rhs.uval: i32; }; }; @@ -7704,13 +7708,13 @@ fn cglet(c: *cgen, n: *node) void = { // op == tkind.TK_ELLIPSIS (autofill marker from the parser), the // entire slot is zero-filled first so unmentioned fields // read as 0. - if (rhs.kind == N_STRUCTLIT) { + if (rhs.kind == nkind.N_STRUCTLIT) { let trefn: *node = rhs.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (trefn != nil) { - if (trefn.kind == N_IDENT) { sname = trefn.str; } - else { if (trefn.kind == N_TNAME) { sname = trefn.str; }; }; + if (trefn.kind == nkind.N_IDENT) { sname = trefn.str; } + else { if (trefn.kind == nkind.N_TNAME) { sname = trefn.str; }; }; }; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -7739,7 +7743,7 @@ fn cglet(c: *cgen, n: *node) void = { }; let fieldnode: *node = rhs.list; for (fieldnode != nil) { - if (fieldnode.kind == N_FIELD) { + if (fieldnode.kind == nkind.N_FIELD) { let fname: str = fieldnode.str; let fi: *fieldinfo = si.fields; for (fi != nil) { @@ -7874,7 +7878,7 @@ fn cgmassign(c: *cgen, n: *node) void = { let l1: *node = nil; if (l0 != nil) { l1 = l0.next; }; if (l0 != nil) { - if (l0.kind == N_IDENT) { + if (l0.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l0.str); if (off != 0) { emitline("\tMOVQ\tAX, "); @@ -7885,7 +7889,7 @@ fn cgmassign(c: *cgen, n: *node) void = { }; emitline("\tPOPQ\tDX\n"); if (l1 != nil) { - if (l1.kind == N_IDENT) { + if (l1.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l1.str); if (off != 0) { emitline("\tMOVQ\tDX, "); @@ -7903,7 +7907,7 @@ fn cgmassign(c: *cgen, n: *node) void = { // type is taken from its explicit annotation (l.lhs) when present // or inferred from the called fn's return-type tuple element. // -// Per the AX:DX:CX return convention (mirrors C cgen N_MLET): +// Per the AX:DX:CX return convention (mirrors C cgen nkind.N_MLET): // (scalar, scalar) — AX → l0, DX → l1. // (scalar, str) — AX → scalar slot, (DX, CX) → str slot // as (.ptr, .len). Position-agnostic — the @@ -7914,17 +7918,17 @@ fn cgmlet(c: *cgen, n: *node) void = { let p0t: *node = nil; let p1t: *node = nil; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; @@ -8049,7 +8053,7 @@ use strconv; fn scanlocals(c: *cgen, n: *node) i32 = { if (n == nil) { return 0; }; let total: i32 = 0; - if (n.kind == N_LET) { + if (n.kind == nkind.N_LET) { // Match localadd's rounding: < 8 bumps to 8, then 8-align. // scanlocals must agree with localadd or the prologue // SUBQ undersizes the frame and lets overflow into the @@ -8068,21 +8072,21 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // the rhs call's return-tuple element type. Marking via // scanseenmark also dedupes the recursive descent into n.list // so each child isn't counted again at the default 8B. - if (n.kind == N_MLET) { + if (n.kind == nkind.N_MLET) { let p0t: *node = nil; let p1t: *node = nil; if (n.rhs != nil) { - if (n.rhs.kind == N_CALL) { + if (n.rhs.kind == nkind.N_CALL) { let callee: *node = n.rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; @@ -8117,7 +8121,7 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // so two separate matches in the same function each allocate // their `v`/`e` slots fresh. Treating these as deduped would // shrink the frame below what localadd then bumps it to. - if (n.kind == N_MCASE) { + if (n.kind == nkind.N_MCASE) { let bn: str = n.str; if (bn.len > 0) { let pat: *node = n.lhs; @@ -8149,7 +8153,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { let p: *node = params; let idx: i32 = 0; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (istaggedtype(p.lhs)) { // tagged-union param: spill size/8 registers @@ -8229,7 +8233,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let isffi: bool = false; let a: *node = fn_.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let an: str = a.str; if (streq(an, "symbol")) { isffi = true; }; }; @@ -8253,7 +8257,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let scanp: *node = fn_.list; let frame: i32 = 0; for (scanp != nil) { - if (scanp.kind == N_PARAM) { + if (scanp.kind == nkind.N_PARAM) { if (istaggedtype(scanp.lhs)) { frame += 24; } else { if (isslicetype(c, scanp.lhs)) { frame += 24; } else { if (isstrtype(c, scanp.lhs)) { frame += 16; } @@ -8310,7 +8314,7 @@ export fn cgfile(c: *cgen, file: *node) void = { collectmods(c, file); let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.body != nil) { cgfn(c, d); }; @@ -8329,17 +8333,17 @@ export fn cgfile(c: *cgen, file: *node) void = { // then by assembling + linking + running the result. // // Current coverage: -// - decls: N_FILE, N_FNDECL (params, frame for locals, prologue +// - decls: nkind.N_FILE, nkind.N_FNDECL (params, frame for locals, prologue // + dual-epilogue suppression; FFI body-less fn skipped) -// - stmts: N_BLOCK, N_RETURN, N_EXPRSTMT, N_LET (no init), -// N_LET (int-literal / ident / call / N_BIN init), -// N_IF (with optional else), N_FOR (cond-only and full -// init/cond/post), N_BREAK, N_CONTINUE -// - exprs: N_INTLIT, N_IDENT (local/param), N_BIN with full op +// - stmts: nkind.N_BLOCK, nkind.N_RETURN, nkind.N_EXPRSTMT, nkind.N_LET (no init), +// nkind.N_LET (int-literal / ident / call / nkind.N_BIN init), +// nkind.N_IF (with optional else), nkind.N_FOR (cond-only and full +// init/cond/post), nkind.N_BREAK, nkind.N_CONTINUE +// - exprs: nkind.N_INTLIT, nkind.N_IDENT (local/param), nkind.N_BIN with full op // coverage (+/-/*/// %, &/|/^, <>, comparisons with -// signed-vs-unsigned dispatch, &&/||), N_UN (- ! ~ & *), -// N_CALL (recursive R-to-L push, pop into argregs L-to-R), -// N_ASSIGN to local idents (plain and compound +=/-=) +// signed-vs-unsigned dispatch, &&/||), nkind.N_UN (- ! ~ & *), +// nkind.N_CALL (recursive R-to-L push, pop into argregs L-to-R), +// nkind.N_ASSIGN to local idents (plain and compound +=/-=) // // Type info is shallow — frame slots are 8 bytes per local, all loads // /stores are MOVQ. Programs that mix i8/i32/i64 locals work but spill @@ -8365,7 +8369,7 @@ use cgendecl; // // `type error = str;` makes `error` a struct-shape alias. We track // alias→target so isstrtype / isslicetype / structlookup can -// resolve through the chain. Only direct N_TNAME aliases are mapped; +// resolve through the chain. Only direct nkind.N_TNAME aliases are mapped; // `type p = struct {...}` is handled by collectstructs. type aliasent = struct { @@ -8378,10 +8382,10 @@ fn collectaliases(c: *cgen, file: *node) void = { c.aliases = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind != N_TSTRUCT) { + if (body.kind != nkind.N_TSTRUCT) { let a: *aliasent = amalloc(c.a, 32u64): *aliasent; a.aname = d.str; a.target = body; @@ -8414,11 +8418,11 @@ fn aliaslookup(c: *cgen, name: str) *node = { fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_INTLIT) { *out = e.uval; return true; }; - if (k == N_RUNELIT) { *out = e.uval; return true; }; - if (k == N_TRUE) { *out = 1u64; return true; }; - if (k == N_FALSE) { *out = 0u64; return true; }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { *out = e.uval; return true; }; + if (k == nkind.N_RUNELIT) { *out = e.uval; return true; }; + if (k == nkind.N_TRUE) { *out = 1u64; return true; }; + if (k == nkind.N_FALSE) { *out = 0u64; return true; }; + if (k == nkind.N_IDENT) { let m: *enummember = prev; for (m != nil) { if (streq(m.mname, e.str)) { @@ -8429,7 +8433,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { }; return false; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { let a: u64; let b: u64; if (!enumevalmember(prev, e.lhs, &a)) { return false; }; @@ -8453,7 +8457,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (op == tkind.TK_RSHIFT) { *out = a >> b; return true; }; return false; }; - if (k == N_UN) { + if (k == nkind.N_UN) { let v: u64; if (!enumevalmember(prev, e.lhs, &v)) { return false; }; let op: i32 = e.op; @@ -8469,10 +8473,10 @@ fn collectenums(c: *cgen, file: *node) void = { c.enums = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TENUM) { + if (body.kind == nkind.N_TENUM) { let et: *enumtype = amalloc(c.a, 48u64): *enumtype; et.ename = d.str; et.storage = body.lhs; @@ -8550,7 +8554,7 @@ fn resolvetype(c: *cgen, t: *node) *node = { let depth: i32 = 0; for (depth < 16) { if (cur == nil) { return nil; }; - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let nm: str = cur.str; let next: *node = aliaslookup(c, nm); if (next == nil) { return cur; }; @@ -8563,8 +8567,8 @@ fn resolvetype(c: *cgen, t: *node) *node = { // ---- struct registry ------------------------------------------------ // // Per-file map from struct name → list of fields with computed offsets -// and sizes. Built when cgfile walks N_TYPEDECL with N_TSTRUCT lhs. -// N_DOT and N_ASSIGN consult this to resolve `s.field` for struct or +// and sizes. Built when cgfile walks nkind.N_TYPEDECL with nkind.N_TSTRUCT lhs. +// nkind.N_DOT and nkind.N_ASSIGN consult this to resolve `s.field` for struct or // *struct bases. type fieldinfo = struct { @@ -8587,12 +8591,12 @@ type structinfo = struct { type local = struct { name: str, off: i32, - tnode: *node, // declared type expr (N_TNAME / N_TPTR / ...) or nil + tnode: *node, // declared type expr (nkind.N_TNAME / nkind.N_TPTR / ...) or nil lnext: *local, }; // strlit — interned string literal record. Emitted as a DATA directive -// after all functions; cgexpr N_STRLIT loads (LEAQ ptr, MOVQ len). +// after all functions; cgexpr nkind.N_STRLIT loads (LEAQ ptr, MOVQ len). type strlit = struct { label: str, // "_S_" bytes: str, @@ -8676,7 +8680,7 @@ fn cgeninit(c: *cgen, a: *arena) void = { // match-arm bindings, which C cgen allocates via cgexpr's by-value // `locals` list — so two separate matches each get fresh slots even // when their bind names collide. scanlocals follows the same rule -// for N_MCASE. +// for nkind.N_MCASE. fn localalloc(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { let asz: i32 = sz; if (asz < 8) { asz = 8; }; @@ -8704,7 +8708,7 @@ fn localadd(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { // // On a dedup hit we also overwrite the stored tnode to match // the new declaration's type. C reads `n->lhs->type` (filled - // by the checker) at every N_DOT/N_CAST site; we read + // by the checker) at every nkind.N_DOT/nkind.N_CAST site; we read // `lc.tnode`, so it must follow source order. Without this, // a later `let m: *node` inside a branch keeps an earlier // `let m: i32`'s tnode and `m.next` falls into the SB fallback. @@ -8876,16 +8880,16 @@ fn internstrlit(c: *cgen, bytes: str) str = { fn emitdefconstants(c: *cgen, file: *node) void = { let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let r: *node = d.rhs; let v: u64 = 0u64; let ok: bool = false; if (r != nil) { - if (r.kind == N_INTLIT) { v = r.uval; ok = true; }; - if (r.kind == N_RUNELIT) { v = r.uval; ok = true; }; - if (r.kind == N_TRUE) { v = 1u64; ok = true; }; - if (r.kind == N_FALSE) { v = 0u64; ok = true; }; - if (r.kind == N_NIL) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_INTLIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_RUNELIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_TRUE) { v = 1u64; ok = true; }; + if (r.kind == nkind.N_FALSE) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_NIL) { v = 0u64; ok = true; }; }; if (ok) { emitline("DATA "); @@ -9015,7 +9019,7 @@ fn collectfnrets(c: *cgen, file: *node) void = { c.fnrets = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let f: *fnret = amalloc(c.a, 32u64): *fnret; f.fname = d.str; f.rtype = d.lhs; @@ -9040,7 +9044,7 @@ fn fnretlookup(c: *cgen, name: str) *node = { // // `def NAME: T = LIT;` becomes a DATA symbol the C-side w6c emits; an // ident reference loads it via `MOVQ NAME(SB), AX`. We collect them at -// file load and consult on N_IDENT lookup. +// file load and consult on nkind.N_IDENT lookup. type defent = struct { dname: str, @@ -9052,7 +9056,7 @@ fn collectdefs(c: *cgen, file: *node) void = { c.defs = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let e: *defent = amalloc(c.a, 32u64): *defent; e.dname = d.str; e.drhs = d.rhs; @@ -9108,7 +9112,7 @@ fn collectmods(c: *cgen, file: *node) void = { // Mirror collectfnrets' shape exactly (plain prepend in one // branch). Earlier nested-if/early-return variants tickled a // wwstage cgen bug that dropped most prepends. - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.exported == 0) { if (d.module.len > 0) { if (!streq(d.str, "main")) { @@ -9121,7 +9125,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9132,7 +9136,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9143,7 +9147,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_LET) { + if (d.kind == nkind.N_LET) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9196,15 +9200,15 @@ fn fficollect(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let a: *node = d.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let aname: str = a.str; if (streq(aname, "symbol")) { let symnode: *node = a.list; if (symnode != nil) { - if (symnode.kind == N_STRLIT) { + if (symnode.kind == nkind.N_STRLIT) { let f: *ffi = amalloc(c.a, 48u64): *ffi; f.ident = d.str; f.symbol = symnode.str; diff --git a/selfhost/cmd/wcc/cgen.ww b/selfhost/cmd/wcc/cgen.ww index 7ba34bf8..92267ad6 100644 --- a/selfhost/cmd/wcc/cgen.ww +++ b/selfhost/cmd/wcc/cgen.ww @@ -5,17 +5,17 @@ // then by assembling + linking + running the result. // // Current coverage: -// - decls: N_FILE, N_FNDECL (params, frame for locals, prologue +// - decls: nkind.N_FILE, nkind.N_FNDECL (params, frame for locals, prologue // + dual-epilogue suppression; FFI body-less fn skipped) -// - stmts: N_BLOCK, N_RETURN, N_EXPRSTMT, N_LET (no init), -// N_LET (int-literal / ident / call / N_BIN init), -// N_IF (with optional else), N_FOR (cond-only and full -// init/cond/post), N_BREAK, N_CONTINUE -// - exprs: N_INTLIT, N_IDENT (local/param), N_BIN with full op +// - stmts: nkind.N_BLOCK, nkind.N_RETURN, nkind.N_EXPRSTMT, nkind.N_LET (no init), +// nkind.N_LET (int-literal / ident / call / nkind.N_BIN init), +// nkind.N_IF (with optional else), nkind.N_FOR (cond-only and full +// init/cond/post), nkind.N_BREAK, nkind.N_CONTINUE +// - exprs: nkind.N_INTLIT, nkind.N_IDENT (local/param), nkind.N_BIN with full op // coverage (+/-/*/// %, &/|/^, <>, comparisons with -// signed-vs-unsigned dispatch, &&/||), N_UN (- ! ~ & *), -// N_CALL (recursive R-to-L push, pop into argregs L-to-R), -// N_ASSIGN to local idents (plain and compound +=/-=) +// signed-vs-unsigned dispatch, &&/||), nkind.N_UN (- ! ~ & *), +// nkind.N_CALL (recursive R-to-L push, pop into argregs L-to-R), +// nkind.N_ASSIGN to local idents (plain and compound +=/-=) // // Type info is shallow — frame slots are 8 bytes per local, all loads // /stores are MOVQ. Programs that mix i8/i32/i64 locals work but spill @@ -41,7 +41,7 @@ use cgendecl; // // `type error = str;` makes `error` a struct-shape alias. We track // alias→target so isstrtype / isslicetype / structlookup can -// resolve through the chain. Only direct N_TNAME aliases are mapped; +// resolve through the chain. Only direct nkind.N_TNAME aliases are mapped; // `type p = struct {...}` is handled by collectstructs. type aliasent = struct { @@ -54,10 +54,10 @@ fn collectaliases(c: *cgen, file: *node) void = { c.aliases = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind != N_TSTRUCT) { + if (body.kind != nkind.N_TSTRUCT) { let a: *aliasent = amalloc(c.a, 32u64): *aliasent; a.aname = d.str; a.target = body; @@ -90,11 +90,11 @@ fn aliaslookup(c: *cgen, name: str) *node = { fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_INTLIT) { *out = e.uval; return true; }; - if (k == N_RUNELIT) { *out = e.uval; return true; }; - if (k == N_TRUE) { *out = 1u64; return true; }; - if (k == N_FALSE) { *out = 0u64; return true; }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { *out = e.uval; return true; }; + if (k == nkind.N_RUNELIT) { *out = e.uval; return true; }; + if (k == nkind.N_TRUE) { *out = 1u64; return true; }; + if (k == nkind.N_FALSE) { *out = 0u64; return true; }; + if (k == nkind.N_IDENT) { let m: *enummember = prev; for (m != nil) { if (streq(m.mname, e.str)) { @@ -105,7 +105,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { }; return false; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { let a: u64; let b: u64; if (!enumevalmember(prev, e.lhs, &a)) { return false; }; @@ -129,7 +129,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (op == tkind.TK_RSHIFT) { *out = a >> b; return true; }; return false; }; - if (k == N_UN) { + if (k == nkind.N_UN) { let v: u64; if (!enumevalmember(prev, e.lhs, &v)) { return false; }; let op: i32 = e.op; @@ -145,10 +145,10 @@ fn collectenums(c: *cgen, file: *node) void = { c.enums = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TENUM) { + if (body.kind == nkind.N_TENUM) { let et: *enumtype = amalloc(c.a, 48u64): *enumtype; et.ename = d.str; et.storage = body.lhs; @@ -226,7 +226,7 @@ fn resolvetype(c: *cgen, t: *node) *node = { let depth: i32 = 0; for (depth < 16) { if (cur == nil) { return nil; }; - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let nm: str = cur.str; let next: *node = aliaslookup(c, nm); if (next == nil) { return cur; }; @@ -239,8 +239,8 @@ fn resolvetype(c: *cgen, t: *node) *node = { // ---- struct registry ------------------------------------------------ // // Per-file map from struct name → list of fields with computed offsets -// and sizes. Built when cgfile walks N_TYPEDECL with N_TSTRUCT lhs. -// N_DOT and N_ASSIGN consult this to resolve `s.field` for struct or +// and sizes. Built when cgfile walks nkind.N_TYPEDECL with nkind.N_TSTRUCT lhs. +// nkind.N_DOT and nkind.N_ASSIGN consult this to resolve `s.field` for struct or // *struct bases. type fieldinfo = struct { @@ -263,12 +263,12 @@ type structinfo = struct { type local = struct { name: str, off: i32, - tnode: *node, // declared type expr (N_TNAME / N_TPTR / ...) or nil + tnode: *node, // declared type expr (nkind.N_TNAME / nkind.N_TPTR / ...) or nil lnext: *local, }; // strlit — interned string literal record. Emitted as a DATA directive -// after all functions; cgexpr N_STRLIT loads (LEAQ ptr, MOVQ len). +// after all functions; cgexpr nkind.N_STRLIT loads (LEAQ ptr, MOVQ len). type strlit = struct { label: str, // "_S_" bytes: str, @@ -352,7 +352,7 @@ fn cgeninit(c: *cgen, a: *arena) void = { // match-arm bindings, which C cgen allocates via cgexpr's by-value // `locals` list — so two separate matches each get fresh slots even // when their bind names collide. scanlocals follows the same rule -// for N_MCASE. +// for nkind.N_MCASE. fn localalloc(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { let asz: i32 = sz; if (asz < 8) { asz = 8; }; @@ -380,7 +380,7 @@ fn localadd(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { // // On a dedup hit we also overwrite the stored tnode to match // the new declaration's type. C reads `n->lhs->type` (filled - // by the checker) at every N_DOT/N_CAST site; we read + // by the checker) at every nkind.N_DOT/nkind.N_CAST site; we read // `lc.tnode`, so it must follow source order. Without this, // a later `let m: *node` inside a branch keeps an earlier // `let m: i32`'s tnode and `m.next` falls into the SB fallback. @@ -552,16 +552,16 @@ fn internstrlit(c: *cgen, bytes: str) str = { fn emitdefconstants(c: *cgen, file: *node) void = { let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let r: *node = d.rhs; let v: u64 = 0u64; let ok: bool = false; if (r != nil) { - if (r.kind == N_INTLIT) { v = r.uval; ok = true; }; - if (r.kind == N_RUNELIT) { v = r.uval; ok = true; }; - if (r.kind == N_TRUE) { v = 1u64; ok = true; }; - if (r.kind == N_FALSE) { v = 0u64; ok = true; }; - if (r.kind == N_NIL) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_INTLIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_RUNELIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_TRUE) { v = 1u64; ok = true; }; + if (r.kind == nkind.N_FALSE) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_NIL) { v = 0u64; ok = true; }; }; if (ok) { emitline("DATA "); @@ -691,7 +691,7 @@ fn collectfnrets(c: *cgen, file: *node) void = { c.fnrets = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let f: *fnret = amalloc(c.a, 32u64): *fnret; f.fname = d.str; f.rtype = d.lhs; @@ -716,7 +716,7 @@ fn fnretlookup(c: *cgen, name: str) *node = { // // `def NAME: T = LIT;` becomes a DATA symbol the C-side w6c emits; an // ident reference loads it via `MOVQ NAME(SB), AX`. We collect them at -// file load and consult on N_IDENT lookup. +// file load and consult on nkind.N_IDENT lookup. type defent = struct { dname: str, @@ -728,7 +728,7 @@ fn collectdefs(c: *cgen, file: *node) void = { c.defs = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let e: *defent = amalloc(c.a, 32u64): *defent; e.dname = d.str; e.drhs = d.rhs; @@ -784,7 +784,7 @@ fn collectmods(c: *cgen, file: *node) void = { // Mirror collectfnrets' shape exactly (plain prepend in one // branch). Earlier nested-if/early-return variants tickled a // wwstage cgen bug that dropped most prepends. - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.exported == 0) { if (d.module.len > 0) { if (!streq(d.str, "main")) { @@ -797,7 +797,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -808,7 +808,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -819,7 +819,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_LET) { + if (d.kind == nkind.N_LET) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -872,15 +872,15 @@ fn fficollect(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let a: *node = d.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let aname: str = a.str; if (streq(aname, "symbol")) { let symnode: *node = a.list; if (symnode != nil) { - if (symnode.kind == N_STRLIT) { + if (symnode.kind == nkind.N_STRLIT) { let f: *ffi = amalloc(c.a, 48u64): *ffi; f.ident = d.str; f.symbol = symnode.str; diff --git a/selfhost/cmd/wcc/cgendecl.ww b/selfhost/cmd/wcc/cgendecl.ww index deff3490..498e3a68 100644 --- a/selfhost/cmd/wcc/cgendecl.ww +++ b/selfhost/cmd/wcc/cgendecl.ww @@ -25,7 +25,7 @@ use strconv; fn scanlocals(c: *cgen, n: *node) i32 = { if (n == nil) { return 0; }; let total: i32 = 0; - if (n.kind == N_LET) { + if (n.kind == nkind.N_LET) { // Match localadd's rounding: < 8 bumps to 8, then 8-align. // scanlocals must agree with localadd or the prologue // SUBQ undersizes the frame and lets overflow into the @@ -44,21 +44,21 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // the rhs call's return-tuple element type. Marking via // scanseenmark also dedupes the recursive descent into n.list // so each child isn't counted again at the default 8B. - if (n.kind == N_MLET) { + if (n.kind == nkind.N_MLET) { let p0t: *node = nil; let p1t: *node = nil; if (n.rhs != nil) { - if (n.rhs.kind == N_CALL) { + if (n.rhs.kind == nkind.N_CALL) { let callee: *node = n.rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; @@ -93,7 +93,7 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // so two separate matches in the same function each allocate // their `v`/`e` slots fresh. Treating these as deduped would // shrink the frame below what localadd then bumps it to. - if (n.kind == N_MCASE) { + if (n.kind == nkind.N_MCASE) { let bn: str = n.str; if (bn.len > 0) { let pat: *node = n.lhs; @@ -125,7 +125,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { let p: *node = params; let idx: i32 = 0; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (istaggedtype(p.lhs)) { // tagged-union param: spill size/8 registers @@ -205,7 +205,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let isffi: bool = false; let a: *node = fn_.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let an: str = a.str; if (streq(an, "symbol")) { isffi = true; }; }; @@ -229,7 +229,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let scanp: *node = fn_.list; let frame: i32 = 0; for (scanp != nil) { - if (scanp.kind == N_PARAM) { + if (scanp.kind == nkind.N_PARAM) { if (istaggedtype(scanp.lhs)) { frame += 24; } else { if (isslicetype(c, scanp.lhs)) { frame += 24; } else { if (isstrtype(c, scanp.lhs)) { frame += 16; } @@ -286,7 +286,7 @@ export fn cgfile(c: *cgen, file: *node) void = { collectmods(c, file); let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.body != nil) { cgfn(c, d); }; diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index 62625ab0..ee321aa7 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -3,7 +3,7 @@ // cgexpr is a thin dispatcher over n.kind; each non-trivial branch // lives in a per-kind helper (cgstrlit, cgident, cgindex, cgmatch, // cgdot, cgun, cgbin, cgcall, cgassign). Trivial literal loads -// (N_INTLIT, N_RUNELIT, N_TRUE/FALSE/NIL, N_CAST) stay inline. +// (nkind.N_INTLIT, nkind.N_RUNELIT, nkind.N_TRUE/FALSE/NIL, nkind.N_CAST) stay inline. // // The remainder of cgen lives in cgen.ww (foundation: types, emit // primitives, the collect* tables, FFI/module maps) and cgenstmt.ww @@ -24,7 +24,7 @@ fn cgexpr(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_INTLIT) { + if (k == nkind.N_INTLIT) { // Print signed (i64), not unsigned (u64). C cgen uses // `$%lld` so 64-bit constants with bit 63 set show up as // negative — e.g. FNV-1a's offset basis prints as @@ -34,39 +34,39 @@ fn cgexpr(c: *cgen, n: *node) void = { emitline(", AX\n"); return; }; - if (k == N_RUNELIT) { + if (k == nkind.N_RUNELIT) { emitline("\tMOVQ\t$"); emitint(n.uval: i64); emitline(", AX\n"); return; }; - if (k == N_STRLIT) { cgstrlit(c, n); return; }; - if (k == N_TRUE) { + if (k == nkind.N_STRLIT) { cgstrlit(c, n); return; }; + if (k == nkind.N_TRUE) { emitline("\tMOVQ\t$1, AX\n"); return; }; - if (k == N_FALSE) { + if (k == nkind.N_FALSE) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_NIL) { + if (k == nkind.N_NIL) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_VOIDLIT) { + if (k == nkind.N_VOIDLIT) { // void value: zero-size, but the consumer's ABI expects a // deterministic AX. Emit 0 like nil/false do. emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_IDENT) { cgident(c, n); return; }; + if (k == nkind.N_IDENT) { cgident(c, n); return; }; - if (k == N_INDEX) { cgindex(c, n); return; }; + if (k == nkind.N_INDEX) { cgindex(c, n); return; }; - if (k == N_MATCH) { cgmatch(c, n); return; }; + if (k == nkind.N_MATCH) { cgmatch(c, n); return; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // Type casts are mostly no-ops at the asm level for our // integer-shaped operands. Evaluate the source; AX holds // the bits unchanged. (Sign- or zero-extending narrow loads @@ -76,38 +76,38 @@ fn cgexpr(c: *cgen, n: *node) void = { return; }; - if (k == N_DOT) { cgdot(c, n); return; }; + if (k == nkind.N_DOT) { cgdot(c, n); return; }; - if (k == N_UN) { cgun(c, n); return; }; + if (k == nkind.N_UN) { cgun(c, n); return; }; - if (k == N_BIN) { cgbin(c, n); return; }; + if (k == nkind.N_BIN) { cgbin(c, n); return; }; - if (k == N_CALL) { cgcall(c, n); return; }; + if (k == nkind.N_CALL) { cgcall(c, n); return; }; - if (k == N_ASSIGN) { cgassign(c, n); return; }; + if (k == nkind.N_ASSIGN) { cgassign(c, n); return; }; - if (k == N_TRYPROP) { cgtryprop(c, n); return; }; - if (k == N_TRYUNW) { cgtryunw(c, n); return; }; - if (k == N_TYPETEST) { cgtypetest(c, n); return; }; - if (k == N_TYPEASSERT) { cgtypeassert(c, n); return; }; + if (k == nkind.N_TRYPROP) { cgtryprop(c, n); return; }; + if (k == nkind.N_TRYUNW) { cgtryunw(c, n); return; }; + if (k == nkind.N_TYPETEST) { cgtypetest(c, n); return; }; + if (k == nkind.N_TYPEASSERT) { cgtypeassert(c, n); return; }; }; // cgtagvariantidx — find the 0-based variant index of `vt` inside the // tagged-union type expression `tagged`. -1 if `tagged` isn't an -// N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch +// nkind.N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch // does inline; pulled out so `is` / `as` can reuse it. fn cgtagvariantidx(tagged: *node, vt: *node) i32 = { if (tagged == nil) { return -1; }; if (vt == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let want: str; want.ptr = nil; want.len = 0; - if (vt.kind == N_TNAME) { want = vt.str; }; + if (vt.kind == nkind.N_TNAME) { want = vt.str; }; if (want.len == 0) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, want)) { return idx; }; }; v = v.next; @@ -136,17 +136,17 @@ fn cgtryprop(c: *cgen, n: *node) void = { // shuffle (DX,CX) → (AX,BX); else move DX → AX. let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -180,17 +180,17 @@ fn cgtryunw(c: *cgen, n: *node) void = { // Unwrap success value. (Same shuffle pattern as cgtryprop.) let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -222,7 +222,7 @@ fn cgtypetest(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -253,33 +253,33 @@ fn cgtypetest(c: *cgen, n: *node) void = { // isenumexpr — does this expression's static type resolve to an enum? // Recognises enum-member access (`Foo.MEMBER`), enum-typed local -// idents, and N_BIN whose either operand is enum (so `R | W` flows +// idents, and nkind.N_BIN whose either operand is enum (so `R | W` flows // through the cast pass-through too). fn isenumexpr(c: *cgen, e: *node) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_DOT) { + if (k == nkind.N_DOT) { if (e.lhs != nil) { - if (e.lhs.kind == N_IDENT) { + if (e.lhs.kind == nkind.N_IDENT) { if (enumlookup(c, e.lhs.str) != nil) { return true; }; }; }; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let lc: *local = localfindnode(c, e.str); if (lc != nil) { if (lc.tnode != nil) { - if (lc.tnode.kind == N_TNAME) { + if (lc.tnode.kind == nkind.N_TNAME) { if (enumlookup(c, lc.tnode.str) != nil) { return true; }; }; }; }; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { if (isenumexpr(c, e.lhs)) { return true; }; if (isenumexpr(c, e.rhs)) { return true; }; }; - if (k == N_UN) { + if (k == nkind.N_UN) { if (isenumexpr(c, e.lhs)) { return true; }; }; return false; @@ -287,8 +287,8 @@ fn isenumexpr(c: *cgen, e: *node) bool = { fn isenumtype(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TENUM) { return true; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TENUM) { return true; }; + if (t.kind == nkind.N_TNAME) { if (enumlookup(c, t.str) != nil) { return true; }; }; return false; @@ -310,7 +310,7 @@ fn cgtypeassert(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -412,11 +412,11 @@ fn cgindex(c: *cgen, n: *node) void = { let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -430,7 +430,7 @@ fn cgindex(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -479,7 +479,7 @@ fn cgmatch(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (scrut != nil) { - if (scrut.kind == N_IDENT) { + if (scrut.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, scrut.str); if (lc != nil) { scrutoff = lc.off; @@ -507,7 +507,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // void arm: skip if ptr != 0. let ptr_tag: i32 = nullableptrtag(scrutt); let cur_tag: i32 = 0; - if (pat.kind == N_TPTR) { cur_tag = ptr_tag; } + if (pat.kind == nkind.N_TPTR) { cur_tag = ptr_tag; } else { if (ptr_tag == 0) { cur_tag = 1; }; }; emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -523,15 +523,15 @@ fn cgmatch(c: *cgen, n: *node) void = { } else { let want: i32 = 0; if (scrutt != nil) { - if (scrutt.kind == N_TTAGGED) { + if (scrutt.kind == nkind.N_TTAGGED) { let patname: str; patname.ptr = nil; patname.len = 0; - if (pat.kind == N_TNAME) { patname = pat.str; }; + if (pat.kind == nkind.N_TNAME) { patname = pat.str; }; let v: *node = scrutt.list; let idx: i32 = 0; let found: bool = false; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, patname)) { want = idx; found = true; @@ -565,7 +565,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // Bind the pointer (or skip for the // void arm, which has zero-size). The // value IS slot+0. - if (pat.kind == N_TPTR) { + if (pat.kind == nkind.N_TPTR) { let voff: i32 = localalloc(c, bn, 8, pat); emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -621,12 +621,12 @@ fn cgdot(c: *cgen, n: *node) void = { if (lhs != nil) { let etname: str; etname.ptr = nil; etname.len = 0; - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { if (lhs.lhs != nil) { - if (lhs.lhs.kind == N_IDENT) { + if (lhs.lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; }; @@ -645,7 +645,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -653,12 +653,12 @@ fn cgdot(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then field load. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; @@ -699,7 +699,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Direct struct local: field load at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -733,7 +733,7 @@ fn cgdot(c: *cgen, n: *node) void = { // Array pseudo-fields: `.ptr` is the array's // address (LEAQ); `.len` is the static element // count (immediate). - if (lkind == N_TARRAY) { + if (lkind == nkind.N_TARRAY) { if (streq(fld, "ptr")) { emitline("\tLEAQ\t"); emitoff(lc.off: i64); @@ -744,7 +744,7 @@ fn cgdot(c: *cgen, n: *node) void = { let lenn: *node = tn.rhs; let alen: i64 = 0i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { alen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { alen = lenn.uval: i64; }; }; emitline("\tMOVQ\t$"); emitint(alen); @@ -758,7 +758,7 @@ fn cgdot(c: *cgen, n: *node) void = { // the scalar in an 8B slot and the str in 16B). For // a str element, load both halves into (AX, BX) so // chains like `t.1.len` propagate correctly. - if (lkind == N_TTUPLE) { + if (lkind == nkind.N_TTUPLE) { let idx: i32 = fldnumidx(fld); if (idx >= 0) { let tp: *node = tn.list; @@ -805,15 +805,15 @@ fn cgdot(c: *cgen, n: *node) void = { // Pointer to str/slice (`*[]u8`, `*str`): // deref, then load at delta within the // pointed-to header. C cgen does the same. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { emitline("\tMOVQ\t"); emitoff(lc.off: i64); @@ -836,12 +836,12 @@ fn cgdot(c: *cgen, n: *node) void = { // Sdef-backed strs aren't laid out in memory, so falling // through to the SB-load fallback below would mis-emit // `MOVQ (SB), AX` (looking up the field name as a - // symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch. + // symbol). Mirrors cmd/w6c/cgen.c nkind.N_DOT off==0 / Sdef branch. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let drhs: *node = deflookuprhs(c, lhs.str); if (drhs != nil) { - if (drhs.kind == N_STRLIT) { + if (drhs.kind == nkind.N_STRLIT) { let bytes: str = drhs.str; if (streq(fld, "ptr")) { let lab: str = internstrlit(c, bytes); @@ -861,11 +861,11 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Module-qualified value reference: `mod.name` where `mod` - // is N_IDENT bound as skind.SK_USE and the leaf isn't a local. + // is nkind.N_IDENT bound as skind.SK_USE and the leaf isn't a local. // Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback // the C cgen takes when bt is NULL/tyerr. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { emitline("\tMOVQ\t"); emitsymname(c, fld); emitline("(SB), AX\n"); @@ -892,7 +892,7 @@ fn cgdot(c: *cgen, n: *node) void = { // itself, so reads silently get the pointer value instead of // the field. (Showed up porting w6l/pass.ww.) if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, lhs); if (innert != nil) { let sname: str = innert.str; @@ -941,7 +941,7 @@ fn cgun(c: *cgen, n: *node) void = { if (n.op == tkind.TK_AMP) { let opnd: *node = n.lhs; if (opnd != nil) { - if (opnd.kind == N_IDENT) { + if (opnd.kind == nkind.N_IDENT) { let nm: str = opnd.str; let off: i32 = localfind(c, nm); if (off != 0) { @@ -1047,7 +1047,7 @@ fn cgcall(c: *cgen, n: *node) void = { let calleename: str; calleename.ptr = nil; calleename.len = 0; // Detect fn-pointer field call: `w.emit(args)` where `w` is - // a struct local and `emit` is an N_TFN field. Load the + // a struct local and `emit` is an nkind.N_TFN field. Load the // field value into AX and CALL through it. Also detect a // bare `fp(args)` where `fp` is a local holding a function // pointer — mirror C cgen's localfind dispatch (commit @@ -1055,17 +1055,17 @@ fn cgcall(c: *cgen, n: *node) void = { // the linker rightly fails. let isfnptrcall: bool = false; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cn: str = callee.str; if (localfindnode(c, cn) != nil) { isfnptrcall = true; }; }; - if (callee.kind == N_DOT) { + if (callee.kind == nkind.N_DOT) { let base: *node = callee.lhs; let fld: str = callee.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -1074,11 +1074,11 @@ fn cgcall(c: *cgen, n: *node) void = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; if (sname.len > 0) { @@ -1090,7 +1090,7 @@ fn cgcall(c: *cgen, n: *node) void = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft != nil) { - if (ft.kind == N_TFN) { + if (ft.kind == nkind.N_TFN) { isfnptrcall = true; }; }; @@ -1117,10 +1117,10 @@ fn cgcall(c: *cgen, n: *node) void = { } else { emitline("\tCALL\t"); if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; emitsymname(c, calleename); - } else { if (callee.kind == N_DOT) { + } else { if (callee.kind == nkind.N_DOT) { calleename = callee.str; emitsymname(c, calleename); };}; @@ -1141,10 +1141,10 @@ fn cgcall(c: *cgen, n: *node) void = { fn cgassign(c: *cgen, n: *node) void = { let lhs: *node = n.lhs; // Discard lvalue `_ = expr;` — evaluate rhs for side effects, - // write nothing. Detected by lhs being an N_IDENT with empty str + // write nothing. Detected by lhs being an nkind.N_IDENT with empty str // (planted by parseprimary on the tkind.TK_UNDER token). if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { if (lhs.str.len == 0) { if (n.op == tkind.TK_ASSIGN) { cgexpr(c, n.rhs); @@ -1159,22 +1159,22 @@ fn cgassign(c: *cgen, n: *node) void = { // We default to MOVQ (8B) since most fixtures use it; for // `*bool` / `*u8` / `*i32` we narrow via the local's tnode. if (lhs != nil) { - if (lhs.kind == N_UN) { + if (lhs.kind == nkind.N_UN) { if (lhs.op == tkind.TK_STAR) { if (n.op == tkind.TK_ASSIGN) { let inner: *node = lhs.lhs; let elemstr: bool = false; let storeop: str = "MOVQ"; if (inner != nil) { - if (inner.kind == N_IDENT) { + if (inner.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, inner.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TPTR) { + if (tn.kind == nkind.N_TPTR) { let pe: *node = tn.lhs; if (pe != nil) { - if (pe.kind == N_TNAME) { + if (pe.kind == nkind.N_TNAME) { if (streq(pe.str, "str")) { elemstr = true; } else { let ps: i32 = primsize(pe.str); @@ -1218,20 +1218,20 @@ fn cgassign(c: *cgen, n: *node) void = { // Array/slice/ptr index store: `arr[i] = v;`. Element size // from base.tnode picks MOVB vs MOVQ. if (lhs != nil) { - if (lhs.kind == N_INDEX) { + if (lhs.kind == nkind.N_INDEX) { if (n.op == tkind.TK_ASSIGN) { let base: *node = lhs.lhs; let idx: *node = lhs.rhs; let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -1249,7 +1249,7 @@ fn cgassign(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -1282,11 +1282,11 @@ fn cgassign(c: *cgen, n: *node) void = { // `p.f = expr;`. Only plain `=` is wired (compound on field // is rare and not yet needed by our fixtures). if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -1294,12 +1294,12 @@ fn cgassign(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then store. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); @@ -1368,7 +1368,7 @@ fn cgassign(c: *cgen, n: *node) void = { }; }; // Direct struct local: store at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -1395,15 +1395,15 @@ fn cgassign(c: *cgen, n: *node) void = { if (streq(fld, "len")) { delta = 8; }; if (streq(fld, "cap")) { delta = 16; }; if (delta >= 0) { - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { if (n.op != tkind.TK_ASSIGN) { // Compound on `(*str|*slice).field`: load @@ -1462,11 +1462,11 @@ fn cgassign(c: *cgen, n: *node) void = { // store. Only plain `=` is wired here; chained compound on a // pointer-field hasn't surfaced. if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { let sname: str = innert.str; @@ -1522,7 +1522,7 @@ fn cgassign(c: *cgen, n: *node) void = { // forms (+= -= *= /=); other compounds fall back to // "evaluate rhs, replace". Mirrors C cgen's IDENT-assign path. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let off: i32 = localfind(c, nm); if (off == 0) { return; }; diff --git a/selfhost/cmd/wcc/cgenstmt.ww b/selfhost/cmd/wcc/cgenstmt.ww index 23b842a6..e2654bb2 100644 --- a/selfhost/cmd/wcc/cgenstmt.ww +++ b/selfhost/cmd/wcc/cgenstmt.ww @@ -22,28 +22,28 @@ fn cgstmt(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_BLOCK) { cgblock(c, n); return; }; + if (k == nkind.N_BLOCK) { cgblock(c, n); return; }; - if (k == N_RETURN) { cgreturn(c, n); return; }; + if (k == nkind.N_RETURN) { cgreturn(c, n); return; }; - if (k == N_EXPRSTMT) { cgexprstmt(c, n); return; }; + if (k == nkind.N_EXPRSTMT) { cgexprstmt(c, n); return; }; - if (k == N_LET) { cglet(c, n); return; }; + if (k == nkind.N_LET) { cglet(c, n); return; }; - if (k == N_IF) { cgif(c, n); return; }; + if (k == nkind.N_IF) { cgif(c, n); return; }; - if (k == N_FOR) { cgfor(c, n); return; }; + if (k == nkind.N_FOR) { cgfor(c, n); return; }; - if (k == N_MASSIGN) { cgmassign(c, n); return; }; + if (k == nkind.N_MASSIGN) { cgmassign(c, n); return; }; - if (k == N_MLET) { cgmlet(c, n); return; }; + if (k == nkind.N_MLET) { cgmlet(c, n); return; }; - if (k == N_BREAK) { cgbreak(c, n); return; }; - if (k == N_CONTINUE) { cgcontinue(c, n); return; }; + if (k == nkind.N_BREAK) { cgbreak(c, n); return; }; + if (k == nkind.N_CONTINUE) { cgcontinue(c, n); return; }; - if (k == N_YIELD) { cgyield(c, n); return; }; + if (k == nkind.N_YIELD) { cgyield(c, n); return; }; - if (k == N_DEFER) { + if (k == nkind.N_DEFER) { if (c.defertop < DEFER_MAX) { c.deferbuf[c.defertop] = n.lhs; c.defertop += 1; @@ -99,7 +99,7 @@ fn cgreturn(c: *cgen, n: *node) void = { // DX = str.ptr, CX = str.len. // 24B convention mirrors the tagged-union return below; receive // sites destructure off the same regs regardless of position. - if (rhs.kind == N_TUPLE) { + if (rhs.kind == nkind.N_TUPLE) { let v: *node = rhs.list; if (v != nil) { let v2: *node = v.next; @@ -221,13 +221,13 @@ fn cglet(c: *cgen, n: *node) void = { if (istaggedtype(n.lhs)) { let nullable: bool = isnullabletype(n.lhs); let rhsreturnstagged: bool = false; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let calleename: str; calleename.ptr = nil; calleename.len = 0; - if (callee.kind == N_IDENT) { calleename = callee.str; }; - if (callee.kind == N_DOT) { calleename = callee.str; }; + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; }; + if (callee.kind == nkind.N_DOT) { calleename = callee.str; }; if (calleename.len > 0) { let rt: *node = fnretlookup(c, calleename); if (istaggedtype(rt)) { rhsreturnstagged = true; }; @@ -290,7 +290,7 @@ fn cglet(c: *cgen, n: *node) void = { // Layout is positional, so we route each register to the // slot dictated by element type, not by AX/DX position. if (n.lhs != nil) { - if (n.lhs.kind == N_TTUPLE) { + if (n.lhs.kind == nkind.N_TTUPLE) { let p0: *node = n.lhs.list; let p1: *node = nil; if (p0 != nil) { p1 = p0.next; }; @@ -331,13 +331,13 @@ fn cglet(c: *cgen, n: *node) void = { // Array literal init: `let xs: [N]T = [a, b, c];` (or [_]T). // Walk elements in declaration order, store each at off + i*esz // using the right width for the element type. Trailing `...` - // after the last value (an N_FIELD with str=="...") fills the + // after the last value (an nkind.N_FIELD with str=="...") fills the // remaining slots up to the declared length with that value. - if (rhs.kind == N_ARRLIT) { + if (rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -349,7 +349,7 @@ fn cglet(c: *cgen, n: *node) void = { let repeat: bool = false; let e: *node = rhs.list; for (e != nil) { - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { repeat = true; e = nil; @@ -379,9 +379,9 @@ fn cglet(c: *cgen, n: *node) void = { if (repeat) { let total: i32 = idx; if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs != nil) { - if (n.lhs.rhs.kind == N_INTLIT) { + if (n.lhs.rhs.kind == nkind.N_INTLIT) { total = n.lhs.rhs.uval: i32; }; }; @@ -406,13 +406,13 @@ fn cglet(c: *cgen, n: *node) void = { // op == tkind.TK_ELLIPSIS (autofill marker from the parser), the // entire slot is zero-filled first so unmentioned fields // read as 0. - if (rhs.kind == N_STRUCTLIT) { + if (rhs.kind == nkind.N_STRUCTLIT) { let trefn: *node = rhs.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (trefn != nil) { - if (trefn.kind == N_IDENT) { sname = trefn.str; } - else { if (trefn.kind == N_TNAME) { sname = trefn.str; }; }; + if (trefn.kind == nkind.N_IDENT) { sname = trefn.str; } + else { if (trefn.kind == nkind.N_TNAME) { sname = trefn.str; }; }; }; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -441,7 +441,7 @@ fn cglet(c: *cgen, n: *node) void = { }; let fieldnode: *node = rhs.list; for (fieldnode != nil) { - if (fieldnode.kind == N_FIELD) { + if (fieldnode.kind == nkind.N_FIELD) { let fname: str = fieldnode.str; let fi: *fieldinfo = si.fields; for (fi != nil) { @@ -576,7 +576,7 @@ fn cgmassign(c: *cgen, n: *node) void = { let l1: *node = nil; if (l0 != nil) { l1 = l0.next; }; if (l0 != nil) { - if (l0.kind == N_IDENT) { + if (l0.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l0.str); if (off != 0) { emitline("\tMOVQ\tAX, "); @@ -587,7 +587,7 @@ fn cgmassign(c: *cgen, n: *node) void = { }; emitline("\tPOPQ\tDX\n"); if (l1 != nil) { - if (l1.kind == N_IDENT) { + if (l1.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l1.str); if (off != 0) { emitline("\tMOVQ\tDX, "); @@ -605,7 +605,7 @@ fn cgmassign(c: *cgen, n: *node) void = { // type is taken from its explicit annotation (l.lhs) when present // or inferred from the called fn's return-type tuple element. // -// Per the AX:DX:CX return convention (mirrors C cgen N_MLET): +// Per the AX:DX:CX return convention (mirrors C cgen nkind.N_MLET): // (scalar, scalar) — AX → l0, DX → l1. // (scalar, str) — AX → scalar slot, (DX, CX) → str slot // as (.ptr, .len). Position-agnostic — the @@ -616,17 +616,17 @@ fn cgmlet(c: *cgen, n: *node) void = { let p0t: *node = nil; let p1t: *node = nil; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index 8284b757..cb38129b 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -30,16 +30,16 @@ use strconv; fn pushargsrev(c: *cgen, arg: *node) i32 = { if (arg == nil) { return 0; }; let rest: i32 = pushargsrev(c, arg.next); - // N_SLICE expression as arg: `buf[lo:hi]` builds a slice header + // nkind.N_SLICE expression as arg: `buf[lo:hi]` builds a slice header // on the stack matching C cgen's sequence — push base, push hi, // compute lo, pop into BX/CX, derive len/ptr, push (cap, len, ptr). - if (arg.kind == N_SLICE) { + if (arg.kind == nkind.N_SLICE) { let base: *node = arg.lhs; let lo: *node = arg.rhs; let hi: *node = arg.cond; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); }; @@ -48,7 +48,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); emitline("(BP), AX\n"); @@ -72,20 +72,20 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { } else { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { let lenn: *node = tn.rhs; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { + if (lenn.kind == nkind.N_INTLIT) { emitline("\tMOVQ\t$"); emituint(lenn.uval); emitline(", AX\n"); }; }; - } else { if (tn.kind == N_TSLICE) { + } else { if (tn.kind == nkind.N_TSLICE) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); emitline("(BP), AX\n"); - } else { if (tn.kind == N_TNAME) { + } else { if (tn.kind == nkind.N_TNAME) { if (streq(tn.str, "str")) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); @@ -113,7 +113,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { // Slice/tagged ident args: emit per-register MOVQ+PUSHQ pairs in // reverse order (cap/v1, len/v0, ptr/tag) so a left-to-right pop // into argregs lands the canonical (ptr/tag, len/v0, cap/v1). - if (arg.kind == N_IDENT) { + if (arg.kind == nkind.N_IDENT) { let nm: str = arg.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -154,13 +154,13 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { fn nodeisslice(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return isslicetype(c, lc.tnode); }; return false; }; - if (k == N_SLICE) { return true; }; + if (k == nkind.N_SLICE) { return true; }; return false; }; @@ -170,14 +170,14 @@ fn nodeisslice(c: *cgen, n: *node) bool = { fn nodeisstr(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_STRLIT) { return true; }; - if (k == N_IDENT) { + if (k == nkind.N_STRLIT) { return true; }; + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { + if (tn.kind == nkind.N_TNAME) { let tnm: str = tn.str; if (streq(tnm, "str")) { return true; }; }; @@ -185,10 +185,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = n.lhs; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cnm: str = callee.str; let rt: *node = fnretlookup(c, cnm); return isstrtype(c, rt); @@ -196,7 +196,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; // `.ptr` is *u8 not str; `.len` is i32 not str. @@ -206,17 +206,17 @@ fn nodeisstr(c: *cgen, n: *node) bool = { if (base != nil) { let sname: str; sname.ptr = nil; sname.len = 0; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; }; @@ -224,10 +224,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { // Chained dot (`p.foo.bar`): use dotinnerstructptr // to resolve the inner chain to the *struct it lands // on, then look up `fld` in that struct. - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { - if (innert.kind == N_TNAME) { sname = innert.str; }; + if (innert.kind == nkind.N_TNAME) { sname = innert.str; }; }; }; if (sname.len > 0) { @@ -246,7 +246,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { return isstrtype(c, n.rhs); }; return false; @@ -266,13 +266,13 @@ fn typenameisunsigned(nm: str) bool = { // typenodeisunsigned — recurse through TNAME / TPTR / TSLICE etc. fn typenodeisunsigned(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { return typenameisunsigned(t.str); }; + if (t.kind == nkind.N_TNAME) { return typenameisunsigned(t.str); }; return false; }; // typeis8byteprimitive — does this type take exactly one 8-byte // slot (pointer / fn-ptr / 64-bit int / chan / scalar primitive -// padded up to 8) rather than a wider aggregate? Used by N_LET +// padded up to 8) rather than a wider aggregate? Used by nkind.N_LET // zero-init to mirror C cgen's "only zero if sz == 8 at the type // level" rule. Strings (16), slices (24), tagged unions (>=16), // tuples (16), structs (varies), arrays — all fall through to @@ -280,14 +280,14 @@ fn typenodeisunsigned(t: *node) bool = { fn typeis8byteprimitive(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; let k: i32 = t.kind; - if (k == N_TPTR) { return true; }; - if (k == N_TFN) { return true; }; - if (k == N_TCHAN) { return true; }; - if (k == N_TSLICE) { return false; }; - if (k == N_TARRAY) { return false; }; - if (k == N_TTUPLE) { return false; }; - if (k == N_TTAGGED){ return false; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { return true; }; + if (k == nkind.N_TFN) { return true; }; + if (k == nkind.N_TCHAN) { return true; }; + if (k == nkind.N_TSLICE) { return false; }; + if (k == nkind.N_TARRAY) { return false; }; + if (k == nkind.N_TTUPLE) { return false; }; + if (k == nkind.N_TTAGGED){ return false; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return false; }; // Struct alias: not a primitive even if the slot is 8B. @@ -322,7 +322,7 @@ fn fieldloadop(f: *fieldinfo) str = { if (sz == 4) { let t: *node = f.tnode; if (t != nil) { - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { if (typenameissigned(t.str)) { return "MOVSXD"; }; }; }; @@ -347,11 +347,11 @@ fn fieldstoreop(f: *fieldinfo) str = { // the slice element type. fn indexbaseesz(c: *cgen, base: *node) i32 = { if (base == nil) { return 8; }; - if (base.kind != N_DOT) { return 8; }; + if (base.kind != nkind.N_DOT) { return 8; }; let fld: str = base.str; let inner: *node = base.lhs; if (inner == nil) { return 8; }; - if (inner.kind != N_IDENT) { return 8; }; + if (inner.kind != nkind.N_IDENT) { return 8; }; let nm: str = inner.str; let lc: *local = localfindnode(c, nm); if (lc == nil) { return 8; }; @@ -361,12 +361,12 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { // `.ptr` pseudo-field on str/slice → element of the str/slice. if (streq(fld, "ptr")) { let innert: *node = tn; - if (tn.kind == N_TPTR) { innert = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { innert = tn.lhs; }; if (innert == nil) { return 8; }; - if (innert.kind == N_TNAME) { + if (innert.kind == nkind.N_TNAME) { if (streq(innert.str, "str")) { return 1; }; }; - if (innert.kind == N_TSLICE) { return elemsizeof(innert); }; + if (innert.kind == nkind.N_TSLICE) { return elemsizeof(innert); }; return 8; }; @@ -374,11 +374,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let pinner: *node = tn.lhs; if (pinner != nil) { - if (pinner.kind == N_TNAME) { sname = pinner.str; }; + if (pinner.kind == nkind.N_TNAME) { sname = pinner.str; }; }; }; if (sname.len == 0) { return 8; }; @@ -390,10 +390,10 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return 8; }; - if (ft.kind == N_TPTR) { + if (ft.kind == nkind.N_TPTR) { let elem: *node = ft.lhs; if (elem != nil) { - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { if (streq(elem.str, "str")) { return 16; }; let ps: i32 = primsize(elem.str); if (ps > 0) { return ps; }; @@ -401,11 +401,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { }; return 8; }; - if (ft.kind == N_TSLICE) { return elemsizeof(ft); }; + if (ft.kind == nkind.N_TSLICE) { return elemsizeof(ft); }; // str-typed field: indexing yields one byte // (`n.s[i]` where .s is str — matches C cgen's // MOVZBQ for byte indexing). - if (ft.kind == N_TNAME) { + if (ft.kind == nkind.N_TNAME) { if (streq(ft.str, "str")) { return 1; }; }; return 8; @@ -415,36 +415,36 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { return 8; }; -// dotinnerstructptr — for an N_DOT whose lhs is a chain of dots -// or an N_IDENT, walk the chain and return the N_TNAME tnode of the +// dotinnerstructptr — for an nkind.N_DOT whose lhs is a chain of dots +// or an nkind.N_IDENT, walk the chain and return the nkind.N_TNAME tnode of the // struct that the chain dereferences to (i.e., for `r.sym` where -// .sym is *lsym, return N_TNAME("lsym")). Returns nil if the chain +// .sym is *lsym, return nkind.N_TNAME("lsym")). Returns nil if the chain // doesn't resolve to a *struct. // // Used by the chained-DOT cgen path so `r.sym.val` knows the outer // is a field of `lsym`. fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind != N_DOT) { return nil; }; + if (n.kind != nkind.N_DOT) { return nil; }; let base: *node = n.lhs; let fld: str = n.str; if (base == nil) { return nil; }; // Resolve base's struct tnode. let baset: *node = nil; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc == nil) { return nil; }; let tn: *node = lc.tnode; if (tn == nil) { return nil; }; - // base could be either struct-by-value (N_TNAME) or *struct (N_TPTR). - if (tn.kind == N_TNAME) { baset = tn; }; - if (tn.kind == N_TPTR) { baset = tn.lhs; }; - } else { if (base.kind == N_DOT) { + // base could be either struct-by-value (nkind.N_TNAME) or *struct (nkind.N_TPTR). + if (tn.kind == nkind.N_TNAME) { baset = tn; }; + if (tn.kind == nkind.N_TPTR) { baset = tn.lhs; }; + } else { if (base.kind == nkind.N_DOT) { baset = dotinnerstructptr(c, base); };}; if (baset == nil) { return nil; }; - if (baset.kind != N_TNAME) { return nil; }; + if (baset.kind != nkind.N_TNAME) { return nil; }; // Look up the struct, find the field, return the field's *struct. let si: *structinfo = structlookup(c, baset.str); @@ -454,10 +454,10 @@ fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (streq(fi.fname, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return nil; }; - if (ft.kind != N_TPTR) { return nil; }; + if (ft.kind != nkind.N_TPTR) { return nil; }; let inner: *node = ft.lhs; if (inner == nil) { return nil; }; - if (inner.kind != N_TNAME) { return nil; }; + if (inner.kind != nkind.N_TNAME) { return nil; }; return inner; }; fi = fi.finext; @@ -472,10 +472,10 @@ fn elemsizeof(t: *node) i32 = { if (t == nil) { return 1; }; let k: i32 = t.kind; let elem: *node = nil; - if (k == N_TPTR) { elem = t.lhs; }; - if (k == N_TSLICE) { elem = t.lhs; }; - if (k == N_TARRAY) { elem = t.lhs; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { elem = t.lhs; }; + if (k == nkind.N_TSLICE) { elem = t.lhs; }; + if (k == nkind.N_TARRAY) { elem = t.lhs; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return 1; }; // Indexing a primitive name (rare): element size = the prim. @@ -484,7 +484,7 @@ fn elemsizeof(t: *node) i32 = { return 1; }; if (elem == nil) { return 1; }; - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { let nm: str = elem.str; // str element is 16B (ptr+len). primsize returns 0 for it. if (streq(nm, "str")) { return 16; }; @@ -496,28 +496,28 @@ fn elemsizeof(t: *node) i32 = { // nodeisunsigned — best-effort cgen-time inference from the AST. We // don't have a typed AST yet, so we walk surface nodes: -// N_INTLIT — never marked unsigned (no tsuffix plumbing yet) -// N_IDENT — look up the local's declared type -// N_DOT — look up the field's declared type via struct reg -// N_BIN / N_UN — recurse: unsigned if either operand is unsigned -// N_CAST — use the cast target type +// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet) +// nkind.N_IDENT — look up the local's declared type +// nkind.N_DOT — look up the field's declared type via struct reg +// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned +// nkind.N_CAST — use the cast target type // // Conservative: if we can't tell, return false (signed). The cost of // being wrong here is byte-different asm vs C, not bad runtime. fn nodeisunsigned(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return typenodeisunsigned(lc.tnode); }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -526,13 +526,13 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { if (tn != nil) { lkind = tn.kind; }; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; - if (lkind == N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TNAME) { sname = tn.str; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -551,29 +551,29 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { return typenodeisunsigned(n.rhs); }; - if (k == N_BIN) { + if (k == nkind.N_CAST) { return typenodeisunsigned(n.rhs); }; + if (k == nkind.N_BIN) { if (nodeisunsigned(c, n.lhs)) { return true; }; return nodeisunsigned(c, n.rhs); }; - if (k == N_UN) { return nodeisunsigned(c, n.lhs); }; - // N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. + if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; + // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. // Walks the base local's declared type and pulls the element // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the // compare-codegen for `p[i] >= 48u8` falls back to signed JGE // instead of JAE, diverging from C w6c on byte indexing. - if (k == N_INDEX) { + if (k == nkind.N_INDEX) { let base: *node = n.lhs; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { let elem: *node = nil; - if (tn.kind == N_TPTR) { elem = tn.lhs; }; - if (tn.kind == N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == N_TSLICE) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; if (elem != nil) { return typenodeisunsigned(elem); }; @@ -601,7 +601,7 @@ fn structlookup(c: *cgen, name: str) *structinfo = { // recognised as a primitive — the caller falls back to other paths). // fldnumidx — parse a tuple field name like "0" / "1" / "12" into an // index, or -1 if not all-digits. Used by cgdot to dispatch -// `t.0` / `t.1` against an N_TTUPLE local without pulling in strconv. +// `t.0` / `t.1` against an nkind.N_TTUPLE local without pulling in strconv. fn fldnumidx(s: str) i32 = { if (s.len == 0) { return -1; }; let r: i32 = 0; @@ -646,14 +646,14 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { // return elem_size * 1 (treating missing length as 1); intercept // and compute the real count first. if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs == nil) { if (n.rhs != nil) { - if (n.rhs.kind == N_ARRLIT) { + if (n.rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -662,7 +662,7 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { let e: *node = n.rhs.list; for (e != nil) { let adv: bool = true; - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { e = nil; adv = false; @@ -685,11 +685,11 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let k: i32 = typn.kind; - if (k == N_TPTR) { return 8; }; - if (k == N_TFN) { return 8; }; - if (k == N_TCHAN) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TTUPLE) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TFN) { return 8; }; + if (k == nkind.N_TCHAN) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TTUPLE) { // Sum element sizes. Mirrors C cgen which uses raw type // sizes; padding to 8 happens inside slotsize for primitives, // so a `(i64, str)` resolves to 8 + 16 = 24 (matches the C @@ -702,13 +702,13 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return total; }; - if (k == N_TTAGGED){ + if (k == nkind.N_TTAGGED){ // Nullable `(*T | void)` collapses to a single 8B pointer. if (isnullabletype(typn)) { return 8; }; // Slot = 8 (tag) + max(variant payload sizes), rounded up // to an 8-byte multiple so the reg-passing ABI (size/8 // words) doesn't drop the last value register. Mirrors C - // cgen's resolve_type for N_TTAGGED. + // cgen's resolve_type for nkind.N_TTAGGED. let v: *node = typn.list; let maxsz: i32 = 0; for (v != nil) { @@ -719,7 +719,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { let pad: i32 = (maxsz + 7) & ~7; return 8 + pad; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = typn.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -733,16 +733,16 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TARRAY) { + if (k == nkind.N_TARRAY) { let lenn: *node = typn.rhs; let elemn: *node = typn.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let en: str = elemn.str; let ps: i32 = primsize(en); if (ps > 0) { esz = ps; }; @@ -750,12 +750,12 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return (esz: i64 * elen): i32; }; - if (k == N_TSTRUCT) { + if (k == nkind.N_TSTRUCT) { // Inline anonymous struct — sum of field sizes. let f: *node = typn.list; let total: i32 = 0; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { total += slotsize(c, f.lhs); }; f = f.next; @@ -772,7 +772,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let k: i32 = tnode.kind; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = tnode.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -781,15 +781,15 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TPTR) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TARRAY) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TARRAY) { // Same shape as slotsize's TARRAY branch. let lenn: *node = tnode.rhs; let elemn: *node = tnode.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = fieldsize(c, elemn); return (esz: i64 * elen): i32; @@ -807,7 +807,7 @@ fn registerstruct(c: *cgen, name: str, tstruct: *node) void = { let off: i32 = 0; let f: *node = tstruct.list; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { let sz: i32 = fieldsize(c, f.lhs); // Align to 8 for any field >= 4 bytes (matches our other // cgen choices). i8/u8/bool may sit on odd byte offsets; @@ -843,10 +843,10 @@ fn collectstructs(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TSTRUCT) { + if (body.kind == nkind.N_TSTRUCT) { registerstruct(c, d.str, body); }; }; @@ -859,7 +859,7 @@ fn collectstructs(c: *cgen, file: *node) void = { // alias chain registered at file load. fn isstrtyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return true; }; }; @@ -875,7 +875,7 @@ fn isstrtype(c: *cgen, t: *node) bool = { fn isslicetyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TSLICE) { return true; }; + if (t.kind == nkind.N_TSLICE) { return true; }; return false; }; @@ -888,26 +888,26 @@ fn isslicetype(c: *cgen, t: *node) bool = { fn istaggedtype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TTAGGED) { return true; }; + if (t.kind == nkind.N_TTAGGED) { return true; }; return false; }; -// isnullabletype — N_TTAGGED with exactly two children, one *T and +// isnullabletype — nkind.N_TTAGGED with exactly two children, one *T and // one `void`. Folds to a single 8-byte pointer slot per Hare's // `(*T | null)` semantics. Mirrors check.c's resolve_type detection. export fn isnullabletype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TTAGGED) { return false; }; + if (t.kind != nkind.N_TTAGGED) { return false; }; let a: *node = t.list; if (a == nil) { return false; }; let b: *node = a.next; if (b == nil) { return false; }; if (b.next != nil) { return false; }; - let aptr: bool = (a.kind == N_TPTR); - let bptr: bool = (b.kind == N_TPTR); - let avoid: bool = (a.kind == N_TNAME); + let aptr: bool = (a.kind == nkind.N_TPTR); + let bptr: bool = (b.kind == nkind.N_TPTR); + let avoid: bool = (a.kind == nkind.N_TNAME); if (avoid) { avoid = streq(a.str, "void"); }; - let bvoid: bool = (b.kind == N_TNAME); + let bvoid: bool = (b.kind == nkind.N_TNAME); if (bvoid) { bvoid = streq(b.str, "void"); }; if (aptr) { if (bvoid) { return true; }; }; if (avoid) { if (bptr) { return true; }; }; @@ -918,9 +918,9 @@ export fn isnullabletype(t: *node) bool = { // union. The void variant takes the other slot (0 or 1). export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; - if (t.kind != N_TTAGGED) { return 0; }; + if (t.kind != nkind.N_TTAGGED) { return 0; }; let a: *node = t.list; - if (a != nil) { if (a.kind == N_TPTR) { return 0; }; }; + if (a != nil) { if (a.kind == nkind.N_TPTR) { return 0; }; }; return 1; }; @@ -929,11 +929,11 @@ export fn nullableptrtag(t: *node) i32 = { // `return;` in a tagged-union-returning fn to the void variant's tag. fn voidvariantindex(tagged: *node) i32 = { if (tagged == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, "void")) { return idx; }; }; v = v.next; @@ -949,20 +949,20 @@ fn rhstargetname(c: *cgen, rhs: *node) str = { let nm: str; nm.ptr = nil; nm.len = 0; if (rhs == nil) { return nm; }; - if (rhs.kind == N_CAST) { + if (rhs.kind == nkind.N_CAST) { let t: *node = rhs.rhs; if (t != nil) { - if (t.kind == N_TNAME) { return t.str; }; + if (t.kind == nkind.N_TNAME) { return t.str; }; }; return nm; }; - if (rhs.kind == N_STRLIT) { return "str"; }; - if (rhs.kind == N_IDENT) { + if (rhs.kind == nkind.N_STRLIT) { return "str"; }; + if (rhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, rhs.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { return tn.str; }; + if (tn.kind == nkind.N_TNAME) { return tn.str; }; }; }; }; @@ -981,7 +981,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, wantname)) { return idx; }; }; v = v.next; @@ -994,7 +994,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let idx: i32 = 0; for (v != nil) { let visstr: bool = false; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (isstrtype(c, v)) { visstr = true; }; }; if (visstr == wantstr) { return idx; }; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index ced97fd2..dd42bb00 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -10,7 +10,7 @@ // `i32`, `str`, `*u8` etc. resolve. // 2. Walks the file's top-level decls (use/def/type/fn/let) and // installs Sym entries for each. -// 3. Recursively walks fn bodies; for every N_IDENT used as an +// 3. Recursively walks fn bodies; for every nkind.N_IDENT used as an // expression or as a type name, looks it up and counts the // resolved vs. unresolved. // 4. Returns a summary the caller (wwdump -r) prints; the test @@ -70,15 +70,15 @@ fn installdecl(c: *checker, d: *node) void = { if (d == nil) { return; }; let k: i32 = d.kind; let nm: str = d.str; - if (k == N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; - if (k == N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; - if (k == N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; - if (k == N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; - if (k == N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; + if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; + if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; + if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; + if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; + if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; }; -// resolvewalk — recursive AST walk that, for every N_IDENT and -// N_TNAME seen, looks up the name and bumps the resolved/unresolved +// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and +// nkind.N_TNAME seen, looks up the name and bumps the resolved/unresolved // counters. Local lets are installed in the current scope as soon as // their init/type expressions have been walked (forward use of a let // before its declaration would resolve to nothing — same semantics as @@ -91,17 +91,17 @@ fn resolvewalk(c: *checker, n: *node) void = { // Typed checks fire on the way down so the scrutinee/operand // is examined before the arm bodies install new bindings. - if (k == N_MATCH) { checkmatchexhaust(c, n); }; - if (k == N_TRYPROP) { checktryprop(c, n); }; - if (k == N_TYPETEST) { checkisas(c, n); }; - if (k == N_TYPEASSERT) { checkisas(c, n); }; - if (k == N_LET) { checkletassign(c, n); }; - if (k == N_RETURN) { checkretassign(c, n); }; + if (k == nkind.N_MATCH) { checkmatchexhaust(c, n); }; + if (k == nkind.N_TRYPROP) { checktryprop(c, n); }; + if (k == nkind.N_TYPETEST) { checkisas(c, n); }; + if (k == nkind.N_TYPEASSERT) { checkisas(c, n); }; + if (k == nkind.N_LET) { checkletassign(c, n); }; + if (k == nkind.N_RETURN) { checkretassign(c, n); }; // `use IDENT;` — name is a module label, not a free ident. - if (k == N_USE) { return; }; + if (k == nkind.N_USE) { return; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -116,7 +116,7 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -155,7 +155,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `match (e) { case let v: T => stmt; ... }` — the binding `v` // is declared by the case arm and visible inside its body. - if (k == N_MCASE) { + if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let nm: str = n.str; if (nm.len > 0) { @@ -165,19 +165,19 @@ fn resolvewalk(c: *checker, n: *node) void = { return; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { // Walk only the base; the .field name is a member, not a // free identifier. if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_FIELD) { + if (k == nkind.N_FIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_TFIELD) { + if (k == nkind.N_TFIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; @@ -201,7 +201,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `X` so subsequent statements can resolve it. Top-level lets // are installed in installdecl, so this duplicate install at // the file scope just no-ops (scopedefine returns nil on dup). - if (k == N_LET) { + if (k == nkind.N_LET) { let nm: str = n.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_VAR, nil, n); @@ -217,21 +217,21 @@ fn resolvewalk(c: *checker, n: *node) void = { // needs to enforce: tagged-union exhaustiveness, ? subset // propagation, and !-flag semantics. -// unwrapbang — strip an N_TBANG wrapper; leaves other nodes alone. +// unwrapbang — strip an nkind.N_TBANG wrapper; leaves other nodes alone. fn unwrapbang(n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind == N_TBANG) { return n.lhs; }; + if (n.kind == nkind.N_TBANG) { return n.lhs; }; return n; }; -// resolvealias — if n is an N_TNAME pointing at a typedecl, return +// resolvealias — if n is an nkind.N_TNAME pointing at a typedecl, return // the typedecl's body (possibly recursively). Pass-through for any -// other node. The chain stops once we hit a non-N_TNAME node or a +// other node. The chain stops once we hit a non-nkind.N_TNAME node or a // name we can't resolve. fn resolvealias(c: *checker, n: *node) *node = { let cur: *node = n; for (cur != nil) { - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let s: *sym = scopelookup(c.cur, cur.str); if (s == nil) { return cur; }; if (s.skind != skind.SK_TYPE) { return cur; }; @@ -254,10 +254,10 @@ fn typeeqast(a: *node, b: *node) bool = { if (bb == nil) { return false; }; if (aa.kind != bb.kind) { return false; }; let k: i32 = aa.kind; - if (k == N_TNAME) { return streq(aa.str, bb.str); }; - if (k == N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TNAME) { return streq(aa.str, bb.str); }; + if (k == nkind.N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; // Conservative: anything else (struct/fn/tagged/tuple/array) // fails the cheap check. Selfhost code doesn't currently rely // on equality at these shapes for the targeted checks. @@ -265,18 +265,18 @@ fn typeeqast(a: *node, b: *node) bool = { }; // varianterr — does this variant carry the `!` mark? Either -// the variant itself is N_TBANG or it's an alias whose typedecl +// the variant itself is nkind.N_TBANG or it's an alias whose typedecl // body is `!T`. Mirrors C check.c's iserror-after-NAMED rule. fn varianterr(c: *checker, v: *node) bool = { if (v == nil) { return false; }; - if (v.kind == N_TBANG) { return true; }; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TBANG) { return true; }; + if (v.kind == nkind.N_TNAME) { let s: *sym = scopelookup(c.cur, v.str); if (s != nil) { if (s.skind == skind.SK_TYPE) { if (s.decl != nil) { if (s.decl.lhs != nil) { - if (s.decl.lhs.kind == N_TBANG) { + if (s.decl.lhs.kind == nkind.N_TBANG) { return true; }; }; @@ -288,7 +288,7 @@ fn varianterr(c: *checker, v: *node) bool = { }; // taggedhaserr — true iff any variant of `n` (assumed -// N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over +// nkind.N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over // the legacy "first variant = success" rule. fn taggedhaserr(c: *checker, n: *node) bool = { let v: *node = n.list; @@ -312,26 +312,26 @@ fn iserrvariant(c: *checker, tagged: *node, v: *node) bool = { }; // scruttype — resolve the type expression for a match's -// scrutinee. Handles N_IDENT (look up local/param's declared -// type) and N_DOT (struct-field access). Returns nil if we +// scrutinee. Handles nkind.N_IDENT (look up local/param's declared +// type) and nkind.N_DOT (struct-field access). Returns nil if we // can't statically determine the type. Used by exhaustiveness. fn scruttype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; - // For N_LET / N_PARAM: declared type is decl.lhs. + // For nkind.N_LET / nkind.N_PARAM: declared type is decl.lhs. return s.decl.lhs; }; return nil; }; -// mktname — fabricate an N_TNAME node with str = `nm`. Used by +// mktname — fabricate an nkind.N_TNAME node with str = `nm`. Used by // exprtype to return primitive type nodes for literal // expressions. The arena keeps them around as long as the checker. fn mktname(c: *checker, nm: str) *node = { - let n: *node = newnode(c.a, N_TNAME, "", 0, 0); + let n: *node = newnode(c.a, nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -343,31 +343,31 @@ fn mktname(c: *checker, nm: str) *node = { fn exprtype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; let k: i32 = e.kind; - if (k == N_INTLIT) { return mktname(c, "untyped_int"); }; - if (k == N_FLOATLIT) { return mktname(c, "untyped_float"); }; - if (k == N_STRLIT) { return mktname(c, "str"); }; - if (k == N_RUNELIT) { return mktname(c, "rune"); }; - if (k == N_TRUE) { return mktname(c, "bool"); }; - if (k == N_FALSE) { return mktname(c, "bool"); }; - if (k == N_VOIDLIT) { return mktname(c, "void"); }; - if (k == N_NIL) { return mktname(c, "untyped_nil"); }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { return mktname(c, "untyped_int"); }; + if (k == nkind.N_FLOATLIT) { return mktname(c, "untyped_float"); }; + if (k == nkind.N_STRLIT) { return mktname(c, "str"); }; + if (k == nkind.N_RUNELIT) { return mktname(c, "rune"); }; + if (k == nkind.N_TRUE) { return mktname(c, "bool"); }; + if (k == nkind.N_FALSE) { return mktname(c, "bool"); }; + if (k == nkind.N_VOIDLIT) { return mktname(c, "void"); }; + if (k == nkind.N_NIL) { return mktname(c, "untyped_nil"); }; + if (k == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // `expr: T` — explicit cast; the type expr is e.rhs. return e.rhs; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -375,13 +375,13 @@ fn exprtype(c: *checker, e: *node) *node = { if (s.decl == nil) { return nil; }; return s.decl.lhs; // fn-decl's lhs is the return type }; - if (k == N_TRYPROP) { + if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union. let opt: *node = exprtype(c, e.lhs); let ou: *node = resolvealias(c, unwrapbang(opt)); if (ou == nil) { return nil; }; - if (ou.kind != N_TTAGGED) { return nil; }; + if (ou.kind != nkind.N_TTAGGED) { return nil; }; // Hare semantics: success = first non-error variant if // any !-flag is present; else first variant. if (taggedhaserr(c, ou)) { @@ -394,11 +394,11 @@ fn exprtype(c: *checker, e: *node) *node = { }; return ou.list; }; - if (k == N_TYPEASSERT) { + if (k == nkind.N_TYPEASSERT) { // `e as T` → T return e.rhs; }; - if (k == N_TYPETEST) { + if (k == nkind.N_TYPETEST) { // `e is T` → bool return mktname(c, "bool"); }; @@ -410,25 +410,25 @@ fn exprtype(c: *checker, e: *node) *node = { // through without needing real type inference. fn isuntypedint(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_int"); }; fn isuntypedfloat(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_float"); }; fn isuntypednil(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_nil"); }; fn isnumerictname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; let s: str = t.str; if (streq(s, "i8")) { return true; }; if (streq(s, "i16")) { return true; }; @@ -449,7 +449,7 @@ fn isnumerictname(t: *node) bool = { fn isstrtname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "str"); }; @@ -474,7 +474,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { if (isuntypedint(su)) { if (isnumerictname(du)) { return true; }; // (T | ...) tagged: only OK if some variant accepts untyped_int. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -487,7 +487,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Known non-numeric primitive: confidently wrong. - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -498,7 +498,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypedfloat(su)) { if (isnumerictname(du)) { return true; }; - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -508,17 +508,17 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypednil(su)) { // nil → ptr/slice/chan/fn/nullable - if (du.kind == N_TPTR) { return true; }; - if (du.kind == N_TSLICE) { return true; }; - if (du.kind == N_TCHAN) { return true; }; - if (du.kind == N_TFN) { return true; }; + if (du.kind == nkind.N_TPTR) { return true; }; + if (du.kind == nkind.N_TSLICE) { return true; }; + if (du.kind == nkind.N_TCHAN) { return true; }; + if (du.kind == nkind.N_TFN) { return true; }; // nullable `(*T | void)` — already accepted by typeeqast // when matched whole; nil is OK there too. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { - if (v.kind == N_TPTR) { return true; }; - if (v.kind == N_TSLICE){ return true; }; + if (v.kind == nkind.N_TPTR) { return true; }; + if (v.kind == nkind.N_TSLICE){ return true; }; v = v.next; }; }; @@ -526,7 +526,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Tagged-union variant inclusion: src is one of dst's variants. - if (du.kind == N_TTAGGED && su.kind != N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind != nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -541,13 +541,13 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { // (don't be confident) — common when forwarding a fallible // return through another fn with the same shape but possibly // a different surface spelling. - if (du.kind == N_TTAGGED && su.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind == nkind.N_TTAGGED) { *confident = false; return true; }; // Two known primitives with different names are confidently // incompatible. `i32 ↔ bool`, `str ↔ i32`, etc. - if (du.kind == N_TNAME && su.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME && su.kind == nkind.N_TNAME) { let known_d: bool = isnumerictname(du) || isstrtname(du); if (!known_d) { if (streq(du.str, "bool")) { known_d = true; }; }; if (!known_d) { if (streq(du.str, "void")) { known_d = true; }; }; @@ -587,7 +587,7 @@ fn casecovers(c: *checker, cs: *node, want: *node) bool = { fn errmatchvariant(c: *checker, n: *node, vname: *node) void = { os.write(2, "match: variant not handled".ptr, 26u64); if (vname != nil) { - if (vname.kind == N_TNAME) { + if (vname.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, vname.str.ptr, vname.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -612,7 +612,7 @@ fn casevariantin(tagged: *node, pat: *node) bool = { fn errbadcase(c: *checker, pat: *node) void = { os.write(2, "case: not a variant of scrutinee".ptr, 32u64); if (pat != nil) { - if (pat.kind == N_TNAME) { + if (pat.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, pat.str.ptr, pat.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -628,7 +628,7 @@ fn checkmatchexhaust(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Validity: every `case T` pattern (and multi-pattern alts) // must name a variant of u. Catches typos and dead arms that // the dispatch would never reach. @@ -684,12 +684,12 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = { os.write(2, where.ptr, where.len: u64); os.write(2, ": not assignable".ptr, 16u64); if (src != nil) { - if (src.kind == N_TNAME) { + if (src.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, src.str.ptr, src.str.len: u64); os.write(2, " → ".ptr, 5u64); if (dst != nil) { - if (dst.kind == N_TNAME) { + if (dst.kind == nkind.N_TNAME) { os.write(2, dst.str.ptr, dst.str.len: u64); }; }; @@ -741,7 +741,7 @@ fn checkisas(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { + if (u.kind != nkind.N_TTAGGED) { os.write(2, "is/as: operand is not a tagged union\n".ptr, 37u64); c.errs += 1; return; @@ -750,7 +750,7 @@ fn checkisas(c: *checker, n: *node) void = { if (want == nil) { return; }; if (!casevariantin(u, want)) { os.write(2, "is/as: not a variant of operand".ptr, 31u64); - if (want.kind == N_TNAME) { + if (want.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, want.str.ptr, want.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -764,26 +764,26 @@ fn checkisas(c: *checker, n: *node) void = { // // For `expr?`, the operand's error subset must be a subset of the // enclosing fn's return-type variants. Mirrors C check.c. Operand -// is N_TRYPROP; its lhs is the value-bearing expr; we look at the -// expr's *declared* type for N_IDENT/N_CALL cases. +// is nkind.N_TRYPROP; its lhs is the value-bearing expr; we look at the +// expr's *declared* type for nkind.N_IDENT/nkind.N_CALL cases. fn exprtypeoftry(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (e.kind == N_CALL) { - // callee return type lookup: callee is e.lhs (N_IDENT or - // N_DOT). We need the fn-decl's lhs (return-type AST). + if (e.kind == nkind.N_CALL) { + // callee return type lookup: callee is e.lhs (nkind.N_IDENT or + // nkind.N_DOT). We need the fn-decl's lhs (return-type AST). let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -799,7 +799,7 @@ fn checktryprop(c: *checker, n: *node) void = { let t: *node = exprtypeoftry(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(t)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Does the operand have any error variants? let haserr: bool = false; let v: *node = u.list; @@ -816,7 +816,7 @@ fn checktryprop(c: *checker, n: *node) void = { c.errs += 1; return; }; - if (r.kind != N_TTAGGED) { + if (r.kind != nkind.N_TTAGGED) { os.write(2, "?: enclosing fn return is not tagged\n".ptr, 37u64); c.errs += 1; return; @@ -846,7 +846,7 @@ fn checktryprop(c: *checker, n: *node) void = { fn installparams(c: *checker, params: *node) void = { let p: *node = params; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_PARAM, nil, p); @@ -888,7 +888,7 @@ export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { export fn checkfile(c: *checker, file: *node) void = { if (file == nil) { return; }; - if (file.kind != N_FILE) { return; }; + if (file.kind != nkind.N_FILE) { return; }; // Pass 1: install all top-level names. let d: *node = file.list; @@ -901,15 +901,15 @@ export fn checkfile(c: *checker, file: *node) void = { d = file.list; for (d != nil) { let k: i32 = d.kind; - if (k == N_FNDECL) { + if (k == nkind.N_FNDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type resolvefnbody(c, d); - } else { if (k == N_DEF) { + } else { if (k == nkind.N_DEF) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; - } else { if (k == N_TYPEDECL) { + } else { if (k == nkind.N_TYPEDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; - } else { if (k == N_LET) { + } else { if (k == nkind.N_LET) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; };};};}; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index e503b08c..238b4a14 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -1680,84 +1680,88 @@ use tok; // Mirror of cmd/wcc/ww.h Nkind. Values must stay numerically equal so // the AST diff probe in 990_selfhost works. -def N_NONE: i32 = 0; +// Mirror of the C `Nkind` enum in cmd/wcc/ww.h. Numeric values are +// explicit and must stay in sync — the 990_selfhost test diffs +// astprint against the C side byte-for-byte. Tail-appended entries +// (TYPETEST onward) preserve every prior N_* value. +type nkind = enum i32 { + N_NONE = 0, -def N_INTLIT: i32 = 1; -def N_FLOATLIT: i32 = 2; -def N_STRLIT: i32 = 3; -def N_RUNELIT: i32 = 4; -def N_TRUE: i32 = 5; -def N_FALSE: i32 = 6; -def N_NIL: i32 = 7; -def N_IDENT: i32 = 8; + N_INTLIT = 1, + N_FLOATLIT = 2, + N_STRLIT = 3, + N_RUNELIT = 4, + N_TRUE = 5, + N_FALSE = 6, + N_NIL = 7, + N_IDENT = 8, -def N_BIN: i32 = 9; -def N_UN: i32 = 10; -def N_CALL: i32 = 11; -def N_INDEX: i32 = 12; -def N_DOT: i32 = 13; -def N_CAST: i32 = 14; -def N_STRUCTLIT:i32 = 15; -def N_ARRLIT: i32 = 16; -def N_FIELD: i32 = 17; -def N_ASSIGN: i32 = 18; -def N_ALLOC: i32 = 19; -def N_FREE: i32 = 20; -def N_RECV: i32 = 21; -def N_SLICE: i32 = 22; -def N_SPREAD: i32 = 23; + N_BIN = 9, + N_UN = 10, + N_CALL = 11, + N_INDEX = 12, + N_DOT = 13, + N_CAST = 14, + N_STRUCTLIT = 15, + N_ARRLIT = 16, + N_FIELD = 17, + N_ASSIGN = 18, + N_ALLOC = 19, + N_FREE = 20, + N_RECV = 21, + N_SLICE = 22, + N_SPREAD = 23, -def N_BLOCK: i32 = 24; -def N_EXPRSTMT: i32 = 25; -def N_LET: i32 = 26; -def N_RETURN: i32 = 27; -def N_IF: i32 = 28; -def N_FOR: i32 = 29; -def N_FORRANGE: i32 = 30; -def N_DEFER: i32 = 31; -def N_BREAK: i32 = 32; -def N_CONTINUE: i32 = 33; -def N_SWITCH: i32 = 34; -def N_CASE: i32 = 35; + N_BLOCK = 24, + N_EXPRSTMT = 25, + N_LET = 26, + N_RETURN = 27, + N_IF = 28, + N_FOR = 29, + N_FORRANGE = 30, + N_DEFER = 31, + N_BREAK = 32, + N_CONTINUE = 33, + N_SWITCH = 34, + N_CASE = 35, -def N_FILE: i32 = 36; -def N_USE: i32 = 37; -def N_DEF: i32 = 38; -def N_TYPEDECL: i32 = 39; -def N_FNDECL: i32 = 40; -def N_PARAM: i32 = 41; + N_FILE = 36, + N_USE = 37, + N_DEF = 38, + N_TYPEDECL = 39, + N_FNDECL = 40, + N_PARAM = 41, -def N_TNAME: i32 = 42; -def N_TPTR: i32 = 43; -def N_TSLICE: i32 = 44; -def N_TARRAY: i32 = 45; -def N_TFN: i32 = 46; -def N_TSTRUCT: i32 = 47; -def N_TFIELD: i32 = 48; -def N_TCHAN: i32 = 49; + N_TNAME = 42, + N_TPTR = 43, + N_TSLICE = 44, + N_TARRAY = 45, + N_TFN = 46, + N_TSTRUCT = 47, + N_TFIELD = 48, + N_TCHAN = 49, -def N_ATTR: i32 = 50; -def N_TTUPLE: i32 = 51; -def N_TTAGGED: i32 = 52; -def N_TUPLE: i32 = 53; -def N_MATCH: i32 = 54; -def N_MCASE: i32 = 55; -def N_TRYPROP: i32 = 56; -def N_TRYUNW: i32 = 57; -def N_MLET: i32 = 58; -def N_MASSIGN: i32 = 59; + N_ATTR = 50, + N_TTUPLE = 51, + N_TTAGGED = 52, + N_TUPLE = 53, + N_MATCH = 54, + N_MCASE = 55, + N_TRYPROP = 56, + N_TRYUNW = 57, + N_MLET = 58, + N_MASSIGN = 59, -// Appended at the tail to keep all prior N_* values stable. The -// 990_selfhost test diffs astprint against the C side byte-for-byte. -def N_TYPETEST: i32 = 60; -def N_TYPEASSERT: i32 = 61; -def N_VOIDLIT: i32 = 62; -def N_TBANG: i32 = 63; -def N_YIELD: i32 = 64; -def N_TENUM: i32 = 65; -def N_TENUMMEMBER: i32 = 66; + N_TYPETEST = 60, + N_TYPEASSERT = 61, + N_VOIDLIT = 62, + N_TBANG = 63, + N_YIELD = 64, + N_TENUM = 65, + N_TENUMMEMBER = 66, -def N_LAST: i32 = 67; + N_LAST = 67, +}; // ---- Node ------------------------------------------------------------- @@ -1766,7 +1770,7 @@ type node = struct { file: str, line: i32, col: i32, - op: i32, // for N_BIN / N_UN / N_ASSIGN + op: i32, // for nkind.N_BIN / nkind.N_UN / nkind.N_ASSIGN str: str, uval: u64, fval: f64, @@ -1796,74 +1800,74 @@ export fn newnode(a: *arena, k: i32, file: str, line: i32, col: i32) *node = { // ---- printer ---------------------------------------------------------- fn nkname(k: i32) str = { - if (k == N_NONE) { return "none"; }; - if (k == N_INTLIT) { return "int"; }; - if (k == N_FLOATLIT) { return "float"; }; - if (k == N_STRLIT) { return "str"; }; - if (k == N_RUNELIT) { return "rune"; }; - if (k == N_TRUE) { return "true"; }; - if (k == N_FALSE) { return "false"; }; - if (k == N_NIL) { return "nil"; }; - if (k == N_IDENT) { return "id"; }; - if (k == N_BIN) { return "bin"; }; - if (k == N_UN) { return "un"; }; - if (k == N_CALL) { return "call"; }; - if (k == N_INDEX) { return "index"; }; - if (k == N_DOT) { return "dot"; }; - if (k == N_CAST) { return "cast"; }; - if (k == N_STRUCTLIT) { return "structlit"; }; - if (k == N_ARRLIT) { return "arrlit"; }; - if (k == N_FIELD) { return "field"; }; - if (k == N_ASSIGN) { return "assign"; }; - if (k == N_ALLOC) { return "alloc"; }; - if (k == N_FREE) { return "free"; }; - if (k == N_RECV) { return "recv"; }; - if (k == N_SLICE) { return "slice"; }; - if (k == N_SPREAD) { return "spread"; }; - if (k == N_BLOCK) { return "block"; }; - if (k == N_EXPRSTMT) { return "exprstmt"; }; - if (k == N_LET) { return "let"; }; - if (k == N_RETURN) { return "return"; }; - if (k == N_IF) { return "if"; }; - if (k == N_FOR) { return "for"; }; - if (k == N_FORRANGE) { return "forrange"; }; - if (k == N_DEFER) { return "defer"; }; - if (k == N_BREAK) { return "break"; }; - if (k == N_CONTINUE) { return "continue"; }; - if (k == N_SWITCH) { return "switch"; }; - if (k == N_CASE) { return "case"; }; - if (k == N_FILE) { return "file"; }; - if (k == N_USE) { return "use"; }; - if (k == N_DEF) { return "def"; }; - if (k == N_TYPEDECL) { return "typedecl"; }; - if (k == N_FNDECL) { return "fn"; }; - if (k == N_PARAM) { return "param"; }; - if (k == N_TNAME) { return "tname"; }; - if (k == N_TPTR) { return "tptr"; }; - if (k == N_TSLICE) { return "tslice"; }; - if (k == N_TARRAY) { return "tarray"; }; - if (k == N_TFN) { return "tfn"; }; - if (k == N_TSTRUCT) { return "tstruct"; }; - if (k == N_TFIELD) { return "tfield"; }; - if (k == N_TCHAN) { return "tchan"; }; - if (k == N_ATTR) { return "attr"; }; - if (k == N_TTUPLE) { return "ttuple"; }; - if (k == N_TTAGGED) { return "ttagged"; }; - if (k == N_TUPLE) { return "tuple"; }; - if (k == N_MATCH) { return "match"; }; - if (k == N_MCASE) { return "mcase"; }; - if (k == N_TRYPROP) { return "tryprop"; }; - if (k == N_TRYUNW) { return "tryunw"; }; - if (k == N_MLET) { return "mlet"; }; - if (k == N_MASSIGN) { return "massign"; }; - if (k == N_TYPETEST) { return "typetest"; }; - if (k == N_TYPEASSERT) { return "typeassert"; }; - if (k == N_VOIDLIT) { return "voidlit"; }; - if (k == N_TBANG) { return "tbang"; }; - if (k == N_YIELD) { return "yield"; }; - if (k == N_TENUM) { return "tenum"; }; - if (k == N_TENUMMEMBER) { return "tenummember"; }; - if (k == N_LAST) { return "last"; }; + if (k == nkind.N_NONE) { return "none"; }; + if (k == nkind.N_INTLIT) { return "int"; }; + if (k == nkind.N_FLOATLIT) { return "float"; }; + if (k == nkind.N_STRLIT) { return "str"; }; + if (k == nkind.N_RUNELIT) { return "rune"; }; + if (k == nkind.N_TRUE) { return "true"; }; + if (k == nkind.N_FALSE) { return "false"; }; + if (k == nkind.N_NIL) { return "nil"; }; + if (k == nkind.N_IDENT) { return "id"; }; + if (k == nkind.N_BIN) { return "bin"; }; + if (k == nkind.N_UN) { return "un"; }; + if (k == nkind.N_CALL) { return "call"; }; + if (k == nkind.N_INDEX) { return "index"; }; + if (k == nkind.N_DOT) { return "dot"; }; + if (k == nkind.N_CAST) { return "cast"; }; + if (k == nkind.N_STRUCTLIT) { return "structlit"; }; + if (k == nkind.N_ARRLIT) { return "arrlit"; }; + if (k == nkind.N_FIELD) { return "field"; }; + if (k == nkind.N_ASSIGN) { return "assign"; }; + if (k == nkind.N_ALLOC) { return "alloc"; }; + if (k == nkind.N_FREE) { return "free"; }; + if (k == nkind.N_RECV) { return "recv"; }; + if (k == nkind.N_SLICE) { return "slice"; }; + if (k == nkind.N_SPREAD) { return "spread"; }; + if (k == nkind.N_BLOCK) { return "block"; }; + if (k == nkind.N_EXPRSTMT) { return "exprstmt"; }; + if (k == nkind.N_LET) { return "let"; }; + if (k == nkind.N_RETURN) { return "return"; }; + if (k == nkind.N_IF) { return "if"; }; + if (k == nkind.N_FOR) { return "for"; }; + if (k == nkind.N_FORRANGE) { return "forrange"; }; + if (k == nkind.N_DEFER) { return "defer"; }; + if (k == nkind.N_BREAK) { return "break"; }; + if (k == nkind.N_CONTINUE) { return "continue"; }; + if (k == nkind.N_SWITCH) { return "switch"; }; + if (k == nkind.N_CASE) { return "case"; }; + if (k == nkind.N_FILE) { return "file"; }; + if (k == nkind.N_USE) { return "use"; }; + if (k == nkind.N_DEF) { return "def"; }; + if (k == nkind.N_TYPEDECL) { return "typedecl"; }; + if (k == nkind.N_FNDECL) { return "fn"; }; + if (k == nkind.N_PARAM) { return "param"; }; + if (k == nkind.N_TNAME) { return "tname"; }; + if (k == nkind.N_TPTR) { return "tptr"; }; + if (k == nkind.N_TSLICE) { return "tslice"; }; + if (k == nkind.N_TARRAY) { return "tarray"; }; + if (k == nkind.N_TFN) { return "tfn"; }; + if (k == nkind.N_TSTRUCT) { return "tstruct"; }; + if (k == nkind.N_TFIELD) { return "tfield"; }; + if (k == nkind.N_TCHAN) { return "tchan"; }; + if (k == nkind.N_ATTR) { return "attr"; }; + if (k == nkind.N_TTUPLE) { return "ttuple"; }; + if (k == nkind.N_TTAGGED) { return "ttagged"; }; + if (k == nkind.N_TUPLE) { return "tuple"; }; + if (k == nkind.N_MATCH) { return "match"; }; + if (k == nkind.N_MCASE) { return "mcase"; }; + if (k == nkind.N_TRYPROP) { return "tryprop"; }; + if (k == nkind.N_TRYUNW) { return "tryunw"; }; + if (k == nkind.N_MLET) { return "mlet"; }; + if (k == nkind.N_MASSIGN) { return "massign"; }; + if (k == nkind.N_TYPETEST) { return "typetest"; }; + if (k == nkind.N_TYPEASSERT) { return "typeassert"; }; + if (k == nkind.N_VOIDLIT) { return "voidlit"; }; + if (k == nkind.N_TBANG) { return "tbang"; }; + if (k == nkind.N_YIELD) { return "yield"; }; + if (k == nkind.N_TENUM) { return "tenum"; }; + if (k == nkind.N_TENUMMEMBER) { return "tenummember"; }; + if (k == nkind.N_LAST) { return "last"; }; return "?"; }; @@ -1926,31 +1930,31 @@ fn pr(fd: i32, n: *node, d: i32) void = { let nm: str = nkname(n.kind); os.write(fd, nm.ptr, nm.len: u64); - if (n.kind == N_INTLIT) { + if (n.kind == nkind.N_INTLIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); - } else { if (n.kind == N_RUNELIT) { + } else { if (n.kind == nkind.N_RUNELIT) { putc1(fd, 32u8); let buf: [32]u8; let m: i32 = strconv.u64tos(buf[0:32], n.uval); os.write(fd, buf.ptr, m: u64); } else { if ( - n.kind == N_STRLIT || - n.kind == N_IDENT || - n.kind == N_USE || - n.kind == N_DOT || - n.kind == N_DEF || - n.kind == N_TYPEDECL || - n.kind == N_FNDECL || - n.kind == N_PARAM || - n.kind == N_LET || - n.kind == N_TNAME || - n.kind == N_TFIELD || - n.kind == N_TENUMMEMBER || - n.kind == N_FIELD || - n.kind == N_ATTR + n.kind == nkind.N_STRLIT || + n.kind == nkind.N_IDENT || + n.kind == nkind.N_USE || + n.kind == nkind.N_DOT || + n.kind == nkind.N_DEF || + n.kind == nkind.N_TYPEDECL || + n.kind == nkind.N_FNDECL || + n.kind == nkind.N_PARAM || + n.kind == nkind.N_LET || + n.kind == nkind.N_TNAME || + n.kind == nkind.N_TFIELD || + n.kind == nkind.N_TENUMMEMBER || + n.kind == nkind.N_FIELD || + n.kind == nkind.N_ATTR ) { // Match C ast.c: print the str field whenever it's non-nil, // even if its length is zero (e.g. an empty STRLIT prints @@ -1961,22 +1965,22 @@ fn pr(fd: i32, n: *node, d: i32) void = { putq(fd, s); }; } else { if ( - n.kind == N_BIN || - n.kind == N_UN || - n.kind == N_ASSIGN + n.kind == nkind.N_BIN || + n.kind == nkind.N_UN || + n.kind == nkind.N_ASSIGN ) { putc1(fd, 32u8); let on: str = tokname(n.op); os.write(fd, on.ptr, on.len: u64); };};};}; - if (n.kind == N_FNDECL) { + if (n.kind == nkind.N_FNDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_DEF) { + if (n.kind == nkind.N_DEF) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; - if (n.kind == N_TYPEDECL) { + if (n.kind == nkind.N_TYPEDECL) { if (n.exported != 0) { os.write(fd, " export".ptr, 7u64); }; }; putc1(fd, 10u8); // '\n' @@ -2041,56 +2045,56 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, N_INTLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, N_STRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); n.str = p.curtext; advance(p); return n; }; if (p.curkind == tkind.TK_RUNE) { - let n: *node = newnode(p.a, N_RUNELIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RUNELIT, pf, pl, pc); n.uval = p.curuval; advance(p); return n; }; if (p.curkind == tkind.TK_TRUE) { advance(p); - return newnode(p.a, N_TRUE, pf, pl, pc); + return newnode(p.a, nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, N_FALSE, pf, pl, pc); + return newnode(p.a, nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, N_NIL, pf, pl, pc); + return newnode(p.a, nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, N_VOIDLIT, pf, pl, pc); + return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { - // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT + // Bare `_` — valid only as a discard lvalue. Emit an nkind.N_IDENT // with empty str; the checker rejects it outside lvalue // positions. advance(p); - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); let empty: str; n.str = empty; return n; }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). - // The repeat marker is an N_FIELD node with str = "..." + // The repeat marker is an nkind.N_FIELD node with str = "..." // appended to the element list so cgen can detect it. advance(p); - let n: *node = newnode(p.a, N_ARRLIT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -2099,7 +2103,7 @@ fn parseprimary(p: *parser) *node = { if (head == nil) { head = e; tail = e; } else { tail.next = e; tail = e; }; if (accepttok(p, tkind.TK_ELLIPSIS)) { - let rep: *node = newnode(p.a, N_FIELD, + let rep: *node = newnode(p.a, nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -2117,7 +2121,7 @@ fn parseprimary(p: *parser) *node = { let e: *node = parseexpr(p); // Tuple literal: (a, b, ...) if (accepttok(p, tkind.TK_COMMA)) { - let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -2134,7 +2138,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_IDENT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -2145,7 +2149,7 @@ fn parseprimary(p: *parser) *node = { // own paren/cond, so this is safe. if (p.curkind == tkind.TK_LBRACE) { advance(p); - let s: *node = newnode(p.a, N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(p.a, nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -2165,7 +2169,7 @@ fn parseprimary(p: *parser) *node = { expectident(p, &id); expecttok(p, tkind.TK_ASSIGN, "expected '=' in struct lit field"); let v: *node = parseexpr(p); - let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -2182,7 +2186,7 @@ fn parseprimary(p: *parser) *node = { // match (e) { case let v: T => stmt; case T => stmt; case => stmt; }; advance(p); expecttok(p, tkind.TK_LPAREN, "expected '(' after match"); - let m: *node = newnode(p.a, N_MATCH, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MATCH, pf, pl, pc); m.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after match scrutinee"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open match body"); @@ -2193,7 +2197,7 @@ fn parseprimary(p: *parser) *node = { let cl: i32 = p.curline; let cc: i32 = p.curcol; advance(p); // past `case` - let mc: *node = newnode(p.a, N_MCASE, cf, cl, cc); + let mc: *node = newnode(p.a, nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -2215,7 +2219,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, N_NONE, pf, pl, pc); + return newnode(p.a, nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: i32, headout: **node) void = { @@ -2241,12 +2245,12 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_LPAREN) { advance(p); - let n: *node = newnode(p.a, N_CALL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CALL, pf, pl, pc); n.lhs = cur; // size(T)/align(T): the single arg is a type expression, // not a regular expression. Special-case at the parser. let is_typeop: i32 = 0; - if (cur.kind == N_IDENT) { + if (cur.kind == nkind.N_IDENT) { if (streqlocal(cur.str, "size")) { is_typeop = 1; }; if (streqlocal(cur.str, "align")) { is_typeop = 1; }; }; @@ -2266,7 +2270,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `[ : hi ]` — slice with implicit lo = 0. if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -2283,7 +2287,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { p.nocast = prev; if (p.curkind == tkind.TK_COLON) { advance(p); - let n: *node = newnode(p.a, N_SLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -2293,7 +2297,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, N_INDEX, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -2302,7 +2306,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, N_DOT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); n.lhs = cur; // Hare-style tuple field access: `t.0`, `t.1`. The // numeric literal becomes the field name string so the @@ -2323,7 +2327,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, N_CAST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2335,7 +2339,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // Same precedence level as the `:` cast. if (p.curkind == tkind.TK_AS) { advance(p); - let n: *node = newnode(p.a, N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2343,7 +2347,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, N_TYPETEST, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -2353,14 +2357,14 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { // `e!` — abort on error variant. if (p.curkind == tkind.TK_QUESTION) { advance(p); - let n: *node = newnode(p.a, N_TRYPROP, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYPROP, pf, pl, pc); n.lhs = cur; cur = n; continue; }; if (p.curkind == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_TRYUNW, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -2377,37 +2381,37 @@ fn parseunary(p: *parser) *node = { let k: i32 = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_MINUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_PLUS) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_PLUS; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_NOT) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_NOT; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_TILDE) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_TILDE; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_STAR; n.lhs = parseunary(p); return n; }; if (k == tkind.TK_AMP) { advance(p); - let n: *node = newnode(p.a, N_UN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -2431,7 +2435,7 @@ fn parsebin(p: *parser, lhs: *node, minp: i32) *node = { if (np <= pr) { break; }; rhs = parsebin(p, rhs, np); }; - let n: *node = newnode(p.a, N_BIN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -2446,7 +2450,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: i32 = p.curkind; advance(p); - let n: *node = newnode(p.a, N_ASSIGN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); n.op = op; n.lhs = e; n.rhs = parseexpr(p); // right-associative @@ -2477,14 +2481,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(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -2507,7 +2511,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -2516,16 +2520,16 @@ fn parseletlocal(p: *parser) *node = { }; // Comma-multi-let: `let n, s = call();` (ww extension over Hare). // Collects (name, type) pairs, then '=' rhs. Each binding gets - // its own N_LET; the wrapping N_MLET carries the rhs. + // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MLET, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); let head: *node = n; let tail: *node = 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(p.a, N_LET, lpf, lpl, lpc); + let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -2557,7 +2561,7 @@ fn parseblock(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; expecttok(p, tkind.TK_LBRACE, "expected '{' to open block"); - let blk: *node = newnode(p.a, N_BLOCK, pf, pl, pc); + let blk: *node = newnode(p.a, nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -2579,7 +2583,7 @@ fn parseif(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `if` expecttok(p, tkind.TK_LPAREN, "expected '(' after if"); - let n: *node = newnode(p.a, N_IF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -2599,11 +2603,11 @@ fn parsefor(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `for` expecttok(p, tkind.TK_LPAREN, "expected '(' after for"); - let n: *node = newnode(p.a, N_FOR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); // Three forms (matching C parser): // for (cond) — only cond // for (init; cond; post) — full - // for (true) — infinite (cond is N_TRUE) + // for (true) — infinite (cond is nkind.N_TRUE) // Distinguish by counting ';'. Look at first chunk: if it's a // `let` stmt that's the init. Otherwise, parse expr; if next is // ';' it was cond. If we see two ';' total after init, post is @@ -2663,13 +2667,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, N_RETURN, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); if (p.curkind != tkind.TK_SEMI) { let first: *node = 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(p.a, N_TUPLE, pf, pl, pc); + let t: *node = newnode(p.a, nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -2687,14 +2691,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, N_DEFER, pf, pl, pc); + let n: *node = newnode(p.a, 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(p.a, N_YIELD, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -2702,12 +2706,12 @@ fn parsestmt(p: *parser) *node = { if (p.curkind == tkind.TK_BREAK) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after break"); - return newnode(p.a, N_BREAK, pf, pl, pc); + return newnode(p.a, nkind.N_BREAK, pf, pl, pc); }; if (p.curkind == tkind.TK_CONTINUE) { advance(p); expecttok(p, tkind.TK_SEMI, "expected ';' after continue"); - return newnode(p.a, N_CONTINUE, pf, pl, pc); + return newnode(p.a, nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -2717,7 +2721,7 @@ fn parsestmt(p: *parser) *node = { // consume — parseexpr would absorb it. let e: *node = parseexpr(p); if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, N_MASSIGN, pf, pl, pc); + let m: *node = newnode(p.a, nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -2732,7 +2736,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; @@ -2751,7 +2755,7 @@ fn parseuse(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `use` - let n: *node = newnode(p.a, N_USE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_USE, pf, pl, pc); let id: str; expectident(p, &id); n.str = id; @@ -2764,7 +2768,7 @@ fn parsedef(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `def` - let n: *node = newnode(p.a, N_DEF, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_DEF, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -2787,7 +2791,7 @@ fn parselet(p: *parser, exported: i32) *node = { let is_const: i32 = 0; if (p.curkind == tkind.TK_CONST) { is_const = 1; }; advance(p); - let n: *node = newnode(p.a, N_LET, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); n.module = p.l.module; let id: str; expectbindname(p, &id); @@ -2812,7 +2816,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, N_ATTR, pf, pl, pc); + let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -2838,7 +2842,7 @@ fn parseparams(p: *parser) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - let n: *node = newnode(p.a, N_PARAM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_PARAM, pf, pl, pc); // Param form: (IDENT|'_') ':' type. Anonymous-type-only params // (used in fn type expressions) aren't yet wired here. let id: str; @@ -2859,7 +2863,7 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `fn` - let n: *node = newnode(p.a, N_FNDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_FNDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -2889,7 +2893,7 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); // past `type` - let n: *node = newnode(p.a, N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TYPEDECL, pf, pl, pc); n.module = p.l.module; let id: str; expectident(p, &id); @@ -3037,14 +3041,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_NOT) { // `!T` — Hare error-flagged type wrapper. advance(p); - let n: *node = newnode(p.a, N_TBANG, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, N_TPTR, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -3053,13 +3057,13 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, N_TSLICE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil - // as the sentinel; the cgen path for 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. if (p.curkind == tkind.TK_UNDER) { advance(p); @@ -3074,7 +3078,7 @@ 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(p.a, N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -3082,7 +3086,7 @@ fn parsetype(p: *parser) *node = { let fpf: str = p.curfile; let fpl: i32 = p.curline; let fpc: i32 = p.curcol; - let f: *node = newnode(p.a, N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(p.a, nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -3100,10 +3104,10 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_ENUM) { // `enum [storage] { NAME [= expr], ... }` // Storage defaults to i32 (lhs == nil). Each member is an - // 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). advance(p); - let n: *node = newnode(p.a, N_TENUM, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -3115,7 +3119,7 @@ fn parsetype(p: *parser) *node = { let mpf: str = p.curfile; let mpl: i32 = p.curline; let mpc: i32 = p.curcol; - let m: *node = newnode(p.a, N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(p.a, nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -3132,16 +3136,16 @@ fn parsetype(p: *parser) *node = { }; if (p.curkind == tkind.TK_VOID) { - // `void` keyword in type-expr context — emit as N_TNAME so + // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); n.str = "void"; advance(p); return n; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, N_TNAME, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -3161,7 +3165,7 @@ fn parsetype(p: *parser) *node = { advance(p); let first: *node = parsetype(p); if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, N_TTAGGED, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -3178,7 +3182,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, N_TTUPLE, pf, pl, pc); + let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -3196,7 +3200,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(p.a, N_TFN, pf, pl, pc); + let n: *node = newnode(p.a, 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. @@ -3208,7 +3212,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, N_TNAME, pf, pl, pc); + return newnode(p.a, nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -3259,7 +3263,7 @@ fn isassignop(k: i32) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; @@ -3795,7 +3799,7 @@ export fn scopedefine(s: *scope, name: str, k: i32, t: *tinfo, decl: *node) *sym // `i32`, `str`, `*u8` etc. resolve. // 2. Walks the file's top-level decls (use/def/type/fn/let) and // installs Sym entries for each. -// 3. Recursively walks fn bodies; for every N_IDENT used as an +// 3. Recursively walks fn bodies; for every nkind.N_IDENT used as an // expression or as a type name, looks it up and counts the // resolved vs. unresolved. // 4. Returns a summary the caller (wwdump -r) prints; the test @@ -3855,15 +3859,15 @@ fn installdecl(c: *checker, d: *node) void = { if (d == nil) { return; }; let k: i32 = d.kind; let nm: str = d.str; - if (k == N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; - if (k == N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; - if (k == N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; - if (k == N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; - if (k == N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; + if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; }; + if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; }; + if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; }; + if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; }; + if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; }; }; -// resolvewalk — recursive AST walk that, for every N_IDENT and -// N_TNAME seen, looks up the name and bumps the resolved/unresolved +// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and +// nkind.N_TNAME seen, looks up the name and bumps the resolved/unresolved // counters. Local lets are installed in the current scope as soon as // their init/type expressions have been walked (forward use of a let // before its declaration would resolve to nothing — same semantics as @@ -3876,17 +3880,17 @@ fn resolvewalk(c: *checker, n: *node) void = { // Typed checks fire on the way down so the scrutinee/operand // is examined before the arm bodies install new bindings. - if (k == N_MATCH) { checkmatchexhaust(c, n); }; - if (k == N_TRYPROP) { checktryprop(c, n); }; - if (k == N_TYPETEST) { checkisas(c, n); }; - if (k == N_TYPEASSERT) { checkisas(c, n); }; - if (k == N_LET) { checkletassign(c, n); }; - if (k == N_RETURN) { checkretassign(c, n); }; + if (k == nkind.N_MATCH) { checkmatchexhaust(c, n); }; + if (k == nkind.N_TRYPROP) { checktryprop(c, n); }; + if (k == nkind.N_TYPETEST) { checkisas(c, n); }; + if (k == nkind.N_TYPEASSERT) { checkisas(c, n); }; + if (k == nkind.N_LET) { checkletassign(c, n); }; + if (k == nkind.N_RETURN) { checkretassign(c, n); }; // `use IDENT;` — name is a module label, not a free ident. - if (k == N_USE) { return; }; + if (k == nkind.N_USE) { return; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -3901,7 +3905,7 @@ fn resolvewalk(c: *checker, n: *node) void = { }; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = n.str; if (nm.len > 0) { let s: *sym = scopelookup(c.cur, nm); @@ -3940,7 +3944,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `match (e) { case let v: T => stmt; ... }` — the binding `v` // is declared by the case arm and visible inside its body. - if (k == N_MCASE) { + if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let nm: str = n.str; if (nm.len > 0) { @@ -3950,19 +3954,19 @@ fn resolvewalk(c: *checker, n: *node) void = { return; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { // Walk only the base; the .field name is a member, not a // free identifier. if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_FIELD) { + if (k == nkind.N_FIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; - if (k == N_TFIELD) { + if (k == nkind.N_TFIELD) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; return; }; @@ -3986,7 +3990,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // `X` so subsequent statements can resolve it. Top-level lets // are installed in installdecl, so this duplicate install at // the file scope just no-ops (scopedefine returns nil on dup). - if (k == N_LET) { + if (k == nkind.N_LET) { let nm: str = n.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_VAR, nil, n); @@ -4002,21 +4006,21 @@ fn resolvewalk(c: *checker, n: *node) void = { // needs to enforce: tagged-union exhaustiveness, ? subset // propagation, and !-flag semantics. -// unwrapbang — strip an N_TBANG wrapper; leaves other nodes alone. +// unwrapbang — strip an nkind.N_TBANG wrapper; leaves other nodes alone. fn unwrapbang(n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind == N_TBANG) { return n.lhs; }; + if (n.kind == nkind.N_TBANG) { return n.lhs; }; return n; }; -// resolvealias — if n is an N_TNAME pointing at a typedecl, return +// resolvealias — if n is an nkind.N_TNAME pointing at a typedecl, return // the typedecl's body (possibly recursively). Pass-through for any -// other node. The chain stops once we hit a non-N_TNAME node or a +// other node. The chain stops once we hit a non-nkind.N_TNAME node or a // name we can't resolve. fn resolvealias(c: *checker, n: *node) *node = { let cur: *node = n; for (cur != nil) { - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let s: *sym = scopelookup(c.cur, cur.str); if (s == nil) { return cur; }; if (s.skind != skind.SK_TYPE) { return cur; }; @@ -4039,10 +4043,10 @@ fn typeeqast(a: *node, b: *node) bool = { if (bb == nil) { return false; }; if (aa.kind != bb.kind) { return false; }; let k: i32 = aa.kind; - if (k == N_TNAME) { return streq(aa.str, bb.str); }; - if (k == N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; - if (k == N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TNAME) { return streq(aa.str, bb.str); }; + if (k == nkind.N_TPTR) { return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); }; + if (k == nkind.N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); }; // Conservative: anything else (struct/fn/tagged/tuple/array) // fails the cheap check. Selfhost code doesn't currently rely // on equality at these shapes for the targeted checks. @@ -4050,18 +4054,18 @@ fn typeeqast(a: *node, b: *node) bool = { }; // varianterr — does this variant carry the `!` mark? Either -// the variant itself is N_TBANG or it's an alias whose typedecl +// the variant itself is nkind.N_TBANG or it's an alias whose typedecl // body is `!T`. Mirrors C check.c's iserror-after-NAMED rule. fn varianterr(c: *checker, v: *node) bool = { if (v == nil) { return false; }; - if (v.kind == N_TBANG) { return true; }; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TBANG) { return true; }; + if (v.kind == nkind.N_TNAME) { let s: *sym = scopelookup(c.cur, v.str); if (s != nil) { if (s.skind == skind.SK_TYPE) { if (s.decl != nil) { if (s.decl.lhs != nil) { - if (s.decl.lhs.kind == N_TBANG) { + if (s.decl.lhs.kind == nkind.N_TBANG) { return true; }; }; @@ -4073,7 +4077,7 @@ fn varianterr(c: *checker, v: *node) bool = { }; // taggedhaserr — true iff any variant of `n` (assumed -// N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over +// nkind.N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over // the legacy "first variant = success" rule. fn taggedhaserr(c: *checker, n: *node) bool = { let v: *node = n.list; @@ -4097,26 +4101,26 @@ fn iserrvariant(c: *checker, tagged: *node, v: *node) bool = { }; // scruttype — resolve the type expression for a match's -// scrutinee. Handles N_IDENT (look up local/param's declared -// type) and N_DOT (struct-field access). Returns nil if we +// scrutinee. Handles nkind.N_IDENT (look up local/param's declared +// type) and nkind.N_DOT (struct-field access). Returns nil if we // can't statically determine the type. Used by exhaustiveness. fn scruttype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; - // For N_LET / N_PARAM: declared type is decl.lhs. + // For nkind.N_LET / nkind.N_PARAM: declared type is decl.lhs. return s.decl.lhs; }; return nil; }; -// mktname — fabricate an N_TNAME node with str = `nm`. Used by +// mktname — fabricate an nkind.N_TNAME node with str = `nm`. Used by // exprtype to return primitive type nodes for literal // expressions. The arena keeps them around as long as the checker. fn mktname(c: *checker, nm: str) *node = { - let n: *node = newnode(c.a, N_TNAME, "", 0, 0); + let n: *node = newnode(c.a, nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -4128,31 +4132,31 @@ fn mktname(c: *checker, nm: str) *node = { fn exprtype(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; let k: i32 = e.kind; - if (k == N_INTLIT) { return mktname(c, "untyped_int"); }; - if (k == N_FLOATLIT) { return mktname(c, "untyped_float"); }; - if (k == N_STRLIT) { return mktname(c, "str"); }; - if (k == N_RUNELIT) { return mktname(c, "rune"); }; - if (k == N_TRUE) { return mktname(c, "bool"); }; - if (k == N_FALSE) { return mktname(c, "bool"); }; - if (k == N_VOIDLIT) { return mktname(c, "void"); }; - if (k == N_NIL) { return mktname(c, "untyped_nil"); }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { return mktname(c, "untyped_int"); }; + if (k == nkind.N_FLOATLIT) { return mktname(c, "untyped_float"); }; + if (k == nkind.N_STRLIT) { return mktname(c, "str"); }; + if (k == nkind.N_RUNELIT) { return mktname(c, "rune"); }; + if (k == nkind.N_TRUE) { return mktname(c, "bool"); }; + if (k == nkind.N_FALSE) { return mktname(c, "bool"); }; + if (k == nkind.N_VOIDLIT) { return mktname(c, "void"); }; + if (k == nkind.N_NIL) { return mktname(c, "untyped_nil"); }; + if (k == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // `expr: T` — explicit cast; the type expr is e.rhs. return e.rhs; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -4160,13 +4164,13 @@ fn exprtype(c: *checker, e: *node) *node = { if (s.decl == nil) { return nil; }; return s.decl.lhs; // fn-decl's lhs is the return type }; - if (k == N_TRYPROP) { + if (k == nkind.N_TRYPROP) { // success unwrap: the success-variant type of operand's // tagged union. let opt: *node = exprtype(c, e.lhs); let ou: *node = resolvealias(c, unwrapbang(opt)); if (ou == nil) { return nil; }; - if (ou.kind != N_TTAGGED) { return nil; }; + if (ou.kind != nkind.N_TTAGGED) { return nil; }; // Hare semantics: success = first non-error variant if // any !-flag is present; else first variant. if (taggedhaserr(c, ou)) { @@ -4179,11 +4183,11 @@ fn exprtype(c: *checker, e: *node) *node = { }; return ou.list; }; - if (k == N_TYPEASSERT) { + if (k == nkind.N_TYPEASSERT) { // `e as T` → T return e.rhs; }; - if (k == N_TYPETEST) { + if (k == nkind.N_TYPETEST) { // `e is T` → bool return mktname(c, "bool"); }; @@ -4195,25 +4199,25 @@ fn exprtype(c: *checker, e: *node) *node = { // through without needing real type inference. fn isuntypedint(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_int"); }; fn isuntypedfloat(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_float"); }; fn isuntypednil(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "untyped_nil"); }; fn isnumerictname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; let s: str = t.str; if (streq(s, "i8")) { return true; }; if (streq(s, "i16")) { return true; }; @@ -4234,7 +4238,7 @@ fn isnumerictname(t: *node) bool = { fn isstrtname(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TNAME) { return false; }; + if (t.kind != nkind.N_TNAME) { return false; }; return streq(t.str, "str"); }; @@ -4259,7 +4263,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { if (isuntypedint(su)) { if (isnumerictname(du)) { return true; }; // (T | ...) tagged: only OK if some variant accepts untyped_int. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -4272,7 +4276,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Known non-numeric primitive: confidently wrong. - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -4283,7 +4287,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypedfloat(su)) { if (isnumerictname(du)) { return true; }; - if (du.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME) { if (streq(du.str, "bool")) { return false; }; if (streq(du.str, "void")) { return false; }; if (streq(du.str, "str")) { return false; }; @@ -4293,17 +4297,17 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { }; if (isuntypednil(su)) { // nil → ptr/slice/chan/fn/nullable - if (du.kind == N_TPTR) { return true; }; - if (du.kind == N_TSLICE) { return true; }; - if (du.kind == N_TCHAN) { return true; }; - if (du.kind == N_TFN) { return true; }; + if (du.kind == nkind.N_TPTR) { return true; }; + if (du.kind == nkind.N_TSLICE) { return true; }; + if (du.kind == nkind.N_TCHAN) { return true; }; + if (du.kind == nkind.N_TFN) { return true; }; // nullable `(*T | void)` — already accepted by typeeqast // when matched whole; nil is OK there too. - if (du.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { - if (v.kind == N_TPTR) { return true; }; - if (v.kind == N_TSLICE){ return true; }; + if (v.kind == nkind.N_TPTR) { return true; }; + if (v.kind == nkind.N_TSLICE){ return true; }; v = v.next; }; }; @@ -4311,7 +4315,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { return true; }; // Tagged-union variant inclusion: src is one of dst's variants. - if (du.kind == N_TTAGGED && su.kind != N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind != nkind.N_TTAGGED) { let v: *node = du.list; for (v != nil) { let vu: *node = resolvealias(c, unwrapbang(v)); @@ -4326,13 +4330,13 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = { // (don't be confident) — common when forwarding a fallible // return through another fn with the same shape but possibly // a different surface spelling. - if (du.kind == N_TTAGGED && su.kind == N_TTAGGED) { + if (du.kind == nkind.N_TTAGGED && su.kind == nkind.N_TTAGGED) { *confident = false; return true; }; // Two known primitives with different names are confidently // incompatible. `i32 ↔ bool`, `str ↔ i32`, etc. - if (du.kind == N_TNAME && su.kind == N_TNAME) { + if (du.kind == nkind.N_TNAME && su.kind == nkind.N_TNAME) { let known_d: bool = isnumerictname(du) || isstrtname(du); if (!known_d) { if (streq(du.str, "bool")) { known_d = true; }; }; if (!known_d) { if (streq(du.str, "void")) { known_d = true; }; }; @@ -4372,7 +4376,7 @@ fn casecovers(c: *checker, cs: *node, want: *node) bool = { fn errmatchvariant(c: *checker, n: *node, vname: *node) void = { os.write(2, "match: variant not handled".ptr, 26u64); if (vname != nil) { - if (vname.kind == N_TNAME) { + if (vname.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, vname.str.ptr, vname.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4397,7 +4401,7 @@ fn casevariantin(tagged: *node, pat: *node) bool = { fn errbadcase(c: *checker, pat: *node) void = { os.write(2, "case: not a variant of scrutinee".ptr, 32u64); if (pat != nil) { - if (pat.kind == N_TNAME) { + if (pat.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, pat.str.ptr, pat.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4413,7 +4417,7 @@ fn checkmatchexhaust(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Validity: every `case T` pattern (and multi-pattern alts) // must name a variant of u. Catches typos and dead arms that // the dispatch would never reach. @@ -4469,12 +4473,12 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = { os.write(2, where.ptr, where.len: u64); os.write(2, ": not assignable".ptr, 16u64); if (src != nil) { - if (src.kind == N_TNAME) { + if (src.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, src.str.ptr, src.str.len: u64); os.write(2, " → ".ptr, 5u64); if (dst != nil) { - if (dst.kind == N_TNAME) { + if (dst.kind == nkind.N_TNAME) { os.write(2, dst.str.ptr, dst.str.len: u64); }; }; @@ -4526,7 +4530,7 @@ fn checkisas(c: *checker, n: *node) void = { let st: *node = scruttype(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(st)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { + if (u.kind != nkind.N_TTAGGED) { os.write(2, "is/as: operand is not a tagged union\n".ptr, 37u64); c.errs += 1; return; @@ -4535,7 +4539,7 @@ fn checkisas(c: *checker, n: *node) void = { if (want == nil) { return; }; if (!casevariantin(u, want)) { os.write(2, "is/as: not a variant of operand".ptr, 31u64); - if (want.kind == N_TNAME) { + if (want.kind == nkind.N_TNAME) { os.write(2, " (".ptr, 2u64); os.write(2, want.str.ptr, want.str.len: u64); os.write(2, ")".ptr, 1u64); @@ -4549,26 +4553,26 @@ fn checkisas(c: *checker, n: *node) void = { // // For `expr?`, the operand's error subset must be a subset of the // enclosing fn's return-type variants. Mirrors C check.c. Operand -// is N_TRYPROP; its lhs is the value-bearing expr; we look at the -// expr's *declared* type for N_IDENT/N_CALL cases. +// is nkind.N_TRYPROP; its lhs is the value-bearing expr; we look at the +// expr's *declared* type for nkind.N_IDENT/nkind.N_CALL cases. fn exprtypeoftry(c: *checker, e: *node) *node = { if (e == nil) { return nil; }; - if (e.kind == N_IDENT) { + if (e.kind == nkind.N_IDENT) { let s: *sym = scopelookup(c.cur, e.str); if (s == nil) { return nil; }; if (s.decl == nil) { return nil; }; return s.decl.lhs; }; - if (e.kind == N_CALL) { - // callee return type lookup: callee is e.lhs (N_IDENT or - // N_DOT). We need the fn-decl's lhs (return-type AST). + if (e.kind == nkind.N_CALL) { + // callee return type lookup: callee is e.lhs (nkind.N_IDENT or + // nkind.N_DOT). We need the fn-decl's lhs (return-type AST). let callee: *node = e.lhs; if (callee == nil) { return nil; }; let nm: str; nm.ptr = nil; nm.len = 0; - if (callee.kind == N_IDENT) { nm = callee.str; }; - if (callee.kind == N_DOT) { nm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { nm = callee.str; }; + if (callee.kind == nkind.N_DOT) { nm = callee.str; }; if (nm.len == 0) { return nil; }; let s: *sym = scopelookup(c.cur, nm); if (s == nil) { return nil; }; @@ -4584,7 +4588,7 @@ fn checktryprop(c: *checker, n: *node) void = { let t: *node = exprtypeoftry(c, n.lhs); let u: *node = resolvealias(c, unwrapbang(t)); if (u == nil) { return; }; - if (u.kind != N_TTAGGED) { return; }; + if (u.kind != nkind.N_TTAGGED) { return; }; // Does the operand have any error variants? let haserr: bool = false; let v: *node = u.list; @@ -4601,7 +4605,7 @@ fn checktryprop(c: *checker, n: *node) void = { c.errs += 1; return; }; - if (r.kind != N_TTAGGED) { + if (r.kind != nkind.N_TTAGGED) { os.write(2, "?: enclosing fn return is not tagged\n".ptr, 37u64); c.errs += 1; return; @@ -4631,7 +4635,7 @@ fn checktryprop(c: *checker, n: *node) void = { fn installparams(c: *checker, params: *node) void = { let p: *node = params; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (nm.len > 0) { scopedefine(c.cur, nm, skind.SK_PARAM, nil, p); @@ -4673,7 +4677,7 @@ export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { export fn checkfile(c: *checker, file: *node) void = { if (file == nil) { return; }; - if (file.kind != N_FILE) { return; }; + if (file.kind != nkind.N_FILE) { return; }; // Pass 1: install all top-level names. let d: *node = file.list; @@ -4686,15 +4690,15 @@ export fn checkfile(c: *checker, file: *node) void = { d = file.list; for (d != nil) { let k: i32 = d.kind; - if (k == N_FNDECL) { + if (k == nkind.N_FNDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type resolvefnbody(c, d); - } else { if (k == N_DEF) { + } else { if (k == nkind.N_DEF) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; - } else { if (k == N_TYPEDECL) { + } else { if (k == nkind.N_TYPEDECL) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; - } else { if (k == N_LET) { + } else { if (k == nkind.N_LET) { if (d.lhs != nil) { resolvewalk(c, d.lhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); }; };};};}; @@ -4736,16 +4740,16 @@ use strconv; fn pushargsrev(c: *cgen, arg: *node) i32 = { if (arg == nil) { return 0; }; let rest: i32 = pushargsrev(c, arg.next); - // N_SLICE expression as arg: `buf[lo:hi]` builds a slice header + // nkind.N_SLICE expression as arg: `buf[lo:hi]` builds a slice header // on the stack matching C cgen's sequence — push base, push hi, // compute lo, pop into BX/CX, derive len/ptr, push (cap, len, ptr). - if (arg.kind == N_SLICE) { + if (arg.kind == nkind.N_SLICE) { let base: *node = arg.lhs; let lo: *node = arg.rhs; let hi: *node = arg.cond; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); }; @@ -4754,7 +4758,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); emitline("(BP), AX\n"); @@ -4778,20 +4782,20 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { } else { if (baselocal != nil) { let tn: *node = baselocal.tnode; if (tn != nil) { - if (tn.kind == N_TARRAY) { + if (tn.kind == nkind.N_TARRAY) { let lenn: *node = tn.rhs; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { + if (lenn.kind == nkind.N_INTLIT) { emitline("\tMOVQ\t$"); emituint(lenn.uval); emitline(", AX\n"); }; }; - } else { if (tn.kind == N_TSLICE) { + } else { if (tn.kind == nkind.N_TSLICE) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); emitline("(BP), AX\n"); - } else { if (tn.kind == N_TNAME) { + } else { if (tn.kind == nkind.N_TNAME) { if (streq(tn.str, "str")) { emitline("\tMOVQ\t"); emitoff((baselocal.off + 8): i64); @@ -4819,7 +4823,7 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { // Slice/tagged ident args: emit per-register MOVQ+PUSHQ pairs in // reverse order (cap/v1, len/v0, ptr/tag) so a left-to-right pop // into argregs lands the canonical (ptr/tag, len/v0, cap/v1). - if (arg.kind == N_IDENT) { + if (arg.kind == nkind.N_IDENT) { let nm: str = arg.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -4860,13 +4864,13 @@ fn pushargsrev(c: *cgen, arg: *node) i32 = { fn nodeisslice(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return isslicetype(c, lc.tnode); }; return false; }; - if (k == N_SLICE) { return true; }; + if (k == nkind.N_SLICE) { return true; }; return false; }; @@ -4876,14 +4880,14 @@ fn nodeisslice(c: *cgen, n: *node) bool = { fn nodeisstr(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_STRLIT) { return true; }; - if (k == N_IDENT) { + if (k == nkind.N_STRLIT) { return true; }; + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { + if (tn.kind == nkind.N_TNAME) { let tnm: str = tn.str; if (streq(tnm, "str")) { return true; }; }; @@ -4891,10 +4895,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CALL) { + if (k == nkind.N_CALL) { let callee: *node = n.lhs; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cnm: str = callee.str; let rt: *node = fnretlookup(c, cnm); return isstrtype(c, rt); @@ -4902,7 +4906,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; // `.ptr` is *u8 not str; `.len` is i32 not str. @@ -4912,17 +4916,17 @@ fn nodeisstr(c: *cgen, n: *node) bool = { if (base != nil) { let sname: str; sname.ptr = nil; sname.len = 0; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; }; @@ -4930,10 +4934,10 @@ fn nodeisstr(c: *cgen, n: *node) bool = { // Chained dot (`p.foo.bar`): use dotinnerstructptr // to resolve the inner chain to the *struct it lands // on, then look up `fld` in that struct. - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { - if (innert.kind == N_TNAME) { sname = innert.str; }; + if (innert.kind == nkind.N_TNAME) { sname = innert.str; }; }; }; if (sname.len > 0) { @@ -4952,7 +4956,7 @@ fn nodeisstr(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { return isstrtype(c, n.rhs); }; return false; @@ -4972,13 +4976,13 @@ fn typenameisunsigned(nm: str) bool = { // typenodeisunsigned — recurse through TNAME / TPTR / TSLICE etc. fn typenodeisunsigned(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { return typenameisunsigned(t.str); }; + if (t.kind == nkind.N_TNAME) { return typenameisunsigned(t.str); }; return false; }; // typeis8byteprimitive — does this type take exactly one 8-byte // slot (pointer / fn-ptr / 64-bit int / chan / scalar primitive -// padded up to 8) rather than a wider aggregate? Used by N_LET +// padded up to 8) rather than a wider aggregate? Used by nkind.N_LET // zero-init to mirror C cgen's "only zero if sz == 8 at the type // level" rule. Strings (16), slices (24), tagged unions (>=16), // tuples (16), structs (varies), arrays — all fall through to @@ -4986,14 +4990,14 @@ fn typenodeisunsigned(t: *node) bool = { fn typeis8byteprimitive(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; let k: i32 = t.kind; - if (k == N_TPTR) { return true; }; - if (k == N_TFN) { return true; }; - if (k == N_TCHAN) { return true; }; - if (k == N_TSLICE) { return false; }; - if (k == N_TARRAY) { return false; }; - if (k == N_TTUPLE) { return false; }; - if (k == N_TTAGGED){ return false; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { return true; }; + if (k == nkind.N_TFN) { return true; }; + if (k == nkind.N_TCHAN) { return true; }; + if (k == nkind.N_TSLICE) { return false; }; + if (k == nkind.N_TARRAY) { return false; }; + if (k == nkind.N_TTUPLE) { return false; }; + if (k == nkind.N_TTAGGED){ return false; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return false; }; // Struct alias: not a primitive even if the slot is 8B. @@ -5028,7 +5032,7 @@ fn fieldloadop(f: *fieldinfo) str = { if (sz == 4) { let t: *node = f.tnode; if (t != nil) { - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { if (typenameissigned(t.str)) { return "MOVSXD"; }; }; }; @@ -5053,11 +5057,11 @@ fn fieldstoreop(f: *fieldinfo) str = { // the slice element type. fn indexbaseesz(c: *cgen, base: *node) i32 = { if (base == nil) { return 8; }; - if (base.kind != N_DOT) { return 8; }; + if (base.kind != nkind.N_DOT) { return 8; }; let fld: str = base.str; let inner: *node = base.lhs; if (inner == nil) { return 8; }; - if (inner.kind != N_IDENT) { return 8; }; + if (inner.kind != nkind.N_IDENT) { return 8; }; let nm: str = inner.str; let lc: *local = localfindnode(c, nm); if (lc == nil) { return 8; }; @@ -5067,12 +5071,12 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { // `.ptr` pseudo-field on str/slice → element of the str/slice. if (streq(fld, "ptr")) { let innert: *node = tn; - if (tn.kind == N_TPTR) { innert = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { innert = tn.lhs; }; if (innert == nil) { return 8; }; - if (innert.kind == N_TNAME) { + if (innert.kind == nkind.N_TNAME) { if (streq(innert.str, "str")) { return 1; }; }; - if (innert.kind == N_TSLICE) { return elemsizeof(innert); }; + if (innert.kind == nkind.N_TSLICE) { return elemsizeof(innert); }; return 8; }; @@ -5080,11 +5084,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let pinner: *node = tn.lhs; if (pinner != nil) { - if (pinner.kind == N_TNAME) { sname = pinner.str; }; + if (pinner.kind == nkind.N_TNAME) { sname = pinner.str; }; }; }; if (sname.len == 0) { return 8; }; @@ -5096,10 +5100,10 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return 8; }; - if (ft.kind == N_TPTR) { + if (ft.kind == nkind.N_TPTR) { let elem: *node = ft.lhs; if (elem != nil) { - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { if (streq(elem.str, "str")) { return 16; }; let ps: i32 = primsize(elem.str); if (ps > 0) { return ps; }; @@ -5107,11 +5111,11 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { }; return 8; }; - if (ft.kind == N_TSLICE) { return elemsizeof(ft); }; + if (ft.kind == nkind.N_TSLICE) { return elemsizeof(ft); }; // str-typed field: indexing yields one byte // (`n.s[i]` where .s is str — matches C cgen's // MOVZBQ for byte indexing). - if (ft.kind == N_TNAME) { + if (ft.kind == nkind.N_TNAME) { if (streq(ft.str, "str")) { return 1; }; }; return 8; @@ -5121,36 +5125,36 @@ fn indexbaseesz(c: *cgen, base: *node) i32 = { return 8; }; -// dotinnerstructptr — for an N_DOT whose lhs is a chain of dots -// or an N_IDENT, walk the chain and return the N_TNAME tnode of the +// dotinnerstructptr — for an nkind.N_DOT whose lhs is a chain of dots +// or an nkind.N_IDENT, walk the chain and return the nkind.N_TNAME tnode of the // struct that the chain dereferences to (i.e., for `r.sym` where -// .sym is *lsym, return N_TNAME("lsym")). Returns nil if the chain +// .sym is *lsym, return nkind.N_TNAME("lsym")). Returns nil if the chain // doesn't resolve to a *struct. // // Used by the chained-DOT cgen path so `r.sym.val` knows the outer // is a field of `lsym`. fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (n == nil) { return nil; }; - if (n.kind != N_DOT) { return nil; }; + if (n.kind != nkind.N_DOT) { return nil; }; let base: *node = n.lhs; let fld: str = n.str; if (base == nil) { return nil; }; // Resolve base's struct tnode. let baset: *node = nil; - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc == nil) { return nil; }; let tn: *node = lc.tnode; if (tn == nil) { return nil; }; - // base could be either struct-by-value (N_TNAME) or *struct (N_TPTR). - if (tn.kind == N_TNAME) { baset = tn; }; - if (tn.kind == N_TPTR) { baset = tn.lhs; }; - } else { if (base.kind == N_DOT) { + // base could be either struct-by-value (nkind.N_TNAME) or *struct (nkind.N_TPTR). + if (tn.kind == nkind.N_TNAME) { baset = tn; }; + if (tn.kind == nkind.N_TPTR) { baset = tn.lhs; }; + } else { if (base.kind == nkind.N_DOT) { baset = dotinnerstructptr(c, base); };}; if (baset == nil) { return nil; }; - if (baset.kind != N_TNAME) { return nil; }; + if (baset.kind != nkind.N_TNAME) { return nil; }; // Look up the struct, find the field, return the field's *struct. let si: *structinfo = structlookup(c, baset.str); @@ -5160,10 +5164,10 @@ fn dotinnerstructptr(c: *cgen, n: *node) *node = { if (streq(fi.fname, fld)) { let ft: *node = fi.tnode; if (ft == nil) { return nil; }; - if (ft.kind != N_TPTR) { return nil; }; + if (ft.kind != nkind.N_TPTR) { return nil; }; let inner: *node = ft.lhs; if (inner == nil) { return nil; }; - if (inner.kind != N_TNAME) { return nil; }; + if (inner.kind != nkind.N_TNAME) { return nil; }; return inner; }; fi = fi.finext; @@ -5178,10 +5182,10 @@ fn elemsizeof(t: *node) i32 = { if (t == nil) { return 1; }; let k: i32 = t.kind; let elem: *node = nil; - if (k == N_TPTR) { elem = t.lhs; }; - if (k == N_TSLICE) { elem = t.lhs; }; - if (k == N_TARRAY) { elem = t.lhs; }; - if (k == N_TNAME) { + if (k == nkind.N_TPTR) { elem = t.lhs; }; + if (k == nkind.N_TSLICE) { elem = t.lhs; }; + if (k == nkind.N_TARRAY) { elem = t.lhs; }; + if (k == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return 1; }; // Indexing a primitive name (rare): element size = the prim. @@ -5190,7 +5194,7 @@ fn elemsizeof(t: *node) i32 = { return 1; }; if (elem == nil) { return 1; }; - if (elem.kind == N_TNAME) { + if (elem.kind == nkind.N_TNAME) { let nm: str = elem.str; // str element is 16B (ptr+len). primsize returns 0 for it. if (streq(nm, "str")) { return 16; }; @@ -5202,28 +5206,28 @@ fn elemsizeof(t: *node) i32 = { // nodeisunsigned — best-effort cgen-time inference from the AST. We // don't have a typed AST yet, so we walk surface nodes: -// N_INTLIT — never marked unsigned (no tsuffix plumbing yet) -// N_IDENT — look up the local's declared type -// N_DOT — look up the field's declared type via struct reg -// N_BIN / N_UN — recurse: unsigned if either operand is unsigned -// N_CAST — use the cast target type +// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet) +// nkind.N_IDENT — look up the local's declared type +// nkind.N_DOT — look up the field's declared type via struct reg +// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned +// nkind.N_CAST — use the cast target type // // Conservative: if we can't tell, return false (signed). The cost of // being wrong here is byte-different asm vs C, not bad runtime. fn nodeisunsigned(c: *cgen, n: *node) bool = { if (n == nil) { return false; }; let k: i32 = n.kind; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let nm: str = n.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { return typenodeisunsigned(lc.tnode); }; return false; }; - if (k == N_DOT) { + if (k == nkind.N_DOT) { let base: *node = n.lhs; let fld: str = n.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -5232,13 +5236,13 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { if (tn != nil) { lkind = tn.kind; }; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; - if (lkind == N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TNAME) { sname = tn.str; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -5257,29 +5261,29 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { }; return false; }; - if (k == N_CAST) { return typenodeisunsigned(n.rhs); }; - if (k == N_BIN) { + if (k == nkind.N_CAST) { return typenodeisunsigned(n.rhs); }; + if (k == nkind.N_BIN) { if (nodeisunsigned(c, n.lhs)) { return true; }; return nodeisunsigned(c, n.rhs); }; - if (k == N_UN) { return nodeisunsigned(c, n.lhs); }; - // N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. + if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; + // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. // Walks the base local's declared type and pulls the element // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the // compare-codegen for `p[i] >= 48u8` falls back to signed JGE // instead of JAE, diverging from C w6c on byte indexing. - if (k == N_INDEX) { + if (k == nkind.N_INDEX) { let base: *node = n.lhs; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, base.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { let elem: *node = nil; - if (tn.kind == N_TPTR) { elem = tn.lhs; }; - if (tn.kind == N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == N_TSLICE) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; + if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; if (elem != nil) { return typenodeisunsigned(elem); }; @@ -5307,7 +5311,7 @@ fn structlookup(c: *cgen, name: str) *structinfo = { // recognised as a primitive — the caller falls back to other paths). // fldnumidx — parse a tuple field name like "0" / "1" / "12" into an // index, or -1 if not all-digits. Used by cgdot to dispatch -// `t.0` / `t.1` against an N_TTUPLE local without pulling in strconv. +// `t.0` / `t.1` against an nkind.N_TTUPLE local without pulling in strconv. fn fldnumidx(s: str) i32 = { if (s.len == 0) { return -1; }; let r: i32 = 0; @@ -5352,14 +5356,14 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { // return elem_size * 1 (treating missing length as 1); intercept // and compute the real count first. if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs == nil) { if (n.rhs != nil) { - if (n.rhs.kind == N_ARRLIT) { + if (n.rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -5368,7 +5372,7 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { let e: *node = n.rhs.list; for (e != nil) { let adv: bool = true; - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { e = nil; adv = false; @@ -5391,11 +5395,11 @@ export fn letslotsize(c: *cgen, n: *node) i32 = { fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let k: i32 = typn.kind; - if (k == N_TPTR) { return 8; }; - if (k == N_TFN) { return 8; }; - if (k == N_TCHAN) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TTUPLE) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TFN) { return 8; }; + if (k == nkind.N_TCHAN) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TTUPLE) { // Sum element sizes. Mirrors C cgen which uses raw type // sizes; padding to 8 happens inside slotsize for primitives, // so a `(i64, str)` resolves to 8 + 16 = 24 (matches the C @@ -5408,13 +5412,13 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return total; }; - if (k == N_TTAGGED){ + if (k == nkind.N_TTAGGED){ // Nullable `(*T | void)` collapses to a single 8B pointer. if (isnullabletype(typn)) { return 8; }; // Slot = 8 (tag) + max(variant payload sizes), rounded up // to an 8-byte multiple so the reg-passing ABI (size/8 // words) doesn't drop the last value register. Mirrors C - // cgen's resolve_type for N_TTAGGED. + // cgen's resolve_type for nkind.N_TTAGGED. let v: *node = typn.list; let maxsz: i32 = 0; for (v != nil) { @@ -5425,7 +5429,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { let pad: i32 = (maxsz + 7) & ~7; return 8 + pad; }; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = typn.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -5439,16 +5443,16 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TARRAY) { + if (k == nkind.N_TARRAY) { let lenn: *node = typn.rhs; let elemn: *node = typn.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let en: str = elemn.str; let ps: i32 = primsize(en); if (ps > 0) { esz = ps; }; @@ -5456,12 +5460,12 @@ fn slotsize(c: *cgen, typn: *node) i32 = { }; return (esz: i64 * elen): i32; }; - if (k == N_TSTRUCT) { + if (k == nkind.N_TSTRUCT) { // Inline anonymous struct — sum of field sizes. let f: *node = typn.list; let total: i32 = 0; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { total += slotsize(c, f.lhs); }; f = f.next; @@ -5478,7 +5482,7 @@ fn slotsize(c: *cgen, typn: *node) i32 = { fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let k: i32 = tnode.kind; - if (k == N_TNAME) { + if (k == nkind.N_TNAME) { let nm: str = tnode.str; if (streq(nm, "str")) { return 16; }; let ps: i32 = primsize(nm); @@ -5487,15 +5491,15 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (si != nil) { return si.totsize; }; return 8; }; - if (k == N_TPTR) { return 8; }; - if (k == N_TSLICE) { return 24; }; - if (k == N_TARRAY) { + if (k == nkind.N_TPTR) { return 8; }; + if (k == nkind.N_TSLICE) { return 24; }; + if (k == nkind.N_TARRAY) { // Same shape as slotsize's TARRAY branch. let lenn: *node = tnode.rhs; let elemn: *node = tnode.lhs; let elen: i64 = 1i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { elen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { elen = lenn.uval: i64; }; }; let esz: i32 = fieldsize(c, elemn); return (esz: i64 * elen): i32; @@ -5513,7 +5517,7 @@ fn registerstruct(c: *cgen, name: str, tstruct: *node) void = { let off: i32 = 0; let f: *node = tstruct.list; for (f != nil) { - if (f.kind == N_TFIELD) { + if (f.kind == nkind.N_TFIELD) { let sz: i32 = fieldsize(c, f.lhs); // Align to 8 for any field >= 4 bytes (matches our other // cgen choices). i8/u8/bool may sit on odd byte offsets; @@ -5549,10 +5553,10 @@ fn collectstructs(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TSTRUCT) { + if (body.kind == nkind.N_TSTRUCT) { registerstruct(c, d.str, body); }; }; @@ -5565,7 +5569,7 @@ fn collectstructs(c: *cgen, file: *node) void = { // alias chain registered at file load. fn isstrtyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TNAME) { let nm: str = t.str; if (streq(nm, "str")) { return true; }; }; @@ -5581,7 +5585,7 @@ fn isstrtype(c: *cgen, t: *node) bool = { fn isslicetyperaw(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TSLICE) { return true; }; + if (t.kind == nkind.N_TSLICE) { return true; }; return false; }; @@ -5594,26 +5598,26 @@ fn isslicetype(c: *cgen, t: *node) bool = { fn istaggedtype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TTAGGED) { return true; }; + if (t.kind == nkind.N_TTAGGED) { return true; }; return false; }; -// isnullabletype — N_TTAGGED with exactly two children, one *T and +// isnullabletype — nkind.N_TTAGGED with exactly two children, one *T and // one `void`. Folds to a single 8-byte pointer slot per Hare's // `(*T | null)` semantics. Mirrors check.c's resolve_type detection. export fn isnullabletype(t: *node) bool = { if (t == nil) { return false; }; - if (t.kind != N_TTAGGED) { return false; }; + if (t.kind != nkind.N_TTAGGED) { return false; }; let a: *node = t.list; if (a == nil) { return false; }; let b: *node = a.next; if (b == nil) { return false; }; if (b.next != nil) { return false; }; - let aptr: bool = (a.kind == N_TPTR); - let bptr: bool = (b.kind == N_TPTR); - let avoid: bool = (a.kind == N_TNAME); + let aptr: bool = (a.kind == nkind.N_TPTR); + let bptr: bool = (b.kind == nkind.N_TPTR); + let avoid: bool = (a.kind == nkind.N_TNAME); if (avoid) { avoid = streq(a.str, "void"); }; - let bvoid: bool = (b.kind == N_TNAME); + let bvoid: bool = (b.kind == nkind.N_TNAME); if (bvoid) { bvoid = streq(b.str, "void"); }; if (aptr) { if (bvoid) { return true; }; }; if (avoid) { if (bptr) { return true; }; }; @@ -5624,9 +5628,9 @@ export fn isnullabletype(t: *node) bool = { // union. The void variant takes the other slot (0 or 1). export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; - if (t.kind != N_TTAGGED) { return 0; }; + if (t.kind != nkind.N_TTAGGED) { return 0; }; let a: *node = t.list; - if (a != nil) { if (a.kind == N_TPTR) { return 0; }; }; + if (a != nil) { if (a.kind == nkind.N_TPTR) { return 0; }; }; return 1; }; @@ -5635,11 +5639,11 @@ export fn nullableptrtag(t: *node) i32 = { // `return;` in a tagged-union-returning fn to the void variant's tag. fn voidvariantindex(tagged: *node) i32 = { if (tagged == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, "void")) { return idx; }; }; v = v.next; @@ -5655,20 +5659,20 @@ fn rhstargetname(c: *cgen, rhs: *node) str = { let nm: str; nm.ptr = nil; nm.len = 0; if (rhs == nil) { return nm; }; - if (rhs.kind == N_CAST) { + if (rhs.kind == nkind.N_CAST) { let t: *node = rhs.rhs; if (t != nil) { - if (t.kind == N_TNAME) { return t.str; }; + if (t.kind == nkind.N_TNAME) { return t.str; }; }; return nm; }; - if (rhs.kind == N_STRLIT) { return "str"; }; - if (rhs.kind == N_IDENT) { + if (rhs.kind == nkind.N_STRLIT) { return "str"; }; + if (rhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, rhs.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TNAME) { return tn.str; }; + if (tn.kind == nkind.N_TNAME) { return tn.str; }; }; }; }; @@ -5687,7 +5691,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, wantname)) { return idx; }; }; v = v.next; @@ -5700,7 +5704,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { let idx: i32 = 0; for (v != nil) { let visstr: bool = false; - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (isstrtype(c, v)) { visstr = true; }; }; if (visstr == wantstr) { return idx; }; @@ -5716,7 +5720,7 @@ fn taggedvariantindex(c: *cgen, tagged: *node, rhs: *node) i32 = { // cgexpr is a thin dispatcher over n.kind; each non-trivial branch // lives in a per-kind helper (cgstrlit, cgident, cgindex, cgmatch, // cgdot, cgun, cgbin, cgcall, cgassign). Trivial literal loads -// (N_INTLIT, N_RUNELIT, N_TRUE/FALSE/NIL, N_CAST) stay inline. +// (nkind.N_INTLIT, nkind.N_RUNELIT, nkind.N_TRUE/FALSE/NIL, nkind.N_CAST) stay inline. // // The remainder of cgen lives in cgen.ww (foundation: types, emit // primitives, the collect* tables, FFI/module maps) and cgenstmt.ww @@ -5737,7 +5741,7 @@ fn cgexpr(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_INTLIT) { + if (k == nkind.N_INTLIT) { // Print signed (i64), not unsigned (u64). C cgen uses // `$%lld` so 64-bit constants with bit 63 set show up as // negative — e.g. FNV-1a's offset basis prints as @@ -5747,39 +5751,39 @@ fn cgexpr(c: *cgen, n: *node) void = { emitline(", AX\n"); return; }; - if (k == N_RUNELIT) { + if (k == nkind.N_RUNELIT) { emitline("\tMOVQ\t$"); emitint(n.uval: i64); emitline(", AX\n"); return; }; - if (k == N_STRLIT) { cgstrlit(c, n); return; }; - if (k == N_TRUE) { + if (k == nkind.N_STRLIT) { cgstrlit(c, n); return; }; + if (k == nkind.N_TRUE) { emitline("\tMOVQ\t$1, AX\n"); return; }; - if (k == N_FALSE) { + if (k == nkind.N_FALSE) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_NIL) { + if (k == nkind.N_NIL) { emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_VOIDLIT) { + if (k == nkind.N_VOIDLIT) { // void value: zero-size, but the consumer's ABI expects a // deterministic AX. Emit 0 like nil/false do. emitline("\tMOVQ\t$0, AX\n"); return; }; - if (k == N_IDENT) { cgident(c, n); return; }; + if (k == nkind.N_IDENT) { cgident(c, n); return; }; - if (k == N_INDEX) { cgindex(c, n); return; }; + if (k == nkind.N_INDEX) { cgindex(c, n); return; }; - if (k == N_MATCH) { cgmatch(c, n); return; }; + if (k == nkind.N_MATCH) { cgmatch(c, n); return; }; - if (k == N_CAST) { + if (k == nkind.N_CAST) { // Type casts are mostly no-ops at the asm level for our // integer-shaped operands. Evaluate the source; AX holds // the bits unchanged. (Sign- or zero-extending narrow loads @@ -5789,38 +5793,38 @@ fn cgexpr(c: *cgen, n: *node) void = { return; }; - if (k == N_DOT) { cgdot(c, n); return; }; + if (k == nkind.N_DOT) { cgdot(c, n); return; }; - if (k == N_UN) { cgun(c, n); return; }; + if (k == nkind.N_UN) { cgun(c, n); return; }; - if (k == N_BIN) { cgbin(c, n); return; }; + if (k == nkind.N_BIN) { cgbin(c, n); return; }; - if (k == N_CALL) { cgcall(c, n); return; }; + if (k == nkind.N_CALL) { cgcall(c, n); return; }; - if (k == N_ASSIGN) { cgassign(c, n); return; }; + if (k == nkind.N_ASSIGN) { cgassign(c, n); return; }; - if (k == N_TRYPROP) { cgtryprop(c, n); return; }; - if (k == N_TRYUNW) { cgtryunw(c, n); return; }; - if (k == N_TYPETEST) { cgtypetest(c, n); return; }; - if (k == N_TYPEASSERT) { cgtypeassert(c, n); return; }; + if (k == nkind.N_TRYPROP) { cgtryprop(c, n); return; }; + if (k == nkind.N_TRYUNW) { cgtryunw(c, n); return; }; + if (k == nkind.N_TYPETEST) { cgtypetest(c, n); return; }; + if (k == nkind.N_TYPEASSERT) { cgtypeassert(c, n); return; }; }; // cgtagvariantidx — find the 0-based variant index of `vt` inside the // tagged-union type expression `tagged`. -1 if `tagged` isn't an -// N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch +// nkind.N_TTAGGED or no variant matches. Mirrors the lookup that cgmatch // does inline; pulled out so `is` / `as` can reuse it. fn cgtagvariantidx(tagged: *node, vt: *node) i32 = { if (tagged == nil) { return -1; }; if (vt == nil) { return -1; }; - if (tagged.kind != N_TTAGGED) { return -1; }; + if (tagged.kind != nkind.N_TTAGGED) { return -1; }; let want: str; want.ptr = nil; want.len = 0; - if (vt.kind == N_TNAME) { want = vt.str; }; + if (vt.kind == nkind.N_TNAME) { want = vt.str; }; if (want.len == 0) { return -1; }; let v: *node = tagged.list; let idx: i32 = 0; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, want)) { return idx; }; }; v = v.next; @@ -5849,17 +5853,17 @@ fn cgtryprop(c: *cgen, n: *node) void = { // shuffle (DX,CX) → (AX,BX); else move DX → AX. let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -5893,17 +5897,17 @@ fn cgtryunw(c: *cgen, n: *node) void = { // Unwrap success value. (Same shuffle pattern as cgtryprop.) let succisstr: bool = false; if (n.lhs != nil) { - if (n.lhs.kind == N_CALL) { + if (n.lhs.kind == nkind.N_CALL) { let callee: *node = n.lhs.lhs; if (callee != nil) { let cname: str; cname.ptr = nil; cname.len = 0; - if (callee.kind == N_IDENT) { cname = callee.str; }; - if (callee.kind == N_DOT) { cname = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cname = callee.str; }; + if (callee.kind == nkind.N_DOT) { cname = callee.str; }; if (cname.len > 0) { let rt: *node = fnretlookup(c, cname); if (rt != nil) { - if (rt.kind == N_TTAGGED) { + if (rt.kind == nkind.N_TTAGGED) { let first: *node = rt.list; if (first != nil) { if (isstrtype(c, first)) { @@ -5935,7 +5939,7 @@ fn cgtypetest(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -5966,33 +5970,33 @@ fn cgtypetest(c: *cgen, n: *node) void = { // isenumexpr — does this expression's static type resolve to an enum? // Recognises enum-member access (`Foo.MEMBER`), enum-typed local -// idents, and N_BIN whose either operand is enum (so `R | W` flows +// idents, and nkind.N_BIN whose either operand is enum (so `R | W` flows // through the cast pass-through too). fn isenumexpr(c: *cgen, e: *node) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_DOT) { + if (k == nkind.N_DOT) { if (e.lhs != nil) { - if (e.lhs.kind == N_IDENT) { + if (e.lhs.kind == nkind.N_IDENT) { if (enumlookup(c, e.lhs.str) != nil) { return true; }; }; }; }; - if (k == N_IDENT) { + if (k == nkind.N_IDENT) { let lc: *local = localfindnode(c, e.str); if (lc != nil) { if (lc.tnode != nil) { - if (lc.tnode.kind == N_TNAME) { + if (lc.tnode.kind == nkind.N_TNAME) { if (enumlookup(c, lc.tnode.str) != nil) { return true; }; }; }; }; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { if (isenumexpr(c, e.lhs)) { return true; }; if (isenumexpr(c, e.rhs)) { return true; }; }; - if (k == N_UN) { + if (k == nkind.N_UN) { if (isenumexpr(c, e.lhs)) { return true; }; }; return false; @@ -6000,8 +6004,8 @@ fn isenumexpr(c: *cgen, e: *node) bool = { fn isenumtype(c: *cgen, t: *node) bool = { if (t == nil) { return false; }; - if (t.kind == N_TENUM) { return true; }; - if (t.kind == N_TNAME) { + if (t.kind == nkind.N_TENUM) { return true; }; + if (t.kind == nkind.N_TNAME) { if (enumlookup(c, t.str) != nil) { return true; }; }; return false; @@ -6023,7 +6027,7 @@ fn cgtypeassert(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, lhs.str); if (lc != nil) { scrutoff = lc.off; @@ -6125,11 +6129,11 @@ fn cgindex(c: *cgen, n: *node) void = { let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -6143,7 +6147,7 @@ fn cgindex(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -6192,7 +6196,7 @@ fn cgmatch(c: *cgen, n: *node) void = { let scrutoff: i32 = 0; let scrutt: *node = nil; if (scrut != nil) { - if (scrut.kind == N_IDENT) { + if (scrut.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, scrut.str); if (lc != nil) { scrutoff = lc.off; @@ -6220,7 +6224,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // void arm: skip if ptr != 0. let ptr_tag: i32 = nullableptrtag(scrutt); let cur_tag: i32 = 0; - if (pat.kind == N_TPTR) { cur_tag = ptr_tag; } + if (pat.kind == nkind.N_TPTR) { cur_tag = ptr_tag; } else { if (ptr_tag == 0) { cur_tag = 1; }; }; emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -6236,15 +6240,15 @@ fn cgmatch(c: *cgen, n: *node) void = { } else { let want: i32 = 0; if (scrutt != nil) { - if (scrutt.kind == N_TTAGGED) { + if (scrutt.kind == nkind.N_TTAGGED) { let patname: str; patname.ptr = nil; patname.len = 0; - if (pat.kind == N_TNAME) { patname = pat.str; }; + if (pat.kind == nkind.N_TNAME) { patname = pat.str; }; let v: *node = scrutt.list; let idx: i32 = 0; let found: bool = false; for (v != nil) { - if (v.kind == N_TNAME) { + if (v.kind == nkind.N_TNAME) { if (streq(v.str, patname)) { want = idx; found = true; @@ -6278,7 +6282,7 @@ fn cgmatch(c: *cgen, n: *node) void = { // Bind the pointer (or skip for the // void arm, which has zero-size). The // value IS slot+0. - if (pat.kind == N_TPTR) { + if (pat.kind == nkind.N_TPTR) { let voff: i32 = localalloc(c, bn, 8, pat); emitline("\tMOVQ\t"); emitoff(scrutoff: i64); @@ -6334,12 +6338,12 @@ fn cgdot(c: *cgen, n: *node) void = { if (lhs != nil) { let etname: str; etname.ptr = nil; etname.len = 0; - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { if (lhs.lhs != nil) { - if (lhs.lhs.kind == N_IDENT) { + if (lhs.lhs.kind == nkind.N_IDENT) { etname = lhs.str; }; }; @@ -6358,7 +6362,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let lc: *local = localfindnode(c, nm); if (lc != nil) { @@ -6366,12 +6370,12 @@ fn cgdot(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then field load. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; @@ -6412,7 +6416,7 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Direct struct local: field load at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -6446,7 +6450,7 @@ fn cgdot(c: *cgen, n: *node) void = { // Array pseudo-fields: `.ptr` is the array's // address (LEAQ); `.len` is the static element // count (immediate). - if (lkind == N_TARRAY) { + if (lkind == nkind.N_TARRAY) { if (streq(fld, "ptr")) { emitline("\tLEAQ\t"); emitoff(lc.off: i64); @@ -6457,7 +6461,7 @@ fn cgdot(c: *cgen, n: *node) void = { let lenn: *node = tn.rhs; let alen: i64 = 0i64; if (lenn != nil) { - if (lenn.kind == N_INTLIT) { alen = lenn.uval: i64; }; + if (lenn.kind == nkind.N_INTLIT) { alen = lenn.uval: i64; }; }; emitline("\tMOVQ\t$"); emitint(alen); @@ -6471,7 +6475,7 @@ fn cgdot(c: *cgen, n: *node) void = { // the scalar in an 8B slot and the str in 16B). For // a str element, load both halves into (AX, BX) so // chains like `t.1.len` propagate correctly. - if (lkind == N_TTUPLE) { + if (lkind == nkind.N_TTUPLE) { let idx: i32 = fldnumidx(fld); if (idx >= 0) { let tp: *node = tn.list; @@ -6518,15 +6522,15 @@ fn cgdot(c: *cgen, n: *node) void = { // Pointer to str/slice (`*[]u8`, `*str`): // deref, then load at delta within the // pointed-to header. C cgen does the same. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { emitline("\tMOVQ\t"); emitoff(lc.off: i64); @@ -6549,12 +6553,12 @@ fn cgdot(c: *cgen, n: *node) void = { // Sdef-backed strs aren't laid out in memory, so falling // through to the SB-load fallback below would mis-emit // `MOVQ (SB), AX` (looking up the field name as a - // symbol). Mirrors cmd/w6c/cgen.c N_DOT off==0 / Sdef branch. + // symbol). Mirrors cmd/w6c/cgen.c nkind.N_DOT off==0 / Sdef branch. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let drhs: *node = deflookuprhs(c, lhs.str); if (drhs != nil) { - if (drhs.kind == N_STRLIT) { + if (drhs.kind == nkind.N_STRLIT) { let bytes: str = drhs.str; if (streq(fld, "ptr")) { let lab: str = internstrlit(c, bytes); @@ -6574,11 +6578,11 @@ fn cgdot(c: *cgen, n: *node) void = { }; }; // Module-qualified value reference: `mod.name` where `mod` - // is N_IDENT bound as skind.SK_USE and the leaf isn't a local. + // is nkind.N_IDENT bound as skind.SK_USE and the leaf isn't a local. // Treat as a SB symbol — `MOVQ leaf(SB), AX`. Same fallback // the C cgen takes when bt is NULL/tyerr. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { emitline("\tMOVQ\t"); emitsymname(c, fld); emitline("(SB), AX\n"); @@ -6605,7 +6609,7 @@ fn cgdot(c: *cgen, n: *node) void = { // itself, so reads silently get the pointer value instead of // the field. (Showed up porting w6l/pass.ww.) if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, lhs); if (innert != nil) { let sname: str = innert.str; @@ -6654,7 +6658,7 @@ fn cgun(c: *cgen, n: *node) void = { if (n.op == tkind.TK_AMP) { let opnd: *node = n.lhs; if (opnd != nil) { - if (opnd.kind == N_IDENT) { + if (opnd.kind == nkind.N_IDENT) { let nm: str = opnd.str; let off: i32 = localfind(c, nm); if (off != 0) { @@ -6760,7 +6764,7 @@ fn cgcall(c: *cgen, n: *node) void = { let calleename: str; calleename.ptr = nil; calleename.len = 0; // Detect fn-pointer field call: `w.emit(args)` where `w` is - // a struct local and `emit` is an N_TFN field. Load the + // a struct local and `emit` is an nkind.N_TFN field. Load the // field value into AX and CALL through it. Also detect a // bare `fp(args)` where `fp` is a local holding a function // pointer — mirror C cgen's localfind dispatch (commit @@ -6768,17 +6772,17 @@ fn cgcall(c: *cgen, n: *node) void = { // the linker rightly fails. let isfnptrcall: bool = false; if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { let cn: str = callee.str; if (localfindnode(c, cn) != nil) { isfnptrcall = true; }; }; - if (callee.kind == N_DOT) { + if (callee.kind == nkind.N_DOT) { let base: *node = callee.lhs; let fld: str = callee.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -6787,11 +6791,11 @@ fn cgcall(c: *cgen, n: *node) void = { let lkind: i32 = tn.kind; let sname: str; sname.ptr = nil; sname.len = 0; - if (lkind == N_TNAME) { sname = tn.str; }; - if (lkind == N_TPTR) { + if (lkind == nkind.N_TNAME) { sname = tn.str; }; + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; }; if (sname.len > 0) { @@ -6803,7 +6807,7 @@ fn cgcall(c: *cgen, n: *node) void = { if (streq(fn_, fld)) { let ft: *node = fi.tnode; if (ft != nil) { - if (ft.kind == N_TFN) { + if (ft.kind == nkind.N_TFN) { isfnptrcall = true; }; }; @@ -6830,10 +6834,10 @@ fn cgcall(c: *cgen, n: *node) void = { } else { emitline("\tCALL\t"); if (callee != nil) { - if (callee.kind == N_IDENT) { + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; emitsymname(c, calleename); - } else { if (callee.kind == N_DOT) { + } else { if (callee.kind == nkind.N_DOT) { calleename = callee.str; emitsymname(c, calleename); };}; @@ -6854,10 +6858,10 @@ fn cgcall(c: *cgen, n: *node) void = { fn cgassign(c: *cgen, n: *node) void = { let lhs: *node = n.lhs; // Discard lvalue `_ = expr;` — evaluate rhs for side effects, - // write nothing. Detected by lhs being an N_IDENT with empty str + // write nothing. Detected by lhs being an nkind.N_IDENT with empty str // (planted by parseprimary on the tkind.TK_UNDER token). if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { if (lhs.str.len == 0) { if (n.op == tkind.TK_ASSIGN) { cgexpr(c, n.rhs); @@ -6872,22 +6876,22 @@ fn cgassign(c: *cgen, n: *node) void = { // We default to MOVQ (8B) since most fixtures use it; for // `*bool` / `*u8` / `*i32` we narrow via the local's tnode. if (lhs != nil) { - if (lhs.kind == N_UN) { + if (lhs.kind == nkind.N_UN) { if (lhs.op == tkind.TK_STAR) { if (n.op == tkind.TK_ASSIGN) { let inner: *node = lhs.lhs; let elemstr: bool = false; let storeop: str = "MOVQ"; if (inner != nil) { - if (inner.kind == N_IDENT) { + if (inner.kind == nkind.N_IDENT) { let lc: *local = localfindnode(c, inner.str); if (lc != nil) { let tn: *node = lc.tnode; if (tn != nil) { - if (tn.kind == N_TPTR) { + if (tn.kind == nkind.N_TPTR) { let pe: *node = tn.lhs; if (pe != nil) { - if (pe.kind == N_TNAME) { + if (pe.kind == nkind.N_TNAME) { if (streq(pe.str, "str")) { elemstr = true; } else { let ps: i32 = primsize(pe.str); @@ -6931,20 +6935,20 @@ fn cgassign(c: *cgen, n: *node) void = { // Array/slice/ptr index store: `arr[i] = v;`. Element size // from base.tnode picks MOVB vs MOVQ. if (lhs != nil) { - if (lhs.kind == N_INDEX) { + if (lhs.kind == nkind.N_INDEX) { if (n.op == tkind.TK_ASSIGN) { let base: *node = lhs.lhs; let idx: *node = lhs.rhs; let esz: i32 = 8; let baselocal: *local = nil; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; baselocal = localfindnode(c, bn); if (baselocal != nil) { esz = elemsizeof(baselocal.tnode); }; - } else { if (base.kind == N_DOT) { + } else { if (base.kind == nkind.N_DOT) { esz = indexbaseesz(c, base); };}; }; @@ -6962,7 +6966,7 @@ fn cgassign(c: *cgen, n: *node) void = { if (baselocal != nil) { let tn: *node = baselocal.tnode; let isarray: bool = false; - if (tn != nil) { if (tn.kind == N_TARRAY) { isarray = true; }; }; + if (tn != nil) { if (tn.kind == nkind.N_TARRAY) { isarray = true; }; }; if (isarray) { emitline("\tLEAQ\t"); emitoff(baselocal.off: i64); @@ -6995,11 +6999,11 @@ fn cgassign(c: *cgen, n: *node) void = { // `p.f = expr;`. Only plain `=` is wired (compound on field // is rare and not yet needed by our fixtures). if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_IDENT) { + if (base.kind == nkind.N_IDENT) { let bn: str = base.str; let lc: *local = localfindnode(c, bn); if (lc != nil) { @@ -7007,12 +7011,12 @@ fn cgassign(c: *cgen, n: *node) void = { let lkind: i32 = -1; if (tn != nil) { lkind = tn.kind; }; // Pointer-to-struct: deref then store. - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (inner != nil) { - if (inner.kind == N_TNAME) { sname = inner.str; }; + if (inner.kind == nkind.N_TNAME) { sname = inner.str; }; }; if (sname.len > 0) { let si: *structinfo = structlookup(c, sname); @@ -7081,7 +7085,7 @@ fn cgassign(c: *cgen, n: *node) void = { }; }; // Direct struct local: store at off+foff. - if (lkind == N_TNAME) { + if (lkind == nkind.N_TNAME) { let sname: str = tn.str; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -7108,15 +7112,15 @@ fn cgassign(c: *cgen, n: *node) void = { if (streq(fld, "len")) { delta = 8; }; if (streq(fld, "cap")) { delta = 16; }; if (delta >= 0) { - if (lkind == N_TPTR) { + if (lkind == nkind.N_TPTR) { let inner: *node = tn.lhs; let innerkind: i32 = -1; if (inner != nil) { innerkind = inner.kind; }; let innerstr: bool = false; - if (innerkind == N_TNAME) { + if (innerkind == nkind.N_TNAME) { if (streq(inner.str, "str")) { innerstr = true; }; }; - if (innerkind == N_TSLICE) { innerstr = true; }; + if (innerkind == nkind.N_TSLICE) { innerstr = true; }; if (innerstr) { if (n.op != tkind.TK_ASSIGN) { // Compound on `(*str|*slice).field`: load @@ -7175,11 +7179,11 @@ fn cgassign(c: *cgen, n: *node) void = { // store. Only plain `=` is wired here; chained compound on a // pointer-field hasn't surfaced. if (lhs != nil) { - if (lhs.kind == N_DOT) { + if (lhs.kind == nkind.N_DOT) { let base: *node = lhs.lhs; let fld: str = lhs.str; if (base != nil) { - if (base.kind == N_DOT) { + if (base.kind == nkind.N_DOT) { let innert: *node = dotinnerstructptr(c, base); if (innert != nil) { let sname: str = innert.str; @@ -7235,7 +7239,7 @@ fn cgassign(c: *cgen, n: *node) void = { // forms (+= -= *= /=); other compounds fall back to // "evaluate rhs, replace". Mirrors C cgen's IDENT-assign path. if (lhs != nil) { - if (lhs.kind == N_IDENT) { + if (lhs.kind == nkind.N_IDENT) { let nm: str = lhs.str; let off: i32 = localfind(c, nm); if (off == 0) { return; }; @@ -7320,28 +7324,28 @@ fn cgstmt(c: *cgen, n: *node) void = { if (n == nil) { return; }; let k: i32 = n.kind; - if (k == N_BLOCK) { cgblock(c, n); return; }; + if (k == nkind.N_BLOCK) { cgblock(c, n); return; }; - if (k == N_RETURN) { cgreturn(c, n); return; }; + if (k == nkind.N_RETURN) { cgreturn(c, n); return; }; - if (k == N_EXPRSTMT) { cgexprstmt(c, n); return; }; + if (k == nkind.N_EXPRSTMT) { cgexprstmt(c, n); return; }; - if (k == N_LET) { cglet(c, n); return; }; + if (k == nkind.N_LET) { cglet(c, n); return; }; - if (k == N_IF) { cgif(c, n); return; }; + if (k == nkind.N_IF) { cgif(c, n); return; }; - if (k == N_FOR) { cgfor(c, n); return; }; + if (k == nkind.N_FOR) { cgfor(c, n); return; }; - if (k == N_MASSIGN) { cgmassign(c, n); return; }; + if (k == nkind.N_MASSIGN) { cgmassign(c, n); return; }; - if (k == N_MLET) { cgmlet(c, n); return; }; + if (k == nkind.N_MLET) { cgmlet(c, n); return; }; - if (k == N_BREAK) { cgbreak(c, n); return; }; - if (k == N_CONTINUE) { cgcontinue(c, n); return; }; + if (k == nkind.N_BREAK) { cgbreak(c, n); return; }; + if (k == nkind.N_CONTINUE) { cgcontinue(c, n); return; }; - if (k == N_YIELD) { cgyield(c, n); return; }; + if (k == nkind.N_YIELD) { cgyield(c, n); return; }; - if (k == N_DEFER) { + if (k == nkind.N_DEFER) { if (c.defertop < DEFER_MAX) { c.deferbuf[c.defertop] = n.lhs; c.defertop += 1; @@ -7397,7 +7401,7 @@ fn cgreturn(c: *cgen, n: *node) void = { // DX = str.ptr, CX = str.len. // 24B convention mirrors the tagged-union return below; receive // sites destructure off the same regs regardless of position. - if (rhs.kind == N_TUPLE) { + if (rhs.kind == nkind.N_TUPLE) { let v: *node = rhs.list; if (v != nil) { let v2: *node = v.next; @@ -7519,13 +7523,13 @@ fn cglet(c: *cgen, n: *node) void = { if (istaggedtype(n.lhs)) { let nullable: bool = isnullabletype(n.lhs); let rhsreturnstagged: bool = false; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let calleename: str; calleename.ptr = nil; calleename.len = 0; - if (callee.kind == N_IDENT) { calleename = callee.str; }; - if (callee.kind == N_DOT) { calleename = callee.str; }; + if (callee.kind == nkind.N_IDENT) { calleename = callee.str; }; + if (callee.kind == nkind.N_DOT) { calleename = callee.str; }; if (calleename.len > 0) { let rt: *node = fnretlookup(c, calleename); if (istaggedtype(rt)) { rhsreturnstagged = true; }; @@ -7588,7 +7592,7 @@ fn cglet(c: *cgen, n: *node) void = { // Layout is positional, so we route each register to the // slot dictated by element type, not by AX/DX position. if (n.lhs != nil) { - if (n.lhs.kind == N_TTUPLE) { + if (n.lhs.kind == nkind.N_TTUPLE) { let p0: *node = n.lhs.list; let p1: *node = nil; if (p0 != nil) { p1 = p0.next; }; @@ -7629,13 +7633,13 @@ fn cglet(c: *cgen, n: *node) void = { // Array literal init: `let xs: [N]T = [a, b, c];` (or [_]T). // Walk elements in declaration order, store each at off + i*esz // using the right width for the element type. Trailing `...` - // after the last value (an N_FIELD with str=="...") fills the + // after the last value (an nkind.N_FIELD with str=="...") fills the // remaining slots up to the declared length with that value. - if (rhs.kind == N_ARRLIT) { + if (rhs.kind == nkind.N_ARRLIT) { let elemn: *node = n.lhs.lhs; let esz: i32 = 8; if (elemn != nil) { - if (elemn.kind == N_TNAME) { + if (elemn.kind == nkind.N_TNAME) { let ps: i32 = primsize(elemn.str); if (ps > 0) { esz = ps; }; }; @@ -7647,7 +7651,7 @@ fn cglet(c: *cgen, n: *node) void = { let repeat: bool = false; let e: *node = rhs.list; for (e != nil) { - if (e.kind == N_FIELD) { + if (e.kind == nkind.N_FIELD) { if (streq(e.str, "...")) { repeat = true; e = nil; @@ -7677,9 +7681,9 @@ fn cglet(c: *cgen, n: *node) void = { if (repeat) { let total: i32 = idx; if (n.lhs != nil) { - if (n.lhs.kind == N_TARRAY) { + if (n.lhs.kind == nkind.N_TARRAY) { if (n.lhs.rhs != nil) { - if (n.lhs.rhs.kind == N_INTLIT) { + if (n.lhs.rhs.kind == nkind.N_INTLIT) { total = n.lhs.rhs.uval: i32; }; }; @@ -7704,13 +7708,13 @@ fn cglet(c: *cgen, n: *node) void = { // op == tkind.TK_ELLIPSIS (autofill marker from the parser), the // entire slot is zero-filled first so unmentioned fields // read as 0. - if (rhs.kind == N_STRUCTLIT) { + if (rhs.kind == nkind.N_STRUCTLIT) { let trefn: *node = rhs.lhs; let sname: str; sname.ptr = nil; sname.len = 0; if (trefn != nil) { - if (trefn.kind == N_IDENT) { sname = trefn.str; } - else { if (trefn.kind == N_TNAME) { sname = trefn.str; }; }; + if (trefn.kind == nkind.N_IDENT) { sname = trefn.str; } + else { if (trefn.kind == nkind.N_TNAME) { sname = trefn.str; }; }; }; let si: *structinfo = structlookup(c, sname); if (si != nil) { @@ -7739,7 +7743,7 @@ fn cglet(c: *cgen, n: *node) void = { }; let fieldnode: *node = rhs.list; for (fieldnode != nil) { - if (fieldnode.kind == N_FIELD) { + if (fieldnode.kind == nkind.N_FIELD) { let fname: str = fieldnode.str; let fi: *fieldinfo = si.fields; for (fi != nil) { @@ -7874,7 +7878,7 @@ fn cgmassign(c: *cgen, n: *node) void = { let l1: *node = nil; if (l0 != nil) { l1 = l0.next; }; if (l0 != nil) { - if (l0.kind == N_IDENT) { + if (l0.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l0.str); if (off != 0) { emitline("\tMOVQ\tAX, "); @@ -7885,7 +7889,7 @@ fn cgmassign(c: *cgen, n: *node) void = { }; emitline("\tPOPQ\tDX\n"); if (l1 != nil) { - if (l1.kind == N_IDENT) { + if (l1.kind == nkind.N_IDENT) { let off: i32 = localfind(c, l1.str); if (off != 0) { emitline("\tMOVQ\tDX, "); @@ -7903,7 +7907,7 @@ fn cgmassign(c: *cgen, n: *node) void = { // type is taken from its explicit annotation (l.lhs) when present // or inferred from the called fn's return-type tuple element. // -// Per the AX:DX:CX return convention (mirrors C cgen N_MLET): +// Per the AX:DX:CX return convention (mirrors C cgen nkind.N_MLET): // (scalar, scalar) — AX → l0, DX → l1. // (scalar, str) — AX → scalar slot, (DX, CX) → str slot // as (.ptr, .len). Position-agnostic — the @@ -7914,17 +7918,17 @@ fn cgmlet(c: *cgen, n: *node) void = { let p0t: *node = nil; let p1t: *node = nil; - if (rhs.kind == N_CALL) { + if (rhs.kind == nkind.N_CALL) { let callee: *node = rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; @@ -8049,7 +8053,7 @@ use strconv; fn scanlocals(c: *cgen, n: *node) i32 = { if (n == nil) { return 0; }; let total: i32 = 0; - if (n.kind == N_LET) { + if (n.kind == nkind.N_LET) { // Match localadd's rounding: < 8 bumps to 8, then 8-align. // scanlocals must agree with localadd or the prologue // SUBQ undersizes the frame and lets overflow into the @@ -8068,21 +8072,21 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // the rhs call's return-tuple element type. Marking via // scanseenmark also dedupes the recursive descent into n.list // so each child isn't counted again at the default 8B. - if (n.kind == N_MLET) { + if (n.kind == nkind.N_MLET) { let p0t: *node = nil; let p1t: *node = nil; if (n.rhs != nil) { - if (n.rhs.kind == N_CALL) { + if (n.rhs.kind == nkind.N_CALL) { let callee: *node = n.rhs.lhs; if (callee != nil) { let cnm: str; cnm.ptr = nil; cnm.len = 0; - if (callee.kind == N_IDENT) { cnm = callee.str; }; - if (callee.kind == N_DOT) { cnm = callee.str; }; + if (callee.kind == nkind.N_IDENT) { cnm = callee.str; }; + if (callee.kind == nkind.N_DOT) { cnm = callee.str; }; if (cnm.len > 0) { let rt: *node = fnretlookup(c, cnm); if (rt != nil) { - if (rt.kind == N_TTUPLE) { + if (rt.kind == nkind.N_TTUPLE) { p0t = rt.list; if (p0t != nil) { p1t = p0t.next; }; }; @@ -8117,7 +8121,7 @@ fn scanlocals(c: *cgen, n: *node) i32 = { // so two separate matches in the same function each allocate // their `v`/`e` slots fresh. Treating these as deduped would // shrink the frame below what localadd then bumps it to. - if (n.kind == N_MCASE) { + if (n.kind == nkind.N_MCASE) { let bn: str = n.str; if (bn.len > 0) { let pat: *node = n.lhs; @@ -8149,7 +8153,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { let p: *node = params; let idx: i32 = 0; for (p != nil) { - if (p.kind == N_PARAM) { + if (p.kind == nkind.N_PARAM) { let nm: str = p.str; if (istaggedtype(p.lhs)) { // tagged-union param: spill size/8 registers @@ -8229,7 +8233,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let isffi: bool = false; let a: *node = fn_.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let an: str = a.str; if (streq(an, "symbol")) { isffi = true; }; }; @@ -8253,7 +8257,7 @@ fn cgfn(c: *cgen, fn_: *node) void = { let scanp: *node = fn_.list; let frame: i32 = 0; for (scanp != nil) { - if (scanp.kind == N_PARAM) { + if (scanp.kind == nkind.N_PARAM) { if (istaggedtype(scanp.lhs)) { frame += 24; } else { if (isslicetype(c, scanp.lhs)) { frame += 24; } else { if (isstrtype(c, scanp.lhs)) { frame += 16; } @@ -8310,7 +8314,7 @@ export fn cgfile(c: *cgen, file: *node) void = { collectmods(c, file); let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.body != nil) { cgfn(c, d); }; @@ -8329,17 +8333,17 @@ export fn cgfile(c: *cgen, file: *node) void = { // then by assembling + linking + running the result. // // Current coverage: -// - decls: N_FILE, N_FNDECL (params, frame for locals, prologue +// - decls: nkind.N_FILE, nkind.N_FNDECL (params, frame for locals, prologue // + dual-epilogue suppression; FFI body-less fn skipped) -// - stmts: N_BLOCK, N_RETURN, N_EXPRSTMT, N_LET (no init), -// N_LET (int-literal / ident / call / N_BIN init), -// N_IF (with optional else), N_FOR (cond-only and full -// init/cond/post), N_BREAK, N_CONTINUE -// - exprs: N_INTLIT, N_IDENT (local/param), N_BIN with full op +// - stmts: nkind.N_BLOCK, nkind.N_RETURN, nkind.N_EXPRSTMT, nkind.N_LET (no init), +// nkind.N_LET (int-literal / ident / call / nkind.N_BIN init), +// nkind.N_IF (with optional else), nkind.N_FOR (cond-only and full +// init/cond/post), nkind.N_BREAK, nkind.N_CONTINUE +// - exprs: nkind.N_INTLIT, nkind.N_IDENT (local/param), nkind.N_BIN with full op // coverage (+/-/*/// %, &/|/^, <>, comparisons with -// signed-vs-unsigned dispatch, &&/||), N_UN (- ! ~ & *), -// N_CALL (recursive R-to-L push, pop into argregs L-to-R), -// N_ASSIGN to local idents (plain and compound +=/-=) +// signed-vs-unsigned dispatch, &&/||), nkind.N_UN (- ! ~ & *), +// nkind.N_CALL (recursive R-to-L push, pop into argregs L-to-R), +// nkind.N_ASSIGN to local idents (plain and compound +=/-=) // // Type info is shallow — frame slots are 8 bytes per local, all loads // /stores are MOVQ. Programs that mix i8/i32/i64 locals work but spill @@ -8365,7 +8369,7 @@ use cgendecl; // // `type error = str;` makes `error` a struct-shape alias. We track // alias→target so isstrtype / isslicetype / structlookup can -// resolve through the chain. Only direct N_TNAME aliases are mapped; +// resolve through the chain. Only direct nkind.N_TNAME aliases are mapped; // `type p = struct {...}` is handled by collectstructs. type aliasent = struct { @@ -8378,10 +8382,10 @@ fn collectaliases(c: *cgen, file: *node) void = { c.aliases = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind != N_TSTRUCT) { + if (body.kind != nkind.N_TSTRUCT) { let a: *aliasent = amalloc(c.a, 32u64): *aliasent; a.aname = d.str; a.target = body; @@ -8414,11 +8418,11 @@ fn aliaslookup(c: *cgen, name: str) *node = { fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (e == nil) { return false; }; let k: i32 = e.kind; - if (k == N_INTLIT) { *out = e.uval; return true; }; - if (k == N_RUNELIT) { *out = e.uval; return true; }; - if (k == N_TRUE) { *out = 1u64; return true; }; - if (k == N_FALSE) { *out = 0u64; return true; }; - if (k == N_IDENT) { + if (k == nkind.N_INTLIT) { *out = e.uval; return true; }; + if (k == nkind.N_RUNELIT) { *out = e.uval; return true; }; + if (k == nkind.N_TRUE) { *out = 1u64; return true; }; + if (k == nkind.N_FALSE) { *out = 0u64; return true; }; + if (k == nkind.N_IDENT) { let m: *enummember = prev; for (m != nil) { if (streq(m.mname, e.str)) { @@ -8429,7 +8433,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { }; return false; }; - if (k == N_BIN) { + if (k == nkind.N_BIN) { let a: u64; let b: u64; if (!enumevalmember(prev, e.lhs, &a)) { return false; }; @@ -8453,7 +8457,7 @@ fn enumevalmember(prev: *enummember, e: *node, out: *u64) bool = { if (op == tkind.TK_RSHIFT) { *out = a >> b; return true; }; return false; }; - if (k == N_UN) { + if (k == nkind.N_UN) { let v: u64; if (!enumevalmember(prev, e.lhs, &v)) { return false; }; let op: i32 = e.op; @@ -8469,10 +8473,10 @@ fn collectenums(c: *cgen, file: *node) void = { c.enums = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { let body: *node = d.lhs; if (body != nil) { - if (body.kind == N_TENUM) { + if (body.kind == nkind.N_TENUM) { let et: *enumtype = amalloc(c.a, 48u64): *enumtype; et.ename = d.str; et.storage = body.lhs; @@ -8550,7 +8554,7 @@ fn resolvetype(c: *cgen, t: *node) *node = { let depth: i32 = 0; for (depth < 16) { if (cur == nil) { return nil; }; - if (cur.kind != N_TNAME) { return cur; }; + if (cur.kind != nkind.N_TNAME) { return cur; }; let nm: str = cur.str; let next: *node = aliaslookup(c, nm); if (next == nil) { return cur; }; @@ -8563,8 +8567,8 @@ fn resolvetype(c: *cgen, t: *node) *node = { // ---- struct registry ------------------------------------------------ // // Per-file map from struct name → list of fields with computed offsets -// and sizes. Built when cgfile walks N_TYPEDECL with N_TSTRUCT lhs. -// N_DOT and N_ASSIGN consult this to resolve `s.field` for struct or +// and sizes. Built when cgfile walks nkind.N_TYPEDECL with nkind.N_TSTRUCT lhs. +// nkind.N_DOT and nkind.N_ASSIGN consult this to resolve `s.field` for struct or // *struct bases. type fieldinfo = struct { @@ -8587,12 +8591,12 @@ type structinfo = struct { type local = struct { name: str, off: i32, - tnode: *node, // declared type expr (N_TNAME / N_TPTR / ...) or nil + tnode: *node, // declared type expr (nkind.N_TNAME / nkind.N_TPTR / ...) or nil lnext: *local, }; // strlit — interned string literal record. Emitted as a DATA directive -// after all functions; cgexpr N_STRLIT loads (LEAQ ptr, MOVQ len). +// after all functions; cgexpr nkind.N_STRLIT loads (LEAQ ptr, MOVQ len). type strlit = struct { label: str, // "_S_" bytes: str, @@ -8676,7 +8680,7 @@ fn cgeninit(c: *cgen, a: *arena) void = { // match-arm bindings, which C cgen allocates via cgexpr's by-value // `locals` list — so two separate matches each get fresh slots even // when their bind names collide. scanlocals follows the same rule -// for N_MCASE. +// for nkind.N_MCASE. fn localalloc(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { let asz: i32 = sz; if (asz < 8) { asz = 8; }; @@ -8704,7 +8708,7 @@ fn localadd(c: *cgen, name: str, sz: i32, tnode: *node) i32 = { // // On a dedup hit we also overwrite the stored tnode to match // the new declaration's type. C reads `n->lhs->type` (filled - // by the checker) at every N_DOT/N_CAST site; we read + // by the checker) at every nkind.N_DOT/nkind.N_CAST site; we read // `lc.tnode`, so it must follow source order. Without this, // a later `let m: *node` inside a branch keeps an earlier // `let m: i32`'s tnode and `m.next` falls into the SB fallback. @@ -8876,16 +8880,16 @@ fn internstrlit(c: *cgen, bytes: str) str = { fn emitdefconstants(c: *cgen, file: *node) void = { let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let r: *node = d.rhs; let v: u64 = 0u64; let ok: bool = false; if (r != nil) { - if (r.kind == N_INTLIT) { v = r.uval; ok = true; }; - if (r.kind == N_RUNELIT) { v = r.uval; ok = true; }; - if (r.kind == N_TRUE) { v = 1u64; ok = true; }; - if (r.kind == N_FALSE) { v = 0u64; ok = true; }; - if (r.kind == N_NIL) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_INTLIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_RUNELIT) { v = r.uval; ok = true; }; + if (r.kind == nkind.N_TRUE) { v = 1u64; ok = true; }; + if (r.kind == nkind.N_FALSE) { v = 0u64; ok = true; }; + if (r.kind == nkind.N_NIL) { v = 0u64; ok = true; }; }; if (ok) { emitline("DATA "); @@ -9015,7 +9019,7 @@ fn collectfnrets(c: *cgen, file: *node) void = { c.fnrets = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let f: *fnret = amalloc(c.a, 32u64): *fnret; f.fname = d.str; f.rtype = d.lhs; @@ -9040,7 +9044,7 @@ fn fnretlookup(c: *cgen, name: str) *node = { // // `def NAME: T = LIT;` becomes a DATA symbol the C-side w6c emits; an // ident reference loads it via `MOVQ NAME(SB), AX`. We collect them at -// file load and consult on N_IDENT lookup. +// file load and consult on nkind.N_IDENT lookup. type defent = struct { dname: str, @@ -9052,7 +9056,7 @@ fn collectdefs(c: *cgen, file: *node) void = { c.defs = nil; let d: *node = file.list; for (d != nil) { - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { let e: *defent = amalloc(c.a, 32u64): *defent; e.dname = d.str; e.drhs = d.rhs; @@ -9108,7 +9112,7 @@ fn collectmods(c: *cgen, file: *node) void = { // Mirror collectfnrets' shape exactly (plain prepend in one // branch). Earlier nested-if/early-return variants tickled a // wwstage cgen bug that dropped most prepends. - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { if (d.exported == 0) { if (d.module.len > 0) { if (!streq(d.str, "main")) { @@ -9121,7 +9125,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_DEF) { + if (d.kind == nkind.N_DEF) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9132,7 +9136,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_TYPEDECL) { + if (d.kind == nkind.N_TYPEDECL) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9143,7 +9147,7 @@ fn collectmods(c: *cgen, file: *node) void = { }; }; }; - if (d.kind == N_LET) { + if (d.kind == nkind.N_LET) { if (d.exported == 0) { if (d.module.len > 0) { let m: *modent = amalloc(c.a, 48u64): *modent; @@ -9196,15 +9200,15 @@ fn fficollect(c: *cgen, file: *node) void = { if (file == nil) { return; }; let d: *node = file.list; for (d != nil) { - if (d.kind == N_FNDECL) { + if (d.kind == nkind.N_FNDECL) { let a: *node = d.attr; for (a != nil) { - if (a.kind == N_ATTR) { + if (a.kind == nkind.N_ATTR) { let aname: str = a.str; if (streq(aname, "symbol")) { let symnode: *node = a.list; if (symnode != nil) { - if (symnode.kind == N_STRLIT) { + if (symnode.kind == nkind.N_STRLIT) { let f: *ffi = amalloc(c.a, 48u64): *ffi; f.ident = d.str; f.symbol = symnode.str;