ww: implement package initialization

This commit is contained in:
2026-08-14 19:02:35 +09:00
parent 72e890d5aa
commit c6bec0914d
24 changed files with 5279 additions and 1009 deletions

View File

@@ -509,6 +509,7 @@ type cgen = struct {
// root entry stays bare. Like sepmode, NOT reset by cgeninit (per-fn).
// Symmetric with cstage Cg.sep_isdep.
sepisdep: i32,
initdispatchsymbol: str, // root-owned complete package-init schedule
};
// Top-level mutable `let` registry. Mirrors cmd/w6c/cgen.c LetVar.
@@ -741,6 +742,17 @@ fn localfind(c: *cgen, name: str) i32 = {
let cgoutstream: memio.stream;
let cgoutmode: i32 = 0;
let cgoutinit: i32 = 0;
let cgwritefailed: i32 = 0;
fn cgwrite(p: *u8, n: u64) void = {
if (cgwritefailed != 0) { return; };
match (os.writeall(1i32, p, n)) {
case let wrote: i64 => {
if (wrote < 0 || (wrote: u64) != n) { cgwritefailed = 1; };
};
case let e: os.oserror => cgwritefailed = 1;
};
};
fn cgout_enable() void = {
if (cgoutinit == 0) {
@@ -754,7 +766,7 @@ fn cgout_disable() void = { cgoutmode = 0; };
fn cgout_flush() void = {
if (cgoutstream.pos > 0) {
os.write(1, cgoutstream.ptr, cgoutstream.pos: u64);
cgwrite(cgoutstream.ptr, cgoutstream.pos: u64);
memio.reset(&cgoutstream);
};
};
@@ -769,7 +781,7 @@ fn emitbytes(p: *u8, n: u64) void = {
// lib/log/log.ww stdprintln. #94 fold-eFinal.
io.write(&cgoutstream.vt, buf);
} else {
os.write(1, p, n);
cgwrite(p, n);
};
};
@@ -2894,6 +2906,35 @@ fn emittupledata(c: *cgen, name: str, module: str, tt: *syntax.node, rhs: *synta
return true;
};
fn emitinitbackings(n: *syntax.node) void = {
for (n != nil) {
if (n.kind == syntax.nkind.N_ARRLIT && n.linksym.len > 0) {
let u: *syntax.tinfo = tichase(n.type_: *syntax.tinfo);
if (u == nil || u.kind != syntax.tykind.TY_ARRAY) {
let msg: str = "runtime package slice backing has no array type\n";
os.write(2, msg.ptr, msg.len: u64);
os.exit(1);
};
emitline("DATAW ");
emitbytes(n.linksym.ptr, n.linksym.len: u64);
emitline("(SB),\"");
let count: u64 = u.size;
if (count == 0u64) { count = 1u64; };
let i: u64 = 0u64;
for (i < count) { emitdatawbyte(0u8); i += 1u64; };
emitline("\"\n");
};
emitinitbackings(n.attr);
emitinitbackings(n.lhs);
emitinitbackings(n.rhs);
emitinitbackings(n.cond);
emitinitbackings(n.body);
emitinitbackings(n.els);
emitinitbackings(n.list);
n = n.next;
};
};
fn emitletdataw(c: *cgen, file: *syntax.node) void = {
let savedmod: str = c.curmod;
let savedsource: i32 = c.cursource;
@@ -3458,6 +3499,10 @@ fn collectfnrets(c: *cgen, file: *syntax.node) void = {
let d: *syntax.node = file.list;
for (d != nil) {
if (d.kind == syntax.nkind.N_FNDECL) {
if (d.initfn != 0 || d.initsynthetic != 0) {
d = d.next;
continue;
};
let f: *fnret = alloc(fnret{fname=d.str, fmod=d.nmod, rtype=d.lhs, params=d.list, frnext=c.fnrets})!;
c.fnrets = f;
};
@@ -3788,12 +3833,16 @@ fn collectmods(c: *cgen, file: *syntax.node) void = {
let d: *syntax.node = file.list;
for (d != nil) {
// M1 #22: record alias→path for the qualified-ref hint.
if (d.kind == syntax.nkind.N_USE) {
if (d.kind == syntax.nkind.N_USE && d.useblank == 0) {
if (d.usepath.len > 0) {
let um: *modent = alloc(modent{mname=d.str, nmod=d.usepath, omod=d.nmod, sourceid=d.sourceid, mnext=c.uses})!;
c.uses = um;
};
};
if (d.initfn != 0 || d.initsynthetic != 0) {
d = d.next;
continue;
};
// Mirror collectfnrets' shape exactly (plain prepend in one
// branch). Earlier nested-if/early-return variants tickled a
// wwstage cgen bug that dropped most prepends.
@@ -3988,6 +4037,10 @@ fn fficollect(c: *cgen, file: *syntax.node) void = {
let d: *syntax.node = file.list;
for (d != nil) {
if (d.kind == syntax.nkind.N_FNDECL) {
if (d.initfn != 0 || d.initsynthetic != 0) {
d = d.next;
continue;
};
let a: *syntax.node = d.attr;
for (a != nil) {
if (a.kind == syntax.nkind.N_ATTR) {