diff --git a/lib/ww/ast.ww b/lib/ww/ast.ww index 8bbd5302..a09956fc 100644 --- a/lib/ww/ast.ww +++ b/lib/ww/ast.ww @@ -11,7 +11,6 @@ package ww; import os; import strconv; -import mem; import tok; // ---- Nkind ------------------------------------------------------------ @@ -127,7 +126,7 @@ type node = struct { nmod: str, // originating module from `// MODULE: foo`; "" if none }; -export fn newnode(a: *arena, k: nkind, file: str, line: i32, col: i32) *node = { +export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = { // fval cast-init: 990's wwdump TK_FLOAT diff requires this file // to tokenise identically through C and ww (lex.ww:382 has the // same workaround for the cstage %g-formats vs ww-skips divergence). diff --git a/lib/ww/lex/lex.ww b/lib/ww/lex/lex.ww index 641f7c9d..f1894b0f 100644 --- a/lib/ww/lex/lex.ww +++ b/lib/ww/lex/lex.ww @@ -17,7 +17,6 @@ package lex; // callers `import lex;` (which dir-enums lib/ww/lex/). import os; import ascii; -import mem; import strings; // isidstart / isidpart — identifier classification. Lexer-local @@ -55,18 +54,16 @@ type lex = struct { lpos: u64, line: i32, col: i32, - a: *arena, errs: i32, }; -export fn lexinit(l: *lex, a: *arena, file: str, src: *u8, len: u64) void = { +export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.file = file; l.src = src; l.srclen = len; l.lpos = 0u64; l.line = 1; l.col = 1; - l.a = a; l.errs = 0; }; diff --git a/lib/ww/parse/decl.ww b/lib/ww/parse/decl.ww index ea57b5b6..b067dbee 100644 --- a/lib/ww/parse/decl.ww +++ b/lib/ww/parse/decl.ww @@ -3,7 +3,6 @@ package parse; import os; -import mem; import tok; // `import encoding.utf8;` — the driver resolves the dotted path to @@ -16,7 +15,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, nkind.N_USE, pf, pl, pc); + let n: *node = newnode(nkind.N_USE, pf, pl, pc); n.nmod = p.curmod; let leaf: str; expectident(p, &leaf); @@ -34,7 +33,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, nkind.N_DEF, pf, pl, pc); + let n: *node = newnode(nkind.N_DEF, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -57,7 +56,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, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); n.nmod = p.curmod; let id: str; expectbindname(p, &id); @@ -82,7 +81,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); + let a: *node = newnode(nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -108,7 +107,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, nkind.N_PARAM, pf, pl, pc); + let n: *node = newnode(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; @@ -138,7 +137,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, nkind.N_FNDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_FNDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -168,7 +167,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, nkind.N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); diff --git a/lib/ww/parse/expr.ww b/lib/ww/parse/expr.ww index 5dc60181..0cc1e0ea 100644 --- a/lib/ww/parse/expr.ww +++ b/lib/ww/parse/expr.ww @@ -3,7 +3,6 @@ package parse; import os; -import mem; import tok; // streqlocal — str-to-str compare. Inlined here to avoid a cross- @@ -24,7 +23,7 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; // Plumb the typed-int suffix (`42i64`, `3u8`) through to @@ -38,7 +37,7 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_FLOAT) { - let n: *node = newnode(p.a, nkind.N_FLOATLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_FLOATLIT, pf, pl, pc); n.fval = p.curfval; // uval carries the IEEE 754 bit pattern — the lexer sets // both, and cgen consumers prefer the integer view so they @@ -50,32 +49,32 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_RUNELIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRUE, pf, pl, pc); + return newnode(nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, nkind.N_FALSE, pf, pl, pc); + return newnode(nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, nkind.N_NIL, pf, pl, pc); + return newnode(nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); + return newnode(nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT @@ -83,14 +82,14 @@ fn parseprimary(p: *parser) *node = { // already 0); the checker rejects it outside lvalue // positions. advance(p); - return newnode(p.a, nkind.N_IDENT, pf, pl, pc); + return newnode(nkind.N_IDENT, pf, pl, pc); }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). // 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, nkind.N_ARRLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -99,7 +98,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, nkind.N_FIELD, + let rep: *node = newnode(nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -117,7 +116,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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -134,7 +133,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); + let n: *node = newnode(nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -145,7 +144,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, nkind.N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -165,7 +164,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, nkind.N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -182,7 +181,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, nkind.N_MATCH, pf, pl, pc); + let m: *node = newnode(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"); @@ -193,7 +192,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, nkind.N_MCASE, cf, cl, cc); + let mc: *node = newnode(nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -215,7 +214,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, nkind.N_NONE, pf, pl, pc); + return newnode(nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { @@ -229,7 +228,7 @@ fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { // marker the callee/builtin can iterate over. Mirrors // cmd/wcc/parse.c. The only consumer today is `append`. if (accepttok(p, tkind.TK_ELLIPSIS)) { - let sp: *node = newnode(p.a, nkind.N_SPREAD, e.file, e.line, e.col); + let sp: *node = newnode(nkind.N_SPREAD, e.file, e.line, e.col); sp.lhs = e; e = sp; }; @@ -249,7 +248,7 @@ 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, nkind.N_CALL, pf, pl, pc); + let n: *node = newnode(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. @@ -274,7 +273,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -291,7 +290,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -301,7 +300,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); + let n: *node = newnode(nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -310,7 +309,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); + let n: *node = newnode(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 @@ -331,7 +330,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); + let n: *node = newnode(nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -343,7 +342,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, nkind.N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -351,7 +350,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -361,14 +360,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, nkind.N_TRYPROP, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRYUNW, pf, pl, pc); + let n: *node = newnode(nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -385,37 +384,37 @@ fn parseunary(p: *parser) *node = { let k: tkind = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -439,7 +438,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, nkind.N_BIN, pf, pl, pc); + let n: *node = newnode(nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -454,7 +453,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: tkind = p.curkind; advance(p); - let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); + let n: *node = newnode(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 8b8614e2..11891ae2 100644 --- a/lib/ww/parse/parse.ww +++ b/lib/ww/parse/parse.ww @@ -16,12 +16,10 @@ package parse; // dir-enum when callers `import parse;` (which dir-enums // lib/ww/parse/). import os; -import mem; import tok; type parser = struct { l: *lex, - a: *arena, errs: i32, // nocast: while inside `[...]` we treat ':' as the slice // separator, not the cast operator. Mirrors parse.c's flag. @@ -60,9 +58,8 @@ fn refill(p: *parser) void = { p.curtsuffix = t.tsuffix; }; -export fn parserinit(p: *parser, a: *arena, l: *lex) void = { +export fn parserinit(p: *parser, l: *lex) void = { p.l = l; - p.a = a; p.errs = 0; p.nocast = 0; refill(p); @@ -120,10 +117,10 @@ fn expectbindname(p: *parser, into: *str) bool = { // Other forms (slice, array, struct, fn, chan, tuple, tagged) will // land in subsequent commits. -// joindotted — arena-build "head.tail" for dotted type-name path +// joindotted — build "head.tail" for dotted type-name path // collapse. Mirrors aprintf in C parser; pulled local to avoid a // cross-module dependency. -fn joindotted(a: *arena, head: str, tail: str) str = { +fn joindotted(head: str, tail: str) str = { let n: u64 = head.len: u64 + 1u64 + tail.len: u64; let buf: []u8 = alloc([], n + 1u64)!; let i: u64 = 0u64; @@ -148,14 +145,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, nkind.N_TBANG, pf, pl, pc); + let n: *node = newnode(nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); + let n: *node = newnode(nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -164,11 +161,11 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); + let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil // as the sentinel; the cgen path for nkind.N_LET fills it from the // array literal's element count. @@ -185,7 +182,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, nkind.N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -193,7 +190,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, nkind.N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -214,7 +211,7 @@ fn parsetype(p: *parser) *node = { // nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil // (auto-increment when omitted). advance(p); - let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); + let n: *node = newnode(nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -226,7 +223,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, nkind.N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -245,14 +242,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_VOID) { // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -260,7 +257,7 @@ fn parsetype(p: *parser) *node = { for (p.curkind == tkind.TK_DOT) { advance(p); if (p.curkind != tkind.TK_IDENT) { break; }; - acc = joindotted(p.a, acc, p.curtext); + acc = joindotted(acc, p.curtext); advance(p); }; n.str = acc; @@ -280,7 +277,7 @@ fn parsetype(p: *parser) *node = { let first: *node = parsetype(p); if (firstspread) { first.op = tkind.TK_ELLIPSIS; }; if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); + let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -302,7 +299,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); + let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -320,7 +317,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, nkind.N_TFN, pf, pl, pc); + let n: *node = newnode(nkind.N_TFN, pf, pl, pc); // Anonymous-or-named params: parseparams handles named only; // for fn-type expressions the C parser allows IDENT-less // (anonymous) params. Stub: only named params for now. @@ -332,7 +329,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, nkind.N_TNAME, pf, pl, pc); + return newnode(nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -383,7 +380,7 @@ fn isassignop(k: tkind) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_EOF) { diff --git a/lib/ww/parse/stmt.ww b/lib/ww/parse/stmt.ww index a1d75d5e..da4c0078 100644 --- a/lib/ww/parse/stmt.ww +++ b/lib/ww/parse/stmt.ww @@ -3,7 +3,6 @@ package parse; import os; -import mem; import tok; fn parseletlocal(p: *parser) *node = { @@ -20,14 +19,14 @@ fn parseletlocal(p: *parser) *node = { // doesn't allow types here, but cmd/wcc/parse.c does). if (p.curkind == tkind.TK_LPAREN) { advance(p); - let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(nkind.N_MLET, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (true) { let lpf: str = p.curfile; let lpl: i32 = p.curline; let lpc: i32 = p.curcol; - let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -50,7 +49,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -61,14 +60,14 @@ fn parseletlocal(p: *parser) *node = { // Collects (name, type) pairs, then '=' rhs. Each binding gets // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(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, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -100,7 +99,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, nkind.N_BLOCK, pf, pl, pc); + let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -122,7 +121,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, nkind.N_IF, pf, pl, pc); + let n: *node = newnode(nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -162,7 +161,7 @@ fn parsefor(p: *parser) *node = { let npf: str = p.curfile; let npl: i32 = p.curline; let npc: i32 = p.curcol; - let e: *node = newnode(p.a, nkind.N_IDENT, npf, npl, npc); + let e: *node = newnode(nkind.N_IDENT, npf, npl, npc); let nm: str; expectbindname(p, &nm); e.str = nm; @@ -173,7 +172,7 @@ fn parsefor(p: *parser) *node = { }; expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names"); expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names"); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.list = names; rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -198,7 +197,7 @@ fn parsefor(p: *parser) *node = { if (p.curkind == tkind.TK_DOTDOT) { advance(p); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.str = nm; // "" for `_` rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -209,12 +208,12 @@ fn parsefor(p: *parser) *node = { // Not a range — finish the let manually and continue as // a 3-clause for-init. - let first: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc); first.str = nm; if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); }; if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); }; expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let"); - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); n.lhs = first; n.cond = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after for cond"); @@ -229,7 +228,7 @@ fn parsefor(p: *parser) *node = { }; // for (cond) or for (cond; post) - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); let first: *node = parseexpr(p); if (accepttok(p, tkind.TK_SEMI)) { n.cond = first; @@ -253,7 +252,7 @@ fn parseswitch(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `switch` expecttok(p, tkind.TK_LPAREN, "expected '(' after switch"); - let n: *node = newnode(p.a, nkind.N_SWITCH, pf, pl, pc); + let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body"); @@ -264,7 +263,7 @@ fn parseswitch(p: *parser) *node = { let cpl: i32 = p.curline; let cpc: i32 = p.curcol; advance(p); // past `case` - let cs: *node = newnode(p.a, nkind.N_CASE, cpf, cpl, cpc); + let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc); let eh: *node = nil; let et: *node = nil; if (p.curkind != tkind.TK_COLON) { @@ -292,7 +291,7 @@ fn parseswitch(p: *parser) *node = { bt = s; }; }; - let blk: *node = newnode(p.a, nkind.N_BLOCK, cpf, cpl, cpc); + let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc); blk.list = bh; cs.body = blk; if (head == nil) { head = cs; } @@ -337,13 +336,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -361,14 +360,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, nkind.N_DEFER, pf, pl, pc); + let n: *node = newnode(nkind.N_DEFER, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after defer"); return n; }; if (p.curkind == tkind.TK_YIELD) { advance(p); - let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); + let n: *node = newnode(nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -376,12 +375,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, nkind.N_BREAK, pf, pl, pc); + return newnode(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, nkind.N_CONTINUE, pf, pl, pc); + return newnode(nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -391,7 +390,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, nkind.N_MASSIGN, pf, pl, pc); + let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -406,7 +405,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; diff --git a/lib/ww/sym.ww b/lib/ww/sym.ww index 8583f8f6..35c6499b 100644 --- a/lib/ww/sym.ww +++ b/lib/ww/sym.ww @@ -6,10 +6,6 @@ package ww; -// Sibling imports (typ, ast) auto-resolve via task #22 dir-enum -// when callers `import ww;` or pull all three separately. -import mem; - // Symbol kinds — must stay numerically aligned with cmd/wcc/ww.h Skind. type skind = enum i32 { SK_NONE = 0, @@ -47,7 +43,6 @@ type scope = struct { last: *sym, buckets: **sym, // length = NBUCKETS nbuckets: i32, - a: *arena, }; // FNV-1a 64 — same hash the C side uses, so bucket distribution is @@ -64,9 +59,9 @@ fn hashstr(s: str) u64 = { return h; }; -export fn newscope(a: *arena, parent: *scope) *scope = { +export fn newscope(parent: *scope) *scope = { let buckets_sl: []*sym = alloc([], NBUCKETS: u64)!; - let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS, a=a})!; + let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS})!; return s; }; diff --git a/lib/ww/typ.ww b/lib/ww/typ.ww index 388525fc..ff6d4319 100644 --- a/lib/ww/typ.ww +++ b/lib/ww/typ.ww @@ -4,12 +4,11 @@ // the primitive types (tyvoid, tyi32, …); ww doesn't have writable // global storage yet, so we bundle the primitives into a `tctx` that // the checker passes around explicitly. typesinit fills the tctx -// once per arena. +// once per program. package ww; import os; -import mem; // ---- TypeKind --------------------------------------------------------- // Numeric values must stay aligned with cmd/wcc/ww.h TypeKind so the @@ -118,7 +117,6 @@ type tinfocacheent = struct { // ---- tctx — the box of primitive types ------------------------------- type tctx = struct { - a: *arena, tyvoid: *tinfo, tybool: *tinfo, tyrune: *tinfo, @@ -149,13 +147,13 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- -export fn newtype(a: *arena, k: tykind) *tinfo = { +export fn newtype(k: tykind) *tinfo = { let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; -fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { - let t: *tinfo = newtype(a, k); +fn prim(k: tykind, nm: str, sz: u64, al: u64) *tinfo = { + let t: *tinfo = newtype(k); t.name = nm; t.size = sz; if (al > 0u64) { t.align = al; } else { t.align = sz; }; @@ -163,38 +161,37 @@ fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { return t; }; -export fn typesinit(c: *tctx, a: *arena) void = { - c.a = a; - c.tyvoid = prim(a, tykind.TY_VOID, "void", 0u64, 1u64); - c.tybool = prim(a, tykind.TY_BOOL, "bool", 1u64, 1u64); - c.tyrune = prim(a, tykind.TY_RUNE, "rune", 4u64, 4u64); - c.tyi8 = prim(a, tykind.TY_I8, "i8", 1u64, 1u64); - c.tyi16 = prim(a, tykind.TY_I16, "i16", 2u64, 2u64); - c.tyi32 = prim(a, tykind.TY_I32, "i32", 4u64, 4u64); - c.tyi64 = prim(a, tykind.TY_I64, "i64", 8u64, 8u64); - c.tyu8 = prim(a, tykind.TY_U8, "u8", 1u64, 1u64); - c.tyu16 = prim(a, tykind.TY_U16, "u16", 2u64, 2u64); - c.tyu32 = prim(a, tykind.TY_U32, "u32", 4u64, 4u64); - c.tyu64 = prim(a, tykind.TY_U64, "u64", 8u64, 8u64); - c.tyint = prim(a, tykind.TY_INT, "int", 8u64, 8u64); - c.tyuint = prim(a, tykind.TY_UINT, "uint", 8u64, 8u64); - c.tyuintptr= prim(a, tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); - c.tyf32 = prim(a, tykind.TY_F32, "f32", 4u64, 4u64); - c.tyf64 = prim(a, tykind.TY_F64, "f64", 8u64, 8u64); - c.tystr = prim(a, tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) - c.tyerr = prim(a, tykind.TY_ERR, "", 0u64, 1u64); - c.tynever = prim(a, tykind.TY_NEVER, "never", 0u64, 1u64); +export fn typesinit(c: *tctx) void = { + c.tyvoid = prim(tykind.TY_VOID, "void", 0u64, 1u64); + c.tybool = prim(tykind.TY_BOOL, "bool", 1u64, 1u64); + c.tyrune = prim(tykind.TY_RUNE, "rune", 4u64, 4u64); + c.tyi8 = prim(tykind.TY_I8, "i8", 1u64, 1u64); + c.tyi16 = prim(tykind.TY_I16, "i16", 2u64, 2u64); + c.tyi32 = prim(tykind.TY_I32, "i32", 4u64, 4u64); + c.tyi64 = prim(tykind.TY_I64, "i64", 8u64, 8u64); + c.tyu8 = prim(tykind.TY_U8, "u8", 1u64, 1u64); + c.tyu16 = prim(tykind.TY_U16, "u16", 2u64, 2u64); + c.tyu32 = prim(tykind.TY_U32, "u32", 4u64, 4u64); + c.tyu64 = prim(tykind.TY_U64, "u64", 8u64, 8u64); + c.tyint = prim(tykind.TY_INT, "int", 8u64, 8u64); + c.tyuint = prim(tykind.TY_UINT, "uint", 8u64, 8u64); + c.tyuintptr= prim(tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); + c.tyf32 = prim(tykind.TY_F32, "f32", 4u64, 4u64); + c.tyf64 = prim(tykind.TY_F64, "f64", 8u64, 8u64); + c.tystr = prim(tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) + c.tyerr = prim(tykind.TY_ERR, "", 0u64, 1u64); + c.tynever = prim(tykind.TY_NEVER, "never", 0u64, 1u64); - c.tyuntypedint = prim(a, tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); - c.tyuntypedfloat = prim(a, tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); - c.tyuntypedstr = prim(a, tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); - c.tyuntypedrune = prim(a, tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); - c.tyuntypedbool = prim(a, tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); - c.tyuntypednil = prim(a, tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); + c.tyuntypedint = prim(tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); + c.tyuntypedfloat = prim(tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); + c.tyuntypedstr = prim(tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); + c.tyuntypedrune = prim(tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); + c.tyuntypedbool = prim(tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); + c.tyuntypednil = prim(tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); }; -export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_PTR); +export fn typeptr(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_PTR); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -202,8 +199,8 @@ export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_SLICE); +export fn typeslice(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_SLICE); t.sub = sub; t.size = 24u64; // sizelint-ok: SSoT for slice header (#64) t.align = 8u64; @@ -211,8 +208,8 @@ export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_ARRAY); +export fn typearray(sub: *tinfo, n: u64) *tinfo = { + let t: *tinfo = newtype(tykind.TY_ARRAY); t.sub = sub; t.alen = n; if (sub != nil) { @@ -229,8 +226,8 @@ export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { return t; }; -export fn typechan(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_CHAN); +export fn typechan(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_CHAN); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -238,8 +235,8 @@ export fn typechan(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typenamed(a: *arena, name: str, under: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_NAMED); +export fn typenamed(name: str, under: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_NAMED); t.name = name; t.under = under; if (under != nil) { diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index e692b444..f0cfb906 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -750,98 +750,6 @@ package rt; // a future task (task #39). ref/hare/rt/malloc.ha:27. @symbol("rt_malloc") export fn malloc(n: u64) *void; -// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. -// -// Bump arena allocator. Backed by the runtime page allocator -// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the -// current chunk runs out we link a fresh one. Freeing the arena -// unmaps the chain. -// -// Memory handed out is 16-byte aligned. The C version under -// cmd/wcc/ is retained until the three-stage bootstrap diffs clean. - -package wcc; - -import os; -import rt; - -def ALIGN: u64 = 16u64; -def INIT_CHUNK: u64 = 65536u64; -def MAX_CHUNK: u64 = 4194304u64; -def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below - -type arena = struct { - buf: *u8, - off: u64, - cap: u64, - next: *arena, - total: u64, -}; - -fn roundup(n: u64, a: u64) u64 = { - return (n + a - 1u64) & ~(a - 1u64); -}; - -export fn newarena() *arena = { - let a: *arena = rt.malloc(ARENA_SZ): *arena; - a.buf = rt.malloc(INIT_CHUNK): *u8; - a.off = 0u64; - a.cap = INIT_CHUNK; - a.next = nil; - a.total = 0u64; - return a; -}; - -// Grow: link a fresh chunk in front of the head. We push the old -// chunk into `next` so the head always describes the current bump -// region. Chunk size doubles up to MAX_CHUNK. -fn grow(a: *arena, need: u64) bool = { - let want: u64 = a.cap * 2u64; - if (want < need) { want = need; }; - if (want > MAX_CHUNK) { want = MAX_CHUNK; }; - if (want < need) { return false; }; // single allocation too big - - let old: *arena = rt.malloc(ARENA_SZ): *arena; - old.buf = a.buf; - old.off = a.off; - old.cap = a.cap; - old.next = a.next; - old.total = 0u64; - - a.buf = rt.malloc(want): *u8; - a.off = 0u64; - a.cap = want; - a.next = old; - return true; -}; - -export fn amalloc(a: *arena, n: u64) *void = { - let need: u64 = roundup(n, ALIGN); - if (need > a.cap - a.off) { - if (!grow(a, need)) { return nil; }; - }; - let p: *u8 = a.buf + a.off; - a.off += need; - a.total += need; - // Zero the region. Plan 9 amalloc zeroes; we mirror that here so - // the checker can assume freshly allocated nodes start at 0. - let i: u64 = 0u64; - for (i < need) { - p[i] = 0u8; - i += 1u64; - }; - return p: *void; -}; - -export fn freearena(a: *arena) void = { - for (a != nil) { - let next: *arena = a.next; - os.free(a.buf: *void, a.cap); - os.free(a: *void, ARENA_SZ); - a = next; - }; -}; - // types — integer limits. Mirrors Hare's types::limits (I8_MAX, …) // platform-fixed for amd64. Numeric helpers live in lib/math, matching // Hare's split between types::limits and math::. @@ -3711,7 +3619,6 @@ package lex; // callers `import lex;` (which dir-enums lib/ww/lex/). import os; import ascii; -import mem; import strings; // isidstart / isidpart — identifier classification. Lexer-local @@ -3749,18 +3656,16 @@ type lex = struct { lpos: u64, line: i32, col: i32, - a: *arena, errs: i32, }; -export fn lexinit(l: *lex, a: *arena, file: str, src: *u8, len: u64) void = { +export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.file = file; l.src = src; l.srclen = len; l.lpos = 0u64; l.line = 1; l.col = 1; - l.a = a; l.errs = 0; }; @@ -4526,7 +4431,6 @@ package ww; import os; import strconv; -import mem; import tok; // ---- Nkind ------------------------------------------------------------ @@ -4642,7 +4546,7 @@ type node = struct { nmod: str, // originating module from `// MODULE: foo`; "" if none }; -export fn newnode(a: *arena, k: nkind, file: str, line: i32, col: i32) *node = { +export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = { // fval cast-init: 990's wwdump TK_FLOAT diff requires this file // to tokenise identically through C and ww (lex.ww:382 has the // same workaround for the cstage %g-formats vs ww-skips divergence). @@ -4876,7 +4780,6 @@ export fn astprint(fd: i32, n: *node) void = { package parse; import os; -import mem; import tok; // `import encoding.utf8;` — the driver resolves the dotted path to @@ -4889,7 +4792,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, nkind.N_USE, pf, pl, pc); + let n: *node = newnode(nkind.N_USE, pf, pl, pc); n.nmod = p.curmod; let leaf: str; expectident(p, &leaf); @@ -4907,7 +4810,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, nkind.N_DEF, pf, pl, pc); + let n: *node = newnode(nkind.N_DEF, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -4930,7 +4833,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, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); n.nmod = p.curmod; let id: str; expectbindname(p, &id); @@ -4955,7 +4858,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); + let a: *node = newnode(nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -4981,7 +4884,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, nkind.N_PARAM, pf, pl, pc); + let n: *node = newnode(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; @@ -5011,7 +4914,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, nkind.N_FNDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_FNDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -5041,7 +4944,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, nkind.N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -5059,7 +4962,6 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { package parse; import os; -import mem; import tok; // streqlocal — str-to-str compare. Inlined here to avoid a cross- @@ -5080,7 +4982,7 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; // Plumb the typed-int suffix (`42i64`, `3u8`) through to @@ -5094,7 +4996,7 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_FLOAT) { - let n: *node = newnode(p.a, nkind.N_FLOATLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_FLOATLIT, pf, pl, pc); n.fval = p.curfval; // uval carries the IEEE 754 bit pattern — the lexer sets // both, and cgen consumers prefer the integer view so they @@ -5106,32 +5008,32 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_RUNELIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRUE, pf, pl, pc); + return newnode(nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, nkind.N_FALSE, pf, pl, pc); + return newnode(nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, nkind.N_NIL, pf, pl, pc); + return newnode(nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); + return newnode(nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT @@ -5139,14 +5041,14 @@ fn parseprimary(p: *parser) *node = { // already 0); the checker rejects it outside lvalue // positions. advance(p); - return newnode(p.a, nkind.N_IDENT, pf, pl, pc); + return newnode(nkind.N_IDENT, pf, pl, pc); }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). // 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, nkind.N_ARRLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -5155,7 +5057,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, nkind.N_FIELD, + let rep: *node = newnode(nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -5173,7 +5075,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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -5190,7 +5092,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); + let n: *node = newnode(nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -5201,7 +5103,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, nkind.N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -5221,7 +5123,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, nkind.N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -5238,7 +5140,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, nkind.N_MATCH, pf, pl, pc); + let m: *node = newnode(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"); @@ -5249,7 +5151,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, nkind.N_MCASE, cf, cl, cc); + let mc: *node = newnode(nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -5271,7 +5173,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, nkind.N_NONE, pf, pl, pc); + return newnode(nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { @@ -5285,7 +5187,7 @@ fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { // marker the callee/builtin can iterate over. Mirrors // cmd/wcc/parse.c. The only consumer today is `append`. if (accepttok(p, tkind.TK_ELLIPSIS)) { - let sp: *node = newnode(p.a, nkind.N_SPREAD, e.file, e.line, e.col); + let sp: *node = newnode(nkind.N_SPREAD, e.file, e.line, e.col); sp.lhs = e; e = sp; }; @@ -5305,7 +5207,7 @@ 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, nkind.N_CALL, pf, pl, pc); + let n: *node = newnode(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. @@ -5330,7 +5232,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -5347,7 +5249,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -5357,7 +5259,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); + let n: *node = newnode(nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -5366,7 +5268,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); + let n: *node = newnode(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 @@ -5387,7 +5289,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); + let n: *node = newnode(nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5399,7 +5301,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, nkind.N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5407,7 +5309,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5417,14 +5319,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, nkind.N_TRYPROP, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRYUNW, pf, pl, pc); + let n: *node = newnode(nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -5441,37 +5343,37 @@ fn parseunary(p: *parser) *node = { let k: tkind = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -5495,7 +5397,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, nkind.N_BIN, pf, pl, pc); + let n: *node = newnode(nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -5510,7 +5412,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: tkind = p.curkind; advance(p); - let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); + let n: *node = newnode(nkind.N_ASSIGN, pf, pl, pc); n.op = op; n.lhs = e; n.rhs = parseexpr(p); // right-associative @@ -5538,12 +5440,10 @@ package parse; // dir-enum when callers `import parse;` (which dir-enums // lib/ww/parse/). import os; -import mem; import tok; type parser = struct { l: *lex, - a: *arena, errs: i32, // nocast: while inside `[...]` we treat ':' as the slice // separator, not the cast operator. Mirrors parse.c's flag. @@ -5582,9 +5482,8 @@ fn refill(p: *parser) void = { p.curtsuffix = t.tsuffix; }; -export fn parserinit(p: *parser, a: *arena, l: *lex) void = { +export fn parserinit(p: *parser, l: *lex) void = { p.l = l; - p.a = a; p.errs = 0; p.nocast = 0; refill(p); @@ -5642,10 +5541,10 @@ fn expectbindname(p: *parser, into: *str) bool = { // Other forms (slice, array, struct, fn, chan, tuple, tagged) will // land in subsequent commits. -// joindotted — arena-build "head.tail" for dotted type-name path +// joindotted — build "head.tail" for dotted type-name path // collapse. Mirrors aprintf in C parser; pulled local to avoid a // cross-module dependency. -fn joindotted(a: *arena, head: str, tail: str) str = { +fn joindotted(head: str, tail: str) str = { let n: u64 = head.len: u64 + 1u64 + tail.len: u64; let buf: []u8 = alloc([], n + 1u64)!; let i: u64 = 0u64; @@ -5670,14 +5569,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, nkind.N_TBANG, pf, pl, pc); + let n: *node = newnode(nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); + let n: *node = newnode(nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -5686,11 +5585,11 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); + let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil // as the sentinel; the cgen path for nkind.N_LET fills it from the // array literal's element count. @@ -5707,7 +5606,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, nkind.N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -5715,7 +5614,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, nkind.N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -5736,7 +5635,7 @@ fn parsetype(p: *parser) *node = { // nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil // (auto-increment when omitted). advance(p); - let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); + let n: *node = newnode(nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -5748,7 +5647,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, nkind.N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -5767,14 +5666,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_VOID) { // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -5782,7 +5681,7 @@ fn parsetype(p: *parser) *node = { for (p.curkind == tkind.TK_DOT) { advance(p); if (p.curkind != tkind.TK_IDENT) { break; }; - acc = joindotted(p.a, acc, p.curtext); + acc = joindotted(acc, p.curtext); advance(p); }; n.str = acc; @@ -5802,7 +5701,7 @@ fn parsetype(p: *parser) *node = { let first: *node = parsetype(p); if (firstspread) { first.op = tkind.TK_ELLIPSIS; }; if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); + let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -5824,7 +5723,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); + let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -5842,7 +5741,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, nkind.N_TFN, pf, pl, pc); + let n: *node = newnode(nkind.N_TFN, pf, pl, pc); // Anonymous-or-named params: parseparams handles named only; // for fn-type expressions the C parser allows IDENT-less // (anonymous) params. Stub: only named params for now. @@ -5854,7 +5753,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, nkind.N_TNAME, pf, pl, pc); + return newnode(nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -5905,7 +5804,7 @@ fn isassignop(k: tkind) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_EOF) { @@ -5988,7 +5887,6 @@ export fn parsefile(p: *parser) *node = { package parse; import os; -import mem; import tok; fn parseletlocal(p: *parser) *node = { @@ -6005,14 +5903,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, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(nkind.N_MLET, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (true) { let lpf: str = p.curfile; let lpl: i32 = p.curline; let lpc: i32 = p.curcol; - let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -6035,7 +5933,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -6046,14 +5944,14 @@ fn parseletlocal(p: *parser) *node = { // Collects (name, type) pairs, then '=' rhs. Each binding gets // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(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, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -6085,7 +5983,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, nkind.N_BLOCK, pf, pl, pc); + let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -6107,7 +6005,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, nkind.N_IF, pf, pl, pc); + let n: *node = newnode(nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -6147,7 +6045,7 @@ fn parsefor(p: *parser) *node = { let npf: str = p.curfile; let npl: i32 = p.curline; let npc: i32 = p.curcol; - let e: *node = newnode(p.a, nkind.N_IDENT, npf, npl, npc); + let e: *node = newnode(nkind.N_IDENT, npf, npl, npc); let nm: str; expectbindname(p, &nm); e.str = nm; @@ -6158,7 +6056,7 @@ fn parsefor(p: *parser) *node = { }; expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names"); expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names"); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.list = names; rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -6183,7 +6081,7 @@ fn parsefor(p: *parser) *node = { if (p.curkind == tkind.TK_DOTDOT) { advance(p); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.str = nm; // "" for `_` rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -6194,12 +6092,12 @@ fn parsefor(p: *parser) *node = { // Not a range — finish the let manually and continue as // a 3-clause for-init. - let first: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc); first.str = nm; if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); }; if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); }; expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let"); - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); n.lhs = first; n.cond = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after for cond"); @@ -6214,7 +6112,7 @@ fn parsefor(p: *parser) *node = { }; // for (cond) or for (cond; post) - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); let first: *node = parseexpr(p); if (accepttok(p, tkind.TK_SEMI)) { n.cond = first; @@ -6238,7 +6136,7 @@ fn parseswitch(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `switch` expecttok(p, tkind.TK_LPAREN, "expected '(' after switch"); - let n: *node = newnode(p.a, nkind.N_SWITCH, pf, pl, pc); + let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body"); @@ -6249,7 +6147,7 @@ fn parseswitch(p: *parser) *node = { let cpl: i32 = p.curline; let cpc: i32 = p.curcol; advance(p); // past `case` - let cs: *node = newnode(p.a, nkind.N_CASE, cpf, cpl, cpc); + let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc); let eh: *node = nil; let et: *node = nil; if (p.curkind != tkind.TK_COLON) { @@ -6277,7 +6175,7 @@ fn parseswitch(p: *parser) *node = { bt = s; }; }; - let blk: *node = newnode(p.a, nkind.N_BLOCK, cpf, cpl, cpc); + let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc); blk.list = bh; cs.body = blk; if (head == nil) { head = cs; } @@ -6322,13 +6220,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -6346,14 +6244,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, nkind.N_DEFER, pf, pl, pc); + let n: *node = newnode(nkind.N_DEFER, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after defer"); return n; }; if (p.curkind == tkind.TK_YIELD) { advance(p); - let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); + let n: *node = newnode(nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -6361,12 +6259,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, nkind.N_BREAK, pf, pl, pc); + return newnode(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, nkind.N_CONTINUE, pf, pl, pc); + return newnode(nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -6376,7 +6274,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, nkind.N_MASSIGN, pf, pl, pc); + let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -6391,7 +6289,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; @@ -6404,12 +6302,11 @@ fn parsestmt(p: *parser) *node = { // the primitive types (tyvoid, tyi32, …); ww doesn't have writable // global storage yet, so we bundle the primitives into a `tctx` that // the checker passes around explicitly. typesinit fills the tctx -// once per arena. +// once per program. package ww; import os; -import mem; // ---- TypeKind --------------------------------------------------------- // Numeric values must stay aligned with cmd/wcc/ww.h TypeKind so the @@ -6518,7 +6415,6 @@ type tinfocacheent = struct { // ---- tctx — the box of primitive types ------------------------------- type tctx = struct { - a: *arena, tyvoid: *tinfo, tybool: *tinfo, tyrune: *tinfo, @@ -6549,13 +6445,13 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- -export fn newtype(a: *arena, k: tykind) *tinfo = { +export fn newtype(k: tykind) *tinfo = { let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; -fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { - let t: *tinfo = newtype(a, k); +fn prim(k: tykind, nm: str, sz: u64, al: u64) *tinfo = { + let t: *tinfo = newtype(k); t.name = nm; t.size = sz; if (al > 0u64) { t.align = al; } else { t.align = sz; }; @@ -6563,38 +6459,37 @@ fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { return t; }; -export fn typesinit(c: *tctx, a: *arena) void = { - c.a = a; - c.tyvoid = prim(a, tykind.TY_VOID, "void", 0u64, 1u64); - c.tybool = prim(a, tykind.TY_BOOL, "bool", 1u64, 1u64); - c.tyrune = prim(a, tykind.TY_RUNE, "rune", 4u64, 4u64); - c.tyi8 = prim(a, tykind.TY_I8, "i8", 1u64, 1u64); - c.tyi16 = prim(a, tykind.TY_I16, "i16", 2u64, 2u64); - c.tyi32 = prim(a, tykind.TY_I32, "i32", 4u64, 4u64); - c.tyi64 = prim(a, tykind.TY_I64, "i64", 8u64, 8u64); - c.tyu8 = prim(a, tykind.TY_U8, "u8", 1u64, 1u64); - c.tyu16 = prim(a, tykind.TY_U16, "u16", 2u64, 2u64); - c.tyu32 = prim(a, tykind.TY_U32, "u32", 4u64, 4u64); - c.tyu64 = prim(a, tykind.TY_U64, "u64", 8u64, 8u64); - c.tyint = prim(a, tykind.TY_INT, "int", 8u64, 8u64); - c.tyuint = prim(a, tykind.TY_UINT, "uint", 8u64, 8u64); - c.tyuintptr= prim(a, tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); - c.tyf32 = prim(a, tykind.TY_F32, "f32", 4u64, 4u64); - c.tyf64 = prim(a, tykind.TY_F64, "f64", 8u64, 8u64); - c.tystr = prim(a, tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) - c.tyerr = prim(a, tykind.TY_ERR, "", 0u64, 1u64); - c.tynever = prim(a, tykind.TY_NEVER, "never", 0u64, 1u64); +export fn typesinit(c: *tctx) void = { + c.tyvoid = prim(tykind.TY_VOID, "void", 0u64, 1u64); + c.tybool = prim(tykind.TY_BOOL, "bool", 1u64, 1u64); + c.tyrune = prim(tykind.TY_RUNE, "rune", 4u64, 4u64); + c.tyi8 = prim(tykind.TY_I8, "i8", 1u64, 1u64); + c.tyi16 = prim(tykind.TY_I16, "i16", 2u64, 2u64); + c.tyi32 = prim(tykind.TY_I32, "i32", 4u64, 4u64); + c.tyi64 = prim(tykind.TY_I64, "i64", 8u64, 8u64); + c.tyu8 = prim(tykind.TY_U8, "u8", 1u64, 1u64); + c.tyu16 = prim(tykind.TY_U16, "u16", 2u64, 2u64); + c.tyu32 = prim(tykind.TY_U32, "u32", 4u64, 4u64); + c.tyu64 = prim(tykind.TY_U64, "u64", 8u64, 8u64); + c.tyint = prim(tykind.TY_INT, "int", 8u64, 8u64); + c.tyuint = prim(tykind.TY_UINT, "uint", 8u64, 8u64); + c.tyuintptr= prim(tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); + c.tyf32 = prim(tykind.TY_F32, "f32", 4u64, 4u64); + c.tyf64 = prim(tykind.TY_F64, "f64", 8u64, 8u64); + c.tystr = prim(tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) + c.tyerr = prim(tykind.TY_ERR, "", 0u64, 1u64); + c.tynever = prim(tykind.TY_NEVER, "never", 0u64, 1u64); - c.tyuntypedint = prim(a, tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); - c.tyuntypedfloat = prim(a, tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); - c.tyuntypedstr = prim(a, tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); - c.tyuntypedrune = prim(a, tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); - c.tyuntypedbool = prim(a, tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); - c.tyuntypednil = prim(a, tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); + c.tyuntypedint = prim(tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); + c.tyuntypedfloat = prim(tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); + c.tyuntypedstr = prim(tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); + c.tyuntypedrune = prim(tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); + c.tyuntypedbool = prim(tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); + c.tyuntypednil = prim(tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); }; -export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_PTR); +export fn typeptr(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_PTR); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -6602,8 +6497,8 @@ export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_SLICE); +export fn typeslice(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_SLICE); t.sub = sub; t.size = 24u64; // sizelint-ok: SSoT for slice header (#64) t.align = 8u64; @@ -6611,8 +6506,8 @@ export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_ARRAY); +export fn typearray(sub: *tinfo, n: u64) *tinfo = { + let t: *tinfo = newtype(tykind.TY_ARRAY); t.sub = sub; t.alen = n; if (sub != nil) { @@ -6629,8 +6524,8 @@ export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { return t; }; -export fn typechan(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_CHAN); +export fn typechan(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_CHAN); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -6638,8 +6533,8 @@ export fn typechan(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typenamed(a: *arena, name: str, under: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_NAMED); +export fn typenamed(name: str, under: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_NAMED); t.name = name; t.under = under; if (under != nil) { @@ -6805,10 +6700,6 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = { package ww; -// Sibling imports (typ, ast) auto-resolve via task #22 dir-enum -// when callers `import ww;` or pull all three separately. -import mem; - // Symbol kinds — must stay numerically aligned with cmd/wcc/ww.h Skind. type skind = enum i32 { SK_NONE = 0, @@ -6846,7 +6737,6 @@ type scope = struct { last: *sym, buckets: **sym, // length = NBUCKETS nbuckets: i32, - a: *arena, }; // FNV-1a 64 — same hash the C side uses, so bucket distribution is @@ -6863,9 +6753,9 @@ fn hashstr(s: str) u64 = { return h; }; -export fn newscope(a: *arena, parent: *scope) *scope = { +export fn newscope(parent: *scope) *scope = { let buckets_sl: []*sym = alloc([], NBUCKETS: u64)!; - let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS, a=a})!; + let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS})!; return s; }; @@ -7062,11 +6952,9 @@ export fn scopedefineinmodule(s: *scope, name: str, mod: str, k: skind, t: *tinf package wcc; import os; -import mem; import tok; type checker = struct { - a: *arena, tc: *tctx, top: *scope, cur: *scope, @@ -7114,11 +7002,11 @@ fn seedprimitives(c: *checker) void = { // separate alias chain — see collectaliases in cgen.ww for the // companion seed. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; - let nomemdecl: *node = newnode(c.a, nkind.N_TYPEDECL, empty, 0, 0); + let nomemdecl: *node = newnode(nkind.N_TYPEDECL, empty, 0, 0); nomemdecl.str = "nomem"; nomemdecl.lhs = bang; scopedefine(c.top, "nomem", skind.SK_TYPE, nil, nomemdecl); @@ -7392,7 +7280,7 @@ fn resolvewalk(c: *checker, n: *node) void = { if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let nm: str = n.str; if (nm.len > 0) { checkmoduleshadow(c, nm, "binding"); @@ -7414,7 +7302,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // Mirrors cstage cstmt N_BLOCK at cmd/wcc/check.c:1559-1566. if (k == nkind.N_BLOCK) { let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let m: *node = n.list; for (m != nil) { resolvewalk(c, m); @@ -7693,7 +7581,7 @@ fn scruttype(c: *checker, e: *node) *node = { // 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, nkind.N_TNAME, "", 0, 0); + let n: *node = newnode(nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -7880,7 +7768,7 @@ fn astoffset(c: *checker, dot: *node) i64 = { // wwstage cgen only reads `uval` for N_INTLIT codegen so `str` is // just for the AST printer, but set it for parity with the parser's // own literal-emit shape. -fn arenau64tos(a: *arena, v: u64) str = { +fn arenau64tos(v: u64) str = { let buf: []u8 = alloc([], 24u64)!; let i: i32 = 23; buf[i] = 0u8; @@ -7904,7 +7792,7 @@ fn arenau64tos(a: *arena, v: u64) str = { fn foldtointlit(c: *checker, n: *node, v: i64) void = { n.kind = nkind.N_INTLIT; n.uval = v: u64; - n.str = arenau64tos(c.a, v: u64); + n.str = arenau64tos(v: u64); n.lhs = nil; n.list = nil; let empty: str; @@ -8056,11 +7944,11 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // site that needs iserror discrimination. r = tinfofornode(c, n.lhs); } else { if (k == nkind.N_TPTR) { - r = typeptr(c.a, tinfofornode(c, n.lhs)); + r = typeptr(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TSLICE) { - r = typeslice(c.a, tinfofornode(c, n.lhs)); + r = typeslice(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TCHAN) { - r = typechan(c.a, tinfofornode(c, n.lhs)); + r = typechan(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TARRAY) { // Cstage cmd/wcc/check.c:314-326: length must be an integer // literal (`[_]T` keeps alen=0 as the inferred-length sentinel @@ -8076,14 +7964,14 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (n.rhs.kind == nkind.N_INTLIT) { elen = n.rhs.uval; }; }; let sub: *tinfo = tinfofornode(c, n.lhs); - r = typearray(c.a, sub, elen); + r = typearray(sub, elen); } else { if (k == nkind.N_TFN) { // Cstage cmd/wcc/check.c:437-466: function types are 8B / 8B // (call-target pointer shape). Pre-bind before recursing into // the return type so a recursive `type F = fn() F` self-ref // doesn't spin (cycle-break mirror of the TSTRUCT/TTAGGED // pattern below). - r = newtype(c.a, tykind.TY_FN); + r = newtype(tykind.TY_FN); r.size = 8u64; r.align = 8u64; r.slotsize = 8u64; @@ -8094,7 +7982,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads // to 8B per its stack-slot contract; tinfo.size carries the // raw storage width so size(EnumT) folds to the correct value. - r = newtype(c.a, tykind.TY_ENUM); + r = newtype(tykind.TY_ENUM); let storage: *tinfo = nil; if (n.lhs != nil) { storage = tinfofornode(c, n.lhs); }; if (storage == nil) { storage = c.tc.tyi32; }; @@ -8113,7 +8001,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // slotsize TTUPLE — narrow scalars pad to 8 (cgen spills each // tuple element into its own register / stack-slot eightbyte), // composites contribute their own ti.slotsize. - r = newtype(c.a, tykind.TY_TUPLE); + r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); let total: u64 = 0u64; let slottotal: u64 = 0u64; @@ -8151,7 +8039,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // struct; size-derived alignment; final round to 8). That // slot total lands in ti.slotsize so the cgen fast-path can // graduate TY_STRUCT off the AST walker. - r = newtype(c.a, tykind.TY_STRUCT); + r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); let off: u64 = 0u64; let maxalign: u64 = 1u64; @@ -8193,7 +8081,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // Cstage cmd/wcc/check.c:347-435: 8B tag + max(variant) // rounded up to 8. Pre-bind for cycle protection (recursive // sum-type shapes through NAMED variants). - r = newtype(c.a, tykind.TY_TAGGED); + r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors @@ -8352,11 +8240,11 @@ fn exprtype(c: *checker, e: *node) *node = { if (e.list.list == nil) { if (e.list.next != nil) { if (e.list.next.next == nil) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = mktname(c, "u8"); let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; return tt; }; @@ -8366,11 +8254,11 @@ fn exprtype(c: *checker, e: *node) *node = { // Value form: `alloc(value)`. if (e.list.next == nil) { let argt: *node = exprtype(c, e.list); - let ptr: *node = newnode(c.a, nkind.N_TPTR, "", 0, 0); + let ptr: *node = newnode(nkind.N_TPTR, "", 0, 0); ptr.lhs = argt; let nome: *node = mktname(c, "nomem"); ptr.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; return tt; }; @@ -8887,14 +8775,14 @@ fn checkletassign(c: *checker, n: *node) void = { }; }; if (!shadowed) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = n.lhs.lhs; if (wrapped) { src = sl; } else { let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; src = tt; }; @@ -9085,7 +8973,7 @@ fn installparams(c: *checker, params: *node) void = { // per-statement scopes. fn resolvefnbody(c: *checker, fnnode: *node) void = { let outer: *scope = c.cur; - c.cur = newscope(c.a, c.cur); + c.cur = newscope(c.cur); installparams(c, fnnode.list); // #61 audit §1.8 — A.2: walk each param's declared type-expr so // tinfofornode stamps n.type_ on it. installparams binds the name @@ -9107,10 +8995,9 @@ fn resolvefnbody(c: *checker, fnnode: *node) void = { c.cur = outer; }; -export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { - c.a = a; +export fn checkinit(c: *checker, tc: *tctx) void = { c.tc = tc; - c.top = newscope(a, nil); + c.top = newscope(nil); c.cur = c.top; c.nresolved = 0; c.nunresolved = 0; @@ -9441,7 +9328,6 @@ fn dynamicgrow(m: *state, need: i32) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -9456,7 +9342,7 @@ import strconv; // (caller side) both advertise their effective type as []ELEM — // every isslicetype / nodeisslice check then succeeds naturally. fn slicewrap(c: *cgen, elem: *node) *node = { - let s: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let s: *node = newnode(nkind.N_TSLICE, "", 0, 0); s.lhs = elem; return s; }; @@ -13439,7 +13325,6 @@ fn cgstructlitfillbp(c: *cgen, si: *structinfo, lit: *node, bpoff: i32) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -16596,7 +16481,7 @@ fn cgcall(c: *cgen, n: *node) void = { emitline("\tMOVQ\tAX, "); emitoff((soff + 16): i64); emitline("(BP)\n"); - let sn: *node = newnode(c.a, nkind.N_IDENT, + let sn: *node = newnode(nkind.N_IDENT, "", 0, 0); sn.str = sname; if (prevarg == nil) { n.list = sn; } @@ -19235,7 +19120,6 @@ fn cgassign(c: *cgen, n: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -20878,7 +20762,6 @@ fn cgcontinue(c: *cgen, n: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -21204,7 +21087,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { }; fn cgfn(c: *cgen, fn_: *node) void = { - cgeninit(c, c.a); + cgeninit(c); c.fnname = fn_.str; c.curmod = fn_.nmod; c.fnret = fn_.lhs; @@ -21348,7 +21231,6 @@ export fn cgfile(c: *cgen, file: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -21391,9 +21273,9 @@ fn collectaliases(c: *cgen, file: *node) void = { // same-module / any-match passes in aliaslookup then let a local // `type nomem = !void;` shadow this fallback within its module. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; let nomemal: *aliasent = alloc(aliasent{aname="nomem", amod=empty, target=bang, aanext=nil})!; c.aliases = nomemal; @@ -21758,7 +21640,6 @@ def LOOP_MAX: i32 = 16; def DEFER_MAX: i32 = 16; type cgen = struct { - a: *arena, locals: *local, // atlocals — persistent registry of `@`-prefix scratch slots // for the current fn. cgblock save/restores c.locals to scope @@ -21845,8 +21726,7 @@ type letvar = struct { lvnext: *letvar, }; -fn cgeninit(c: *cgen, a: *arena) void = { - c.a = a; +fn cgeninit(c: *cgen) void = { c.locals = nil; c.atlocals = nil; c.frame = 0; @@ -23373,7 +23253,6 @@ package main; import os; import rt; -import mem; import strings; import tok; import lex; @@ -23494,7 +23373,6 @@ export fn main(argc: i32, argv: **u8) i32 = { os.close(ofd); }; - let ar: *arena = newarena(); let nlen: u64 = cstrlen(src); let view: str; view.ptr = src; @@ -23502,10 +23380,10 @@ export fn main(argc: i32, argv: **u8) i32 = { let fname: str = strings.dup(view); let l: lex; - lexinit(&l, ar, fname, buf, blen); + lexinit(&l, fname, buf, blen); let ps: parser; - parserinit(&ps, ar, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); // Gate cgen on parse-stage errors. Mirrors cmd/w6c/main.c's // `if (l.errs || p.errs) return 1;` — broken AST otherwise reaches @@ -23519,14 +23397,14 @@ export fn main(argc: i32, argv: **u8) i32 = { // enum↔int reinterpret, #53 N_BLOCK scoping, #55 nominal-first variant // compare, #56 bare-leaf same-module preference. let tc: tctx; - typesinit(&tc, ar); + typesinit(&tc); let ck: checker; - checkinit(&ck, ar, &tc); + checkinit(&ck, &tc); checkfile(&ck, f); if (ck.errs > 0) { return 1; }; let cg: cgen; - cgeninit(&cg, ar); + cgeninit(&cg); cgfile(&cg, f); return 0; }; diff --git a/selfhost/cmd/w6c/main.ww b/selfhost/cmd/w6c/main.ww index 39af3bad..6788b83c 100644 --- a/selfhost/cmd/w6c/main.ww +++ b/selfhost/cmd/w6c/main.ww @@ -14,7 +14,6 @@ package main; import os; import rt; -import mem; import strings; import tok; import lex; @@ -135,7 +134,6 @@ export fn main(argc: i32, argv: **u8) i32 = { os.close(ofd); }; - let ar: *arena = newarena(); let nlen: u64 = cstrlen(src); let view: str; view.ptr = src; @@ -143,10 +141,10 @@ export fn main(argc: i32, argv: **u8) i32 = { let fname: str = strings.dup(view); let l: lex; - lexinit(&l, ar, fname, buf, blen); + lexinit(&l, fname, buf, blen); let ps: parser; - parserinit(&ps, ar, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); // Gate cgen on parse-stage errors. Mirrors cmd/w6c/main.c's // `if (l.errs || p.errs) return 1;` — broken AST otherwise reaches @@ -160,14 +158,14 @@ export fn main(argc: i32, argv: **u8) i32 = { // enum↔int reinterpret, #53 N_BLOCK scoping, #55 nominal-first variant // compare, #56 bare-leaf same-module preference. let tc: tctx; - typesinit(&tc, ar); + typesinit(&tc); let ck: checker; - checkinit(&ck, ar, &tc); + checkinit(&ck, &tc); checkfile(&ck, f); if (ck.errs > 0) { return 1; }; let cg: cgen; - cgeninit(&cg, ar); + cgeninit(&cg); cgfile(&cg, f); return 0; }; diff --git a/selfhost/cmd/wcc/cgen.ww b/selfhost/cmd/wcc/cgen.ww index 1d5c2438..9292dd22 100644 --- a/selfhost/cmd/wcc/cgen.ww +++ b/selfhost/cmd/wcc/cgen.ww @@ -25,7 +25,6 @@ package wcc; import os; -import mem; import ast; import tok; import typ; @@ -68,9 +67,9 @@ fn collectaliases(c: *cgen, file: *node) void = { // same-module / any-match passes in aliaslookup then let a local // `type nomem = !void;` shadow this fallback within its module. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; let nomemal: *aliasent = alloc(aliasent{aname="nomem", amod=empty, target=bang, aanext=nil})!; c.aliases = nomemal; @@ -435,7 +434,6 @@ def LOOP_MAX: i32 = 16; def DEFER_MAX: i32 = 16; type cgen = struct { - a: *arena, locals: *local, // atlocals — persistent registry of `@`-prefix scratch slots // for the current fn. cgblock save/restores c.locals to scope @@ -522,8 +520,7 @@ type letvar = struct { lvnext: *letvar, }; -fn cgeninit(c: *cgen, a: *arena) void = { - c.a = a; +fn cgeninit(c: *cgen) void = { c.locals = nil; c.atlocals = nil; c.frame = 0; diff --git a/selfhost/cmd/wcc/cgendecl.ww b/selfhost/cmd/wcc/cgendecl.ww index d3b334aa..7a2737dc 100644 --- a/selfhost/cmd/wcc/cgendecl.ww +++ b/selfhost/cmd/wcc/cgendecl.ww @@ -13,7 +13,6 @@ package wcc; import os; -import mem; import ast; import tok; import typ; @@ -339,7 +338,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { }; fn cgfn(c: *cgen, fn_: *node) void = { - cgeninit(c, c.a); + cgeninit(c); c.fnname = fn_.str; c.curmod = fn_.nmod; c.fnret = fn_.lhs; diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index ffb3089b..5457c1e4 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -15,7 +15,6 @@ package wcc; import os; -import mem; import ast; import tok; import typ; @@ -3172,7 +3171,7 @@ fn cgcall(c: *cgen, n: *node) void = { emitline("\tMOVQ\tAX, "); emitoff((soff + 16): i64); emitline("(BP)\n"); - let sn: *node = newnode(c.a, nkind.N_IDENT, + let sn: *node = newnode(nkind.N_IDENT, "", 0, 0); sn.str = sname; if (prevarg == nil) { n.list = sn; } diff --git a/selfhost/cmd/wcc/cgenstmt.ww b/selfhost/cmd/wcc/cgenstmt.ww index 6eac818d..1faa30ee 100644 --- a/selfhost/cmd/wcc/cgenstmt.ww +++ b/selfhost/cmd/wcc/cgenstmt.ww @@ -11,7 +11,6 @@ package wcc; import os; -import mem; import ast; import tok; import typ; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index 1a304f2b..e4041263 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -15,7 +15,6 @@ package wcc; import os; -import mem; import ast; import tok; import typ; @@ -30,7 +29,7 @@ import strconv; // (caller side) both advertise their effective type as []ELEM — // every isslicetype / nodeisslice check then succeeds naturally. fn slicewrap(c: *cgen, elem: *node) *node = { - let s: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let s: *node = newnode(nkind.N_TSLICE, "", 0, 0); s.lhs = elem; return s; }; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 18e7dba1..be956b10 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -20,11 +20,9 @@ package wcc; import os; -import mem; import tok; type checker = struct { - a: *arena, tc: *tctx, top: *scope, cur: *scope, @@ -72,11 +70,11 @@ fn seedprimitives(c: *checker) void = { // separate alias chain — see collectaliases in cgen.ww for the // companion seed. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; - let nomemdecl: *node = newnode(c.a, nkind.N_TYPEDECL, empty, 0, 0); + let nomemdecl: *node = newnode(nkind.N_TYPEDECL, empty, 0, 0); nomemdecl.str = "nomem"; nomemdecl.lhs = bang; scopedefine(c.top, "nomem", skind.SK_TYPE, nil, nomemdecl); @@ -350,7 +348,7 @@ fn resolvewalk(c: *checker, n: *node) void = { if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let nm: str = n.str; if (nm.len > 0) { checkmoduleshadow(c, nm, "binding"); @@ -372,7 +370,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // Mirrors cstage cstmt N_BLOCK at cmd/wcc/check.c:1559-1566. if (k == nkind.N_BLOCK) { let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let m: *node = n.list; for (m != nil) { resolvewalk(c, m); @@ -651,7 +649,7 @@ fn scruttype(c: *checker, e: *node) *node = { // 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, nkind.N_TNAME, "", 0, 0); + let n: *node = newnode(nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -838,7 +836,7 @@ fn astoffset(c: *checker, dot: *node) i64 = { // wwstage cgen only reads `uval` for N_INTLIT codegen so `str` is // just for the AST printer, but set it for parity with the parser's // own literal-emit shape. -fn arenau64tos(a: *arena, v: u64) str = { +fn arenau64tos(v: u64) str = { let buf: []u8 = alloc([], 24u64)!; let i: i32 = 23; buf[i] = 0u8; @@ -862,7 +860,7 @@ fn arenau64tos(a: *arena, v: u64) str = { fn foldtointlit(c: *checker, n: *node, v: i64) void = { n.kind = nkind.N_INTLIT; n.uval = v: u64; - n.str = arenau64tos(c.a, v: u64); + n.str = arenau64tos(v: u64); n.lhs = nil; n.list = nil; let empty: str; @@ -1014,11 +1012,11 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // site that needs iserror discrimination. r = tinfofornode(c, n.lhs); } else { if (k == nkind.N_TPTR) { - r = typeptr(c.a, tinfofornode(c, n.lhs)); + r = typeptr(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TSLICE) { - r = typeslice(c.a, tinfofornode(c, n.lhs)); + r = typeslice(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TCHAN) { - r = typechan(c.a, tinfofornode(c, n.lhs)); + r = typechan(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TARRAY) { // Cstage cmd/wcc/check.c:314-326: length must be an integer // literal (`[_]T` keeps alen=0 as the inferred-length sentinel @@ -1034,14 +1032,14 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (n.rhs.kind == nkind.N_INTLIT) { elen = n.rhs.uval; }; }; let sub: *tinfo = tinfofornode(c, n.lhs); - r = typearray(c.a, sub, elen); + r = typearray(sub, elen); } else { if (k == nkind.N_TFN) { // Cstage cmd/wcc/check.c:437-466: function types are 8B / 8B // (call-target pointer shape). Pre-bind before recursing into // the return type so a recursive `type F = fn() F` self-ref // doesn't spin (cycle-break mirror of the TSTRUCT/TTAGGED // pattern below). - r = newtype(c.a, tykind.TY_FN); + r = newtype(tykind.TY_FN); r.size = 8u64; r.align = 8u64; r.slotsize = 8u64; @@ -1052,7 +1050,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads // to 8B per its stack-slot contract; tinfo.size carries the // raw storage width so size(EnumT) folds to the correct value. - r = newtype(c.a, tykind.TY_ENUM); + r = newtype(tykind.TY_ENUM); let storage: *tinfo = nil; if (n.lhs != nil) { storage = tinfofornode(c, n.lhs); }; if (storage == nil) { storage = c.tc.tyi32; }; @@ -1071,7 +1069,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // slotsize TTUPLE — narrow scalars pad to 8 (cgen spills each // tuple element into its own register / stack-slot eightbyte), // composites contribute their own ti.slotsize. - r = newtype(c.a, tykind.TY_TUPLE); + r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); let total: u64 = 0u64; let slottotal: u64 = 0u64; @@ -1109,7 +1107,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // struct; size-derived alignment; final round to 8). That // slot total lands in ti.slotsize so the cgen fast-path can // graduate TY_STRUCT off the AST walker. - r = newtype(c.a, tykind.TY_STRUCT); + r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); let off: u64 = 0u64; let maxalign: u64 = 1u64; @@ -1151,7 +1149,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // Cstage cmd/wcc/check.c:347-435: 8B tag + max(variant) // rounded up to 8. Pre-bind for cycle protection (recursive // sum-type shapes through NAMED variants). - r = newtype(c.a, tykind.TY_TAGGED); + r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors @@ -1310,11 +1308,11 @@ fn exprtype(c: *checker, e: *node) *node = { if (e.list.list == nil) { if (e.list.next != nil) { if (e.list.next.next == nil) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = mktname(c, "u8"); let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; return tt; }; @@ -1324,11 +1322,11 @@ fn exprtype(c: *checker, e: *node) *node = { // Value form: `alloc(value)`. if (e.list.next == nil) { let argt: *node = exprtype(c, e.list); - let ptr: *node = newnode(c.a, nkind.N_TPTR, "", 0, 0); + let ptr: *node = newnode(nkind.N_TPTR, "", 0, 0); ptr.lhs = argt; let nome: *node = mktname(c, "nomem"); ptr.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; return tt; }; @@ -1845,14 +1843,14 @@ fn checkletassign(c: *checker, n: *node) void = { }; }; if (!shadowed) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = n.lhs.lhs; if (wrapped) { src = sl; } else { let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; src = tt; }; @@ -2043,7 +2041,7 @@ fn installparams(c: *checker, params: *node) void = { // per-statement scopes. fn resolvefnbody(c: *checker, fnnode: *node) void = { let outer: *scope = c.cur; - c.cur = newscope(c.a, c.cur); + c.cur = newscope(c.cur); installparams(c, fnnode.list); // #61 audit §1.8 — A.2: walk each param's declared type-expr so // tinfofornode stamps n.type_ on it. installparams binds the name @@ -2065,10 +2063,9 @@ fn resolvefnbody(c: *checker, fnnode: *node) void = { c.cur = outer; }; -export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { - c.a = a; +export fn checkinit(c: *checker, tc: *tctx) void = { c.tc = tc; - c.top = newscope(a, nil); + c.top = newscope(nil); c.cur = c.top; c.nresolved = 0; c.nunresolved = 0; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 75300f9e..045d8779 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -727,121 +727,6 @@ export fn exists(path: str) bool = { return r >= 0i64; }; -// rt — runtime primitives exposed to ww programs. -// Mirrors Hare's rt:: module placement (ref/hare/rt/). - -package rt; - -// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a -// `*void`; callers cast to the target type. Diverges from Hare: Hare -// exposes `alloc` / `free` as typed language builtins that the -// compiler lowers to rt::malloc/rt::free; ww has no such builtins, -// so the rt-symbol surface is exposed directly. Stdlib callers that -// need a typed allocation pattern wrap this with a cast plus a stored -// capacity (see [[strings.dup]], [[memio.dynamic]]). -// -// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no -// error path. The raw Linux mmap syscall returns a negative errno cast -// to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the -// `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches -// it; any deref of such a return faults. Today the stdlib does not -// check; OOM faults on first dereference. A typed fallible variant is -// a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_malloc") export fn malloc(n: u64) *void; - -// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. -// -// Bump arena allocator. Backed by the runtime page allocator -// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the -// current chunk runs out we link a fresh one. Freeing the arena -// unmaps the chain. -// -// Memory handed out is 16-byte aligned. The C version under -// cmd/wcc/ is retained until the three-stage bootstrap diffs clean. - -package wcc; - -import os; -import rt; - -def ALIGN: u64 = 16u64; -def INIT_CHUNK: u64 = 65536u64; -def MAX_CHUNK: u64 = 4194304u64; -def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below - -type arena = struct { - buf: *u8, - off: u64, - cap: u64, - next: *arena, - total: u64, -}; - -fn roundup(n: u64, a: u64) u64 = { - return (n + a - 1u64) & ~(a - 1u64); -}; - -export fn newarena() *arena = { - let a: *arena = rt.malloc(ARENA_SZ): *arena; - a.buf = rt.malloc(INIT_CHUNK): *u8; - a.off = 0u64; - a.cap = INIT_CHUNK; - a.next = nil; - a.total = 0u64; - return a; -}; - -// Grow: link a fresh chunk in front of the head. We push the old -// chunk into `next` so the head always describes the current bump -// region. Chunk size doubles up to MAX_CHUNK. -fn grow(a: *arena, need: u64) bool = { - let want: u64 = a.cap * 2u64; - if (want < need) { want = need; }; - if (want > MAX_CHUNK) { want = MAX_CHUNK; }; - if (want < need) { return false; }; // single allocation too big - - let old: *arena = rt.malloc(ARENA_SZ): *arena; - old.buf = a.buf; - old.off = a.off; - old.cap = a.cap; - old.next = a.next; - old.total = 0u64; - - a.buf = rt.malloc(want): *u8; - a.off = 0u64; - a.cap = want; - a.next = old; - return true; -}; - -export fn amalloc(a: *arena, n: u64) *void = { - let need: u64 = roundup(n, ALIGN); - if (need > a.cap - a.off) { - if (!grow(a, need)) { return nil; }; - }; - let p: *u8 = a.buf + a.off; - a.off += need; - a.total += need; - // Zero the region. Plan 9 amalloc zeroes; we mirror that here so - // the checker can assume freshly allocated nodes start at 0. - let i: u64 = 0u64; - for (i < need) { - p[i] = 0u8; - i += 1u64; - }; - return p: *void; -}; - -export fn freearena(a: *arena) void = { - for (a != nil) { - let next: *arena = a.next; - os.free(a.buf: *void, a.cap); - os.free(a: *void, ARENA_SZ); - a = next; - }; -}; - // types — integer limits. Mirrors Hare's types::limits (I8_MAX, …) // platform-fixed for amd64. Numeric helpers live in lib/math, matching // Hare's split between types::limits and math::. @@ -1819,6 +1704,29 @@ export fn position(d: *decoder) i32 = { }; +// rt — runtime primitives exposed to ww programs. +// Mirrors Hare's rt:: module placement (ref/hare/rt/). + +package rt; + +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a +// `*void`; callers cast to the target type. Diverges from Hare: Hare +// exposes `alloc` / `free` as typed language builtins that the +// compiler lowers to rt::malloc/rt::free; ww has no such builtins, +// so the rt-symbol surface is exposed directly. Stdlib callers that +// need a typed allocation pattern wrap this with a cast plus a stored +// capacity (see [[strings.dup]], [[memio.dynamic]]). +// +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// error path. The raw Linux mmap syscall returns a negative errno cast +// to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the +// `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// it; any deref of such a return faults. Today the stdlib does not +// check; OOM faults on first dereference. A typed fallible variant is +// a future task (task #39). ref/hare/rt/malloc.ha:27. +@symbol("rt_malloc") export fn malloc(n: u64) *void; + // strings — operations over str ({ptr,len}). Hare port; see // ref/hare/strings/. // @@ -3711,7 +3619,6 @@ package lex; // callers `import lex;` (which dir-enums lib/ww/lex/). import os; import ascii; -import mem; import strings; // isidstart / isidpart — identifier classification. Lexer-local @@ -3749,18 +3656,16 @@ type lex = struct { lpos: u64, line: i32, col: i32, - a: *arena, errs: i32, }; -export fn lexinit(l: *lex, a: *arena, file: str, src: *u8, len: u64) void = { +export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.file = file; l.src = src; l.srclen = len; l.lpos = 0u64; l.line = 1; l.col = 1; - l.a = a; l.errs = 0; }; @@ -4526,7 +4431,6 @@ package ww; import os; import strconv; -import mem; import tok; // ---- Nkind ------------------------------------------------------------ @@ -4642,7 +4546,7 @@ type node = struct { nmod: str, // originating module from `// MODULE: foo`; "" if none }; -export fn newnode(a: *arena, k: nkind, file: str, line: i32, col: i32) *node = { +export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = { // fval cast-init: 990's wwdump TK_FLOAT diff requires this file // to tokenise identically through C and ww (lex.ww:382 has the // same workaround for the cstage %g-formats vs ww-skips divergence). @@ -4876,7 +4780,6 @@ export fn astprint(fd: i32, n: *node) void = { package parse; import os; -import mem; import tok; // `import encoding.utf8;` — the driver resolves the dotted path to @@ -4889,7 +4792,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, nkind.N_USE, pf, pl, pc); + let n: *node = newnode(nkind.N_USE, pf, pl, pc); n.nmod = p.curmod; let leaf: str; expectident(p, &leaf); @@ -4907,7 +4810,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, nkind.N_DEF, pf, pl, pc); + let n: *node = newnode(nkind.N_DEF, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -4930,7 +4833,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, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); n.nmod = p.curmod; let id: str; expectbindname(p, &id); @@ -4955,7 +4858,7 @@ fn parseattrs(p: *parser) *node = { let pl: i32 = p.curline; let pc: i32 = p.curcol; advance(p); - let a: *node = newnode(p.a, nkind.N_ATTR, pf, pl, pc); + let a: *node = newnode(nkind.N_ATTR, pf, pl, pc); let id: str; expectident(p, &id); a.str = id; @@ -4981,7 +4884,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, nkind.N_PARAM, pf, pl, pc); + let n: *node = newnode(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; @@ -5011,7 +4914,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, nkind.N_FNDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_FNDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -5041,7 +4944,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, nkind.N_TYPEDECL, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; expectident(p, &id); @@ -5059,7 +4962,6 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { package parse; import os; -import mem; import tok; // streqlocal — str-to-str compare. Inlined here to avoid a cross- @@ -5080,7 +4982,7 @@ fn parseprimary(p: *parser) *node = { let pc: i32 = p.curcol; if (p.curkind == tkind.TK_INT) { - let n: *node = newnode(p.a, nkind.N_INTLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_INTLIT, pf, pl, pc); n.uval = p.curuval; n.str = p.curtext; // Plumb the typed-int suffix (`42i64`, `3u8`) through to @@ -5094,7 +4996,7 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_FLOAT) { - let n: *node = newnode(p.a, nkind.N_FLOATLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_FLOATLIT, pf, pl, pc); n.fval = p.curfval; // uval carries the IEEE 754 bit pattern — the lexer sets // both, and cgen consumers prefer the integer view so they @@ -5106,32 +5008,32 @@ fn parseprimary(p: *parser) *node = { return n; }; if (p.curkind == tkind.TK_STR) { - let n: *node = newnode(p.a, nkind.N_STRLIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_RUNELIT, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRUE, pf, pl, pc); + return newnode(nkind.N_TRUE, pf, pl, pc); }; if (p.curkind == tkind.TK_FALSE) { advance(p); - return newnode(p.a, nkind.N_FALSE, pf, pl, pc); + return newnode(nkind.N_FALSE, pf, pl, pc); }; if (p.curkind == tkind.TK_NIL) { advance(p); - return newnode(p.a, nkind.N_NIL, pf, pl, pc); + return newnode(nkind.N_NIL, pf, pl, pc); }; if (p.curkind == tkind.TK_VOID) { advance(p); - return newnode(p.a, nkind.N_VOIDLIT, pf, pl, pc); + return newnode(nkind.N_VOIDLIT, pf, pl, pc); }; if (p.curkind == tkind.TK_UNDER) { // Bare `_` — valid only as a discard lvalue. Emit an N_IDENT @@ -5139,14 +5041,14 @@ fn parseprimary(p: *parser) *node = { // already 0); the checker rejects it outside lvalue // positions. advance(p); - return newnode(p.a, nkind.N_IDENT, pf, pl, pc); + return newnode(nkind.N_IDENT, pf, pl, pc); }; if (p.curkind == tkind.TK_LBRACK) { // Array literal `[a, b, c]` or `[v, w...]` (repeat suffix). // 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, nkind.N_ARRLIT, pf, pl, pc); + let n: *node = newnode(nkind.N_ARRLIT, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACK) { @@ -5155,7 +5057,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, nkind.N_FIELD, + let rep: *node = newnode(nkind.N_FIELD, p.curfile, p.curline, p.curcol); rep.str = "..."; tail.next = rep; @@ -5173,7 +5075,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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = e; let tail: *node = e; for (true) { @@ -5190,7 +5092,7 @@ fn parseprimary(p: *parser) *node = { return e; }; if (p.curkind == tkind.TK_IDENT) { - let n: *node = newnode(p.a, nkind.N_IDENT, pf, pl, pc); + let n: *node = newnode(nkind.N_IDENT, pf, pl, pc); n.str = p.curtext; advance(p); // `IDENT {` — struct literal. Disambiguate: only consume as a @@ -5201,7 +5103,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, nkind.N_STRUCTLIT, pf, pl, pc); + let s: *node = newnode(nkind.N_STRUCTLIT, pf, pl, pc); s.lhs = n; let head: *node = nil; let tail: *node = nil; @@ -5221,7 +5123,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, nkind.N_FIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_FIELD, fpf, fpl, fpc); f.str = id; f.lhs = v; if (head == nil) { head = f; tail = f; } @@ -5238,7 +5140,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, nkind.N_MATCH, pf, pl, pc); + let m: *node = newnode(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"); @@ -5249,7 +5151,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, nkind.N_MCASE, cf, cl, cc); + let mc: *node = newnode(nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); let id: str; @@ -5271,7 +5173,7 @@ fn parseprimary(p: *parser) *node = { }; errmsg(p, "expected expression"); advance(p); - return newnode(p.a, nkind.N_NONE, pf, pl, pc); + return newnode(nkind.N_NONE, pf, pl, pc); }; fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { @@ -5285,7 +5187,7 @@ fn parsearglist(p: *parser, closekind: tkind, headout: **node) void = { // marker the callee/builtin can iterate over. Mirrors // cmd/wcc/parse.c. The only consumer today is `append`. if (accepttok(p, tkind.TK_ELLIPSIS)) { - let sp: *node = newnode(p.a, nkind.N_SPREAD, e.file, e.line, e.col); + let sp: *node = newnode(nkind.N_SPREAD, e.file, e.line, e.col); sp.lhs = e; e = sp; }; @@ -5305,7 +5207,7 @@ 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, nkind.N_CALL, pf, pl, pc); + let n: *node = newnode(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. @@ -5330,7 +5232,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; if (p.curkind != tkind.TK_RBRACK) { n.cond = parseexpr(p); @@ -5347,7 +5249,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, nkind.N_SLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_SLICE, pf, pl, pc); n.lhs = cur; n.rhs = e; if (p.curkind != tkind.TK_RBRACK) { @@ -5357,7 +5259,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { cur = n; continue; }; - let n: *node = newnode(p.a, nkind.N_INDEX, pf, pl, pc); + let n: *node = newnode(nkind.N_INDEX, pf, pl, pc); n.lhs = cur; n.rhs = e; expecttok(p, tkind.TK_RBRACK, "expected ']' after index"); @@ -5366,7 +5268,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_DOT) { advance(p); - let n: *node = newnode(p.a, nkind.N_DOT, pf, pl, pc); + let n: *node = newnode(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 @@ -5387,7 +5289,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { return cur; }; advance(p); - let n: *node = newnode(p.a, nkind.N_CAST, pf, pl, pc); + let n: *node = newnode(nkind.N_CAST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5399,7 +5301,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, nkind.N_TYPEASSERT, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPEASSERT, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5407,7 +5309,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = { }; if (p.curkind == tkind.TK_IS) { advance(p); - let n: *node = newnode(p.a, nkind.N_TYPETEST, pf, pl, pc); + let n: *node = newnode(nkind.N_TYPETEST, pf, pl, pc); n.lhs = cur; n.rhs = parsetype(p); cur = n; @@ -5417,14 +5319,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, nkind.N_TRYPROP, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TRYUNW, pf, pl, pc); + let n: *node = newnode(nkind.N_TRYUNW, pf, pl, pc); n.lhs = cur; cur = n; continue; @@ -5441,37 +5343,37 @@ fn parseunary(p: *parser) *node = { let k: tkind = p.curkind; if (k == tkind.TK_MINUS) { advance(p); - let n: *node = newnode(p.a, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_UN, pf, pl, pc); + let n: *node = newnode(nkind.N_UN, pf, pl, pc); n.op = tkind.TK_AMP; n.lhs = parseunary(p); return n; }; @@ -5495,7 +5397,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, nkind.N_BIN, pf, pl, pc); + let n: *node = newnode(nkind.N_BIN, pf, pl, pc); n.op = op; n.lhs = cur; n.rhs = rhs; cur = n; }; @@ -5510,7 +5412,7 @@ fn parseexpr(p: *parser) *node = { let pc: i32 = p.curcol; let op: tkind = p.curkind; advance(p); - let n: *node = newnode(p.a, nkind.N_ASSIGN, pf, pl, pc); + let n: *node = newnode(nkind.N_ASSIGN, pf, pl, pc); n.op = op; n.lhs = e; n.rhs = parseexpr(p); // right-associative @@ -5538,12 +5440,10 @@ package parse; // dir-enum when callers `import parse;` (which dir-enums // lib/ww/parse/). import os; -import mem; import tok; type parser = struct { l: *lex, - a: *arena, errs: i32, // nocast: while inside `[...]` we treat ':' as the slice // separator, not the cast operator. Mirrors parse.c's flag. @@ -5582,9 +5482,8 @@ fn refill(p: *parser) void = { p.curtsuffix = t.tsuffix; }; -export fn parserinit(p: *parser, a: *arena, l: *lex) void = { +export fn parserinit(p: *parser, l: *lex) void = { p.l = l; - p.a = a; p.errs = 0; p.nocast = 0; refill(p); @@ -5642,10 +5541,10 @@ fn expectbindname(p: *parser, into: *str) bool = { // Other forms (slice, array, struct, fn, chan, tuple, tagged) will // land in subsequent commits. -// joindotted — arena-build "head.tail" for dotted type-name path +// joindotted — build "head.tail" for dotted type-name path // collapse. Mirrors aprintf in C parser; pulled local to avoid a // cross-module dependency. -fn joindotted(a: *arena, head: str, tail: str) str = { +fn joindotted(head: str, tail: str) str = { let n: u64 = head.len: u64 + 1u64 + tail.len: u64; let buf: []u8 = alloc([], n + 1u64)!; let i: u64 = 0u64; @@ -5670,14 +5569,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, nkind.N_TBANG, pf, pl, pc); + let n: *node = newnode(nkind.N_TBANG, pf, pl, pc); n.lhs = parsetype(p); return n; }; if (p.curkind == tkind.TK_STAR) { advance(p); - let n: *node = newnode(p.a, nkind.N_TPTR, pf, pl, pc); + let n: *node = newnode(nkind.N_TPTR, pf, pl, pc); n.lhs = parsetype(p); return n; }; @@ -5686,11 +5585,11 @@ fn parsetype(p: *parser) *node = { advance(p); if (p.curkind == tkind.TK_RBRACK) { advance(p); - let n: *node = newnode(p.a, nkind.N_TSLICE, pf, pl, pc); + let n: *node = newnode(nkind.N_TSLICE, pf, pl, pc); n.lhs = parsetype(p); return n; }; - let n: *node = newnode(p.a, nkind.N_TARRAY, pf, pl, pc); + let n: *node = newnode(nkind.N_TARRAY, pf, pl, pc); // `[_]T` — length inferred from initialiser. n.rhs stays nil // as the sentinel; the cgen path for nkind.N_LET fills it from the // array literal's element count. @@ -5707,7 +5606,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, nkind.N_TSTRUCT, pf, pl, pc); + let n: *node = newnode(nkind.N_TSTRUCT, pf, pl, pc); let fhead: *node = nil; let ftail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -5715,7 +5614,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, nkind.N_TFIELD, fpf, fpl, fpc); + let f: *node = newnode(nkind.N_TFIELD, fpf, fpl, fpc); let fid: str; expectident(p, &fid); f.str = fid; @@ -5736,7 +5635,7 @@ fn parsetype(p: *parser) *node = { // nkind.N_TENUMMEMBER with str=name and lhs = value expr or nil // (auto-increment when omitted). advance(p); - let n: *node = newnode(p.a, nkind.N_TENUM, pf, pl, pc); + let n: *node = newnode(nkind.N_TENUM, pf, pl, pc); if (p.curkind != tkind.TK_LBRACE) { n.lhs = parsetype(p); }; @@ -5748,7 +5647,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, nkind.N_TENUMMEMBER, mpf, mpl, mpc); + let m: *node = newnode(nkind.N_TENUMMEMBER, mpf, mpl, mpc); let mid: str; expectident(p, &mid); m.str = mid; @@ -5767,14 +5666,14 @@ fn parsetype(p: *parser) *node = { if (p.curkind == tkind.TK_VOID) { // `void` keyword in type-expr context — emit as nkind.N_TNAME so // resolution treats it like any other primitive name. - let n: *node = newnode(p.a, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TNAME, pf, pl, pc); + let n: *node = newnode(nkind.N_TNAME, pf, pl, pc); let acc: str = p.curtext; advance(p); // Dotted path collapse: pkg.Type → single TNAME with the @@ -5782,7 +5681,7 @@ fn parsetype(p: *parser) *node = { for (p.curkind == tkind.TK_DOT) { advance(p); if (p.curkind != tkind.TK_IDENT) { break; }; - acc = joindotted(p.a, acc, p.curtext); + acc = joindotted(acc, p.curtext); advance(p); }; n.str = acc; @@ -5802,7 +5701,7 @@ fn parsetype(p: *parser) *node = { let first: *node = parsetype(p); if (firstspread) { first.op = tkind.TK_ELLIPSIS; }; if (accepttok(p, tkind.TK_PIPE)) { - let n: *node = newnode(p.a, nkind.N_TTAGGED, pf, pl, pc); + let n: *node = newnode(nkind.N_TTAGGED, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -5824,7 +5723,7 @@ fn parsetype(p: *parser) *node = { expecttok(p, tkind.TK_RPAREN, "expected ')' after parenthesised type"); return first; }; - let n: *node = newnode(p.a, nkind.N_TTUPLE, pf, pl, pc); + let n: *node = newnode(nkind.N_TTUPLE, pf, pl, pc); let head: *node = first; let tail: *node = first; for (true) { @@ -5842,7 +5741,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, nkind.N_TFN, pf, pl, pc); + let n: *node = newnode(nkind.N_TFN, pf, pl, pc); // Anonymous-or-named params: parseparams handles named only; // for fn-type expressions the C parser allows IDENT-less // (anonymous) params. Stub: only named params for now. @@ -5854,7 +5753,7 @@ fn parsetype(p: *parser) *node = { errmsg(p, "expected type"); advance(p); - return newnode(p.a, nkind.N_TNAME, pf, pl, pc); + return newnode(nkind.N_TNAME, pf, pl, pc); }; // ---- expressions (Pratt) --------------------------------------------- @@ -5905,7 +5804,7 @@ fn isassignop(k: tkind) bool = { // are resolved by the two-pass checker — no body-less prototypes needed. export fn parsefile(p: *parser) *node = { - let f: *node = newnode(p.a, nkind.N_FILE, p.curfile, p.curline, p.curcol); + let f: *node = newnode(nkind.N_FILE, p.curfile, p.curline, p.curcol); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_EOF) { @@ -5988,7 +5887,6 @@ export fn parsefile(p: *parser) *node = { package parse; import os; -import mem; import tok; fn parseletlocal(p: *parser) *node = { @@ -6005,14 +5903,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, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(nkind.N_MLET, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (true) { let lpf: str = p.curfile; let lpl: i32 = p.curline; let lpc: i32 = p.curcol; - let l: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id: str; expectbindname(p, &id); l.str = id; @@ -6035,7 +5933,7 @@ fn parseletlocal(p: *parser) *node = { return m; }; - let n: *node = newnode(p.a, nkind.N_LET, pf, pl, pc); + let n: *node = newnode(nkind.N_LET, pf, pl, pc); let id: str; expectbindname(p, &id); n.str = id; @@ -6046,14 +5944,14 @@ fn parseletlocal(p: *parser) *node = { // Collects (name, type) pairs, then '=' rhs. Each binding gets // its own nkind.N_LET; the wrapping nkind.N_MLET carries the rhs. if (p.curkind == tkind.TK_COMMA) { - let m: *node = newnode(p.a, nkind.N_MLET, pf, pl, pc); + let m: *node = newnode(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, nkind.N_LET, lpf, lpl, lpc); + let l: *node = newnode(nkind.N_LET, lpf, lpl, lpc); let id2: str; expectbindname(p, &id2); l.str = id2; @@ -6085,7 +5983,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, nkind.N_BLOCK, pf, pl, pc); + let blk: *node = newnode(nkind.N_BLOCK, pf, pl, pc); let head: *node = nil; let tail: *node = nil; for (p.curkind != tkind.TK_RBRACE) { @@ -6107,7 +6005,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, nkind.N_IF, pf, pl, pc); + let n: *node = newnode(nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after if condition"); n.body = parseblock(p); @@ -6147,7 +6045,7 @@ fn parsefor(p: *parser) *node = { let npf: str = p.curfile; let npl: i32 = p.curline; let npc: i32 = p.curcol; - let e: *node = newnode(p.a, nkind.N_IDENT, npf, npl, npc); + let e: *node = newnode(nkind.N_IDENT, npf, npl, npc); let nm: str; expectbindname(p, &nm); e.str = nm; @@ -6158,7 +6056,7 @@ fn parsefor(p: *parser) *node = { }; expecttok(p, tkind.TK_RPAREN, "expected ')' in for-range names"); expecttok(p, tkind.TK_DOTDOT, "expected '..' after for-range names"); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.list = names; rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -6183,7 +6081,7 @@ fn parsefor(p: *parser) *node = { if (p.curkind == tkind.TK_DOTDOT) { advance(p); - let rng: *node = newnode(p.a, nkind.N_FORRANGE, pf, pl, pc); + let rng: *node = newnode(nkind.N_FORRANGE, pf, pl, pc); rng.str = nm; // "" for `_` rng.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after for"); @@ -6194,12 +6092,12 @@ fn parsefor(p: *parser) *node = { // Not a range — finish the let manually and continue as // a 3-clause for-init. - let first: *node = newnode(p.a, nkind.N_LET, lpf, lpl, lpc); + let first: *node = newnode(nkind.N_LET, lpf, lpl, lpc); first.str = nm; if (accepttok(p, tkind.TK_COLON)) { first.lhs = parsetype(p); }; if (accepttok(p, tkind.TK_ASSIGN)) { first.rhs = parseexpr(p); }; expecttok(p, tkind.TK_SEMI, "expected ';' after for-init let"); - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); n.lhs = first; n.cond = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after for cond"); @@ -6214,7 +6112,7 @@ fn parsefor(p: *parser) *node = { }; // for (cond) or for (cond; post) - let n: *node = newnode(p.a, nkind.N_FOR, pf, pl, pc); + let n: *node = newnode(nkind.N_FOR, pf, pl, pc); let first: *node = parseexpr(p); if (accepttok(p, tkind.TK_SEMI)) { n.cond = first; @@ -6238,7 +6136,7 @@ fn parseswitch(p: *parser) *node = { let pc: i32 = p.curcol; advance(p); // past `switch` expecttok(p, tkind.TK_LPAREN, "expected '(' after switch"); - let n: *node = newnode(p.a, nkind.N_SWITCH, pf, pl, pc); + let n: *node = newnode(nkind.N_SWITCH, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression"); expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body"); @@ -6249,7 +6147,7 @@ fn parseswitch(p: *parser) *node = { let cpl: i32 = p.curline; let cpc: i32 = p.curcol; advance(p); // past `case` - let cs: *node = newnode(p.a, nkind.N_CASE, cpf, cpl, cpc); + let cs: *node = newnode(nkind.N_CASE, cpf, cpl, cpc); let eh: *node = nil; let et: *node = nil; if (p.curkind != tkind.TK_COLON) { @@ -6277,7 +6175,7 @@ fn parseswitch(p: *parser) *node = { bt = s; }; }; - let blk: *node = newnode(p.a, nkind.N_BLOCK, cpf, cpl, cpc); + let blk: *node = newnode(nkind.N_BLOCK, cpf, cpl, cpc); blk.list = bh; cs.body = blk; if (head == nil) { head = cs; } @@ -6322,13 +6220,13 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_RETURN) { advance(p); - let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc); + let n: *node = newnode(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, nkind.N_TUPLE, pf, pl, pc); + let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = first; let tail: *node = first; for (accepttok(p, tkind.TK_COMMA)) { @@ -6346,14 +6244,14 @@ fn parsestmt(p: *parser) *node = { }; if (p.curkind == tkind.TK_DEFER) { advance(p); - let n: *node = newnode(p.a, nkind.N_DEFER, pf, pl, pc); + let n: *node = newnode(nkind.N_DEFER, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after defer"); return n; }; if (p.curkind == tkind.TK_YIELD) { advance(p); - let n: *node = newnode(p.a, nkind.N_YIELD, pf, pl, pc); + let n: *node = newnode(nkind.N_YIELD, pf, pl, pc); n.lhs = parseexpr(p); expecttok(p, tkind.TK_SEMI, "expected ';' after yield"); return n; @@ -6361,12 +6259,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, nkind.N_BREAK, pf, pl, pc); + return newnode(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, nkind.N_CONTINUE, pf, pl, pc); + return newnode(nkind.N_CONTINUE, pf, pl, pc); }; // expression statement, or tuple-destructure multi-assign: // a, b = expr; @@ -6376,7 +6274,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, nkind.N_MASSIGN, pf, pl, pc); + let m: *node = newnode(nkind.N_MASSIGN, pf, pl, pc); let head: *node = e; let tail: *node = e; for (p.curkind == tkind.TK_COMMA) { @@ -6391,7 +6289,7 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after multi-assign"); return m; }; - let n: *node = newnode(p.a, nkind.N_EXPRSTMT, pf, pl, pc); + let n: *node = newnode(nkind.N_EXPRSTMT, pf, pl, pc); n.lhs = e; expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; @@ -6404,12 +6302,11 @@ fn parsestmt(p: *parser) *node = { // the primitive types (tyvoid, tyi32, …); ww doesn't have writable // global storage yet, so we bundle the primitives into a `tctx` that // the checker passes around explicitly. typesinit fills the tctx -// once per arena. +// once per program. package ww; import os; -import mem; // ---- TypeKind --------------------------------------------------------- // Numeric values must stay aligned with cmd/wcc/ww.h TypeKind so the @@ -6518,7 +6415,6 @@ type tinfocacheent = struct { // ---- tctx — the box of primitive types ------------------------------- type tctx = struct { - a: *arena, tyvoid: *tinfo, tybool: *tinfo, tyrune: *tinfo, @@ -6549,13 +6445,13 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- -export fn newtype(a: *arena, k: tykind) *tinfo = { +export fn newtype(k: tykind) *tinfo = { let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; -fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { - let t: *tinfo = newtype(a, k); +fn prim(k: tykind, nm: str, sz: u64, al: u64) *tinfo = { + let t: *tinfo = newtype(k); t.name = nm; t.size = sz; if (al > 0u64) { t.align = al; } else { t.align = sz; }; @@ -6563,38 +6459,37 @@ fn prim(a: *arena, k: tykind, nm: str, sz: u64, al: u64) *tinfo = { return t; }; -export fn typesinit(c: *tctx, a: *arena) void = { - c.a = a; - c.tyvoid = prim(a, tykind.TY_VOID, "void", 0u64, 1u64); - c.tybool = prim(a, tykind.TY_BOOL, "bool", 1u64, 1u64); - c.tyrune = prim(a, tykind.TY_RUNE, "rune", 4u64, 4u64); - c.tyi8 = prim(a, tykind.TY_I8, "i8", 1u64, 1u64); - c.tyi16 = prim(a, tykind.TY_I16, "i16", 2u64, 2u64); - c.tyi32 = prim(a, tykind.TY_I32, "i32", 4u64, 4u64); - c.tyi64 = prim(a, tykind.TY_I64, "i64", 8u64, 8u64); - c.tyu8 = prim(a, tykind.TY_U8, "u8", 1u64, 1u64); - c.tyu16 = prim(a, tykind.TY_U16, "u16", 2u64, 2u64); - c.tyu32 = prim(a, tykind.TY_U32, "u32", 4u64, 4u64); - c.tyu64 = prim(a, tykind.TY_U64, "u64", 8u64, 8u64); - c.tyint = prim(a, tykind.TY_INT, "int", 8u64, 8u64); - c.tyuint = prim(a, tykind.TY_UINT, "uint", 8u64, 8u64); - c.tyuintptr= prim(a, tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); - c.tyf32 = prim(a, tykind.TY_F32, "f32", 4u64, 4u64); - c.tyf64 = prim(a, tykind.TY_F64, "f64", 8u64, 8u64); - c.tystr = prim(a, tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) - c.tyerr = prim(a, tykind.TY_ERR, "", 0u64, 1u64); - c.tynever = prim(a, tykind.TY_NEVER, "never", 0u64, 1u64); +export fn typesinit(c: *tctx) void = { + c.tyvoid = prim(tykind.TY_VOID, "void", 0u64, 1u64); + c.tybool = prim(tykind.TY_BOOL, "bool", 1u64, 1u64); + c.tyrune = prim(tykind.TY_RUNE, "rune", 4u64, 4u64); + c.tyi8 = prim(tykind.TY_I8, "i8", 1u64, 1u64); + c.tyi16 = prim(tykind.TY_I16, "i16", 2u64, 2u64); + c.tyi32 = prim(tykind.TY_I32, "i32", 4u64, 4u64); + c.tyi64 = prim(tykind.TY_I64, "i64", 8u64, 8u64); + c.tyu8 = prim(tykind.TY_U8, "u8", 1u64, 1u64); + c.tyu16 = prim(tykind.TY_U16, "u16", 2u64, 2u64); + c.tyu32 = prim(tykind.TY_U32, "u32", 4u64, 4u64); + c.tyu64 = prim(tykind.TY_U64, "u64", 8u64, 8u64); + c.tyint = prim(tykind.TY_INT, "int", 8u64, 8u64); + c.tyuint = prim(tykind.TY_UINT, "uint", 8u64, 8u64); + c.tyuintptr= prim(tykind.TY_UINTPTR, "uintptr", 8u64, 8u64); + c.tyf32 = prim(tykind.TY_F32, "f32", 4u64, 4u64); + c.tyf64 = prim(tykind.TY_F64, "f64", 8u64, 8u64); + c.tystr = prim(tykind.TY_STR, "str", 16u64, 8u64); // sizelint-ok: SSoT for tystr (#64) + c.tyerr = prim(tykind.TY_ERR, "", 0u64, 1u64); + c.tynever = prim(tykind.TY_NEVER, "never", 0u64, 1u64); - c.tyuntypedint = prim(a, tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); - c.tyuntypedfloat = prim(a, tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); - c.tyuntypedstr = prim(a, tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); - c.tyuntypedrune = prim(a, tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); - c.tyuntypedbool = prim(a, tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); - c.tyuntypednil = prim(a, tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); + c.tyuntypedint = prim(tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64); + c.tyuntypedfloat = prim(tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64); + c.tyuntypedstr = prim(tykind.TY_UNTYPED_STR, "untyped_str", 0u64, 1u64); + c.tyuntypedrune = prim(tykind.TY_UNTYPED_RUNE, "untyped_rune", 0u64, 1u64); + c.tyuntypedbool = prim(tykind.TY_UNTYPED_BOOL, "untyped_bool", 0u64, 1u64); + c.tyuntypednil = prim(tykind.TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64); }; -export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_PTR); +export fn typeptr(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_PTR); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -6602,8 +6497,8 @@ export fn typeptr(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_SLICE); +export fn typeslice(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_SLICE); t.sub = sub; t.size = 24u64; // sizelint-ok: SSoT for slice header (#64) t.align = 8u64; @@ -6611,8 +6506,8 @@ export fn typeslice(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_ARRAY); +export fn typearray(sub: *tinfo, n: u64) *tinfo = { + let t: *tinfo = newtype(tykind.TY_ARRAY); t.sub = sub; t.alen = n; if (sub != nil) { @@ -6629,8 +6524,8 @@ export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = { return t; }; -export fn typechan(a: *arena, sub: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_CHAN); +export fn typechan(sub: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_CHAN); t.sub = sub; t.size = 8u64; t.align = 8u64; @@ -6638,8 +6533,8 @@ export fn typechan(a: *arena, sub: *tinfo) *tinfo = { return t; }; -export fn typenamed(a: *arena, name: str, under: *tinfo) *tinfo = { - let t: *tinfo = newtype(a, tykind.TY_NAMED); +export fn typenamed(name: str, under: *tinfo) *tinfo = { + let t: *tinfo = newtype(tykind.TY_NAMED); t.name = name; t.under = under; if (under != nil) { @@ -6805,10 +6700,6 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = { package ww; -// Sibling imports (typ, ast) auto-resolve via task #22 dir-enum -// when callers `import ww;` or pull all three separately. -import mem; - // Symbol kinds — must stay numerically aligned with cmd/wcc/ww.h Skind. type skind = enum i32 { SK_NONE = 0, @@ -6846,7 +6737,6 @@ type scope = struct { last: *sym, buckets: **sym, // length = NBUCKETS nbuckets: i32, - a: *arena, }; // FNV-1a 64 — same hash the C side uses, so bucket distribution is @@ -6863,9 +6753,9 @@ fn hashstr(s: str) u64 = { return h; }; -export fn newscope(a: *arena, parent: *scope) *scope = { +export fn newscope(parent: *scope) *scope = { let buckets_sl: []*sym = alloc([], NBUCKETS: u64)!; - let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS, a=a})!; + let s: *scope = alloc(scope{parent=parent, first=nil, last=nil, buckets=buckets_sl.ptr, nbuckets=NBUCKETS})!; return s; }; @@ -7062,11 +6952,9 @@ export fn scopedefineinmodule(s: *scope, name: str, mod: str, k: skind, t: *tinf package wcc; import os; -import mem; import tok; type checker = struct { - a: *arena, tc: *tctx, top: *scope, cur: *scope, @@ -7114,11 +7002,11 @@ fn seedprimitives(c: *checker) void = { // separate alias chain — see collectaliases in cgen.ww for the // companion seed. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; - let nomemdecl: *node = newnode(c.a, nkind.N_TYPEDECL, empty, 0, 0); + let nomemdecl: *node = newnode(nkind.N_TYPEDECL, empty, 0, 0); nomemdecl.str = "nomem"; nomemdecl.lhs = bang; scopedefine(c.top, "nomem", skind.SK_TYPE, nil, nomemdecl); @@ -7392,7 +7280,7 @@ fn resolvewalk(c: *checker, n: *node) void = { if (k == nkind.N_MCASE) { if (n.lhs != nil) { resolvewalk(c, n.lhs); }; let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let nm: str = n.str; if (nm.len > 0) { checkmoduleshadow(c, nm, "binding"); @@ -7414,7 +7302,7 @@ fn resolvewalk(c: *checker, n: *node) void = { // Mirrors cstage cstmt N_BLOCK at cmd/wcc/check.c:1559-1566. if (k == nkind.N_BLOCK) { let outer: *scope = c.cur; - c.cur = newscope(c.a, outer); + c.cur = newscope(outer); let m: *node = n.list; for (m != nil) { resolvewalk(c, m); @@ -7693,7 +7581,7 @@ fn scruttype(c: *checker, e: *node) *node = { // 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, nkind.N_TNAME, "", 0, 0); + let n: *node = newnode(nkind.N_TNAME, "", 0, 0); n.str = nm; return n; }; @@ -7880,7 +7768,7 @@ fn astoffset(c: *checker, dot: *node) i64 = { // wwstage cgen only reads `uval` for N_INTLIT codegen so `str` is // just for the AST printer, but set it for parity with the parser's // own literal-emit shape. -fn arenau64tos(a: *arena, v: u64) str = { +fn arenau64tos(v: u64) str = { let buf: []u8 = alloc([], 24u64)!; let i: i32 = 23; buf[i] = 0u8; @@ -7904,7 +7792,7 @@ fn arenau64tos(a: *arena, v: u64) str = { fn foldtointlit(c: *checker, n: *node, v: i64) void = { n.kind = nkind.N_INTLIT; n.uval = v: u64; - n.str = arenau64tos(c.a, v: u64); + n.str = arenau64tos(v: u64); n.lhs = nil; n.list = nil; let empty: str; @@ -8056,11 +7944,11 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // site that needs iserror discrimination. r = tinfofornode(c, n.lhs); } else { if (k == nkind.N_TPTR) { - r = typeptr(c.a, tinfofornode(c, n.lhs)); + r = typeptr(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TSLICE) { - r = typeslice(c.a, tinfofornode(c, n.lhs)); + r = typeslice(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TCHAN) { - r = typechan(c.a, tinfofornode(c, n.lhs)); + r = typechan(tinfofornode(c, n.lhs)); } else { if (k == nkind.N_TARRAY) { // Cstage cmd/wcc/check.c:314-326: length must be an integer // literal (`[_]T` keeps alen=0 as the inferred-length sentinel @@ -8076,14 +7964,14 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (n.rhs.kind == nkind.N_INTLIT) { elen = n.rhs.uval; }; }; let sub: *tinfo = tinfofornode(c, n.lhs); - r = typearray(c.a, sub, elen); + r = typearray(sub, elen); } else { if (k == nkind.N_TFN) { // Cstage cmd/wcc/check.c:437-466: function types are 8B / 8B // (call-target pointer shape). Pre-bind before recursing into // the return type so a recursive `type F = fn() F` self-ref // doesn't spin (cycle-break mirror of the TSTRUCT/TTAGGED // pattern below). - r = newtype(c.a, tykind.TY_FN); + r = newtype(tykind.TY_FN); r.size = 8u64; r.align = 8u64; r.slotsize = 8u64; @@ -8094,7 +7982,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads // to 8B per its stack-slot contract; tinfo.size carries the // raw storage width so size(EnumT) folds to the correct value. - r = newtype(c.a, tykind.TY_ENUM); + r = newtype(tykind.TY_ENUM); let storage: *tinfo = nil; if (n.lhs != nil) { storage = tinfofornode(c, n.lhs); }; if (storage == nil) { storage = c.tc.tyi32; }; @@ -8113,7 +8001,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // slotsize TTUPLE — narrow scalars pad to 8 (cgen spills each // tuple element into its own register / stack-slot eightbyte), // composites contribute their own ti.slotsize. - r = newtype(c.a, tykind.TY_TUPLE); + r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); let total: u64 = 0u64; let slottotal: u64 = 0u64; @@ -8151,7 +8039,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // struct; size-derived alignment; final round to 8). That // slot total lands in ti.slotsize so the cgen fast-path can // graduate TY_STRUCT off the AST walker. - r = newtype(c.a, tykind.TY_STRUCT); + r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); let off: u64 = 0u64; let maxalign: u64 = 1u64; @@ -8193,7 +8081,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // Cstage cmd/wcc/check.c:347-435: 8B tag + max(variant) // rounded up to 8. Pre-bind for cycle protection (recursive // sum-type shapes through NAMED variants). - r = newtype(c.a, tykind.TY_TAGGED); + r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors @@ -8352,11 +8240,11 @@ fn exprtype(c: *checker, e: *node) *node = { if (e.list.list == nil) { if (e.list.next != nil) { if (e.list.next.next == nil) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = mktname(c, "u8"); let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; return tt; }; @@ -8366,11 +8254,11 @@ fn exprtype(c: *checker, e: *node) *node = { // Value form: `alloc(value)`. if (e.list.next == nil) { let argt: *node = exprtype(c, e.list); - let ptr: *node = newnode(c.a, nkind.N_TPTR, "", 0, 0); + let ptr: *node = newnode(nkind.N_TPTR, "", 0, 0); ptr.lhs = argt; let nome: *node = mktname(c, "nomem"); ptr.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = ptr; return tt; }; @@ -8887,14 +8775,14 @@ fn checkletassign(c: *checker, n: *node) void = { }; }; if (!shadowed) { - let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0); sl.lhs = n.lhs.lhs; if (wrapped) { src = sl; } else { let nome: *node = mktname(c, "nomem"); sl.next = nome; - let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0); + let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0); tt.list = sl; src = tt; }; @@ -9085,7 +8973,7 @@ fn installparams(c: *checker, params: *node) void = { // per-statement scopes. fn resolvefnbody(c: *checker, fnnode: *node) void = { let outer: *scope = c.cur; - c.cur = newscope(c.a, c.cur); + c.cur = newscope(c.cur); installparams(c, fnnode.list); // #61 audit §1.8 — A.2: walk each param's declared type-expr so // tinfofornode stamps n.type_ on it. installparams binds the name @@ -9107,10 +8995,9 @@ fn resolvefnbody(c: *checker, fnnode: *node) void = { c.cur = outer; }; -export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = { - c.a = a; +export fn checkinit(c: *checker, tc: *tctx) void = { c.tc = tc; - c.top = newscope(a, nil); + c.top = newscope(nil); c.cur = c.top; c.nresolved = 0; c.nunresolved = 0; @@ -9441,7 +9328,6 @@ fn dynamicgrow(m: *state, need: i32) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -9456,7 +9342,7 @@ import strconv; // (caller side) both advertise their effective type as []ELEM — // every isslicetype / nodeisslice check then succeeds naturally. fn slicewrap(c: *cgen, elem: *node) *node = { - let s: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0); + let s: *node = newnode(nkind.N_TSLICE, "", 0, 0); s.lhs = elem; return s; }; @@ -13439,7 +13325,6 @@ fn cgstructlitfillbp(c: *cgen, si: *structinfo, lit: *node, bpoff: i32) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -16596,7 +16481,7 @@ fn cgcall(c: *cgen, n: *node) void = { emitline("\tMOVQ\tAX, "); emitoff((soff + 16): i64); emitline("(BP)\n"); - let sn: *node = newnode(c.a, nkind.N_IDENT, + let sn: *node = newnode(nkind.N_IDENT, "", 0, 0); sn.str = sname; if (prevarg == nil) { n.list = sn; } @@ -19235,7 +19120,6 @@ fn cgassign(c: *cgen, n: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -20878,7 +20762,6 @@ fn cgcontinue(c: *cgen, n: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -21204,7 +21087,7 @@ fn cgfnparams(c: *cgen, params: *node) void = { }; fn cgfn(c: *cgen, fn_: *node) void = { - cgeninit(c, c.a); + cgeninit(c); c.fnname = fn_.str; c.curmod = fn_.nmod; c.fnret = fn_.lhs; @@ -21348,7 +21231,6 @@ export fn cgfile(c: *cgen, file: *node) void = { package wcc; import os; -import mem; import ast; import tok; import typ; @@ -21391,9 +21273,9 @@ fn collectaliases(c: *cgen, file: *node) void = { // same-module / any-match passes in aliaslookup then let a local // `type nomem = !void;` shadow this fallback within its module. let empty: str; - let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0); + let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0); tnvoid.str = "void"; - let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0); + let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0); bang.lhs = tnvoid; let nomemal: *aliasent = alloc(aliasent{aname="nomem", amod=empty, target=bang, aanext=nil})!; c.aliases = nomemal; @@ -21758,7 +21640,6 @@ def LOOP_MAX: i32 = 16; def DEFER_MAX: i32 = 16; type cgen = struct { - a: *arena, locals: *local, // atlocals — persistent registry of `@`-prefix scratch slots // for the current fn. cgblock save/restores c.locals to scope @@ -21845,8 +21726,7 @@ type letvar = struct { lvnext: *letvar, }; -fn cgeninit(c: *cgen, a: *arena) void = { - c.a = a; +fn cgeninit(c: *cgen) void = { c.locals = nil; c.atlocals = nil; c.frame = 0; @@ -23371,7 +23251,6 @@ export fn fargregname(i: i32) str = { package main; import os; -import mem; import tok; import lex; import ast; @@ -23458,7 +23337,6 @@ export fn main(argc: i32, argv: **u8) i32 = { }; }; - let a: *arena = newarena(); let buf: []u8 = alloc([], sz: u64)!; buf.len = sz: i32; let rr: (i64 | os.oserror) = os.readall(fd, buf.ptr, sz: u64); @@ -23477,7 +23355,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; let l: lex; - lexinit(&l, a, argstr(path), buf.ptr, sz: u64); + lexinit(&l, argstr(path), buf.ptr, sz: u64); if (mode == 116) { // '-t' for (true) { @@ -23489,17 +23367,17 @@ export fn main(argc: i32, argv: **u8) i32 = { }; } else { if (mode == 97) { // '-a' let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); astprint(1i32, f); } else { if (mode == 114) { // '-r' — name resolve report let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); let tc: tctx; - typesinit(&tc, a); + typesinit(&tc); let ck: checker; - checkinit(&ck, a, &tc); + checkinit(&ck, &tc); // Quiet by default; flip to 1 when debugging missing names. ck.verbose = 0; checkfile(&ck, f); @@ -23517,7 +23395,7 @@ export fn main(argc: i32, argv: **u8) i32 = { if (ck.nunresolved > 0) { return 1; }; } else { if (mode == 99) { // '-c' — codegen / emit asm let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); // #50: mirror w6c — run check before cgen so AST mutations // from #42 (size/align/offset fold) and audit §1.8 (node.type_ @@ -23525,13 +23403,13 @@ export fn main(argc: i32, argv: **u8) i32 = { // (the byte-identity probe for 994) would diverge from w6c_ww // on any program that uses the size/align/offset typed builtins. let tc: tctx; - typesinit(&tc, a); + typesinit(&tc); let ck: checker; - checkinit(&ck, a, &tc); + checkinit(&ck, &tc); checkfile(&ck, f); if (ck.errs > 0) { return 1; }; let cg: cgen; - cgeninit(&cg, a); + cgeninit(&cg); cgfile(&cg, f); };};};}; diff --git a/selfhost/cmd/wwdump/main.ww b/selfhost/cmd/wwdump/main.ww index 58ca9130..4c8a1972 100644 --- a/selfhost/cmd/wwdump/main.ww +++ b/selfhost/cmd/wwdump/main.ww @@ -12,7 +12,6 @@ package main; import os; -import mem; import tok; import lex; import ast; @@ -99,7 +98,6 @@ export fn main(argc: i32, argv: **u8) i32 = { }; }; - let a: *arena = newarena(); let buf: []u8 = alloc([], sz: u64)!; buf.len = sz: i32; let rr: (i64 | os.oserror) = os.readall(fd, buf.ptr, sz: u64); @@ -118,7 +116,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; let l: lex; - lexinit(&l, a, argstr(path), buf.ptr, sz: u64); + lexinit(&l, argstr(path), buf.ptr, sz: u64); if (mode == 116) { // '-t' for (true) { @@ -130,17 +128,17 @@ export fn main(argc: i32, argv: **u8) i32 = { }; } else { if (mode == 97) { // '-a' let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); astprint(1i32, f); } else { if (mode == 114) { // '-r' — name resolve report let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); let tc: tctx; - typesinit(&tc, a); + typesinit(&tc); let ck: checker; - checkinit(&ck, a, &tc); + checkinit(&ck, &tc); // Quiet by default; flip to 1 when debugging missing names. ck.verbose = 0; checkfile(&ck, f); @@ -158,7 +156,7 @@ export fn main(argc: i32, argv: **u8) i32 = { if (ck.nunresolved > 0) { return 1; }; } else { if (mode == 99) { // '-c' — codegen / emit asm let ps: parser; - parserinit(&ps, a, &l); + parserinit(&ps, &l); let f: *node = parsefile(&ps); // #50: mirror w6c — run check before cgen so AST mutations // from #42 (size/align/offset fold) and audit §1.8 (node.type_ @@ -166,13 +164,13 @@ export fn main(argc: i32, argv: **u8) i32 = { // (the byte-identity probe for 994) would diverge from w6c_ww // on any program that uses the size/align/offset typed builtins. let tc: tctx; - typesinit(&tc, a); + typesinit(&tc); let ck: checker; - checkinit(&ck, a, &tc); + checkinit(&ck, &tc); checkfile(&ck, f); if (ck.errs > 0) { return 1; }; let cg: cgen; - cgeninit(&cg, a); + cgeninit(&cg); cgfile(&cg, f); };};};}; diff --git a/selfhost/test/sym_link.ww b/selfhost/test/sym_link.ww index fa922b1c..c1507388 100644 --- a/selfhost/test/sym_link.ww +++ b/selfhost/test/sym_link.ww @@ -1,20 +1,16 @@ // selfhost/test/sym_link.ww — link-and-run probe for the ww-cgen -// against the sym/typ/ast/mem dep stack. Exercises arena (mem), -// hashtable scope (sym), and pulls in typ/ast as type carriers. +// against the sym/typ/ast dep stack. Exercises hashtable scope +// (sym), and pulls in typ/ast as type carriers. // Returns 42 on success; smaller values name the probe that broke. package test; -import mem; import typ; import ast; import sym; export fn main() i32 = { - let a: *arena = newarena(); - if (a == nil) { return 1; }; - - let s: *scope = newscope(a, nil); + let s: *scope = newscope(nil); if (s == nil) { return 2; }; let n1: str = "foo"; @@ -42,6 +38,5 @@ export fn main() i32 = { let l3: *sym = scopelookup(s, n3); if (l3 != nil) { return 10; }; - freearena(a); return 42; };