wwi: derive decl-less module's .wwi package leaf from parse-stamped path (#11)

wwi_emit took the .wwi `package` leaf from the first primary decl's module tag;
a fully empty primary module body (zero decls) had none, so the leaf stayed the
literal default "main" and the importer rejected it ("package main does not
match import path <leaf>"). The module identity is only available at parse time
(curmod is overwritten by imported //ww:module sections before emit), so stamp
the primary path onto the N_FILE node (TK_MODULE and TK_MODRESET rp!=NULL sites,
only-if-empty so a bare-reset `package main` root stays "main") and, when the
decl-scan finds no leaf, fall back to that stamped path. Symmetric cstage+
selfhost; both detect scan-miss via the same found-flag so the emitted .wwi
stays byte-identical.

Regression: test/wcc/989_wwileaf_run.c, table-driven over {empty body,
comment-only, nested a.b.c} decl-less shapes, non-vacuity proven.
This commit is contained in:
2026-06-22 21:17:30 +09:00
parent a1484aef28
commit 6525e137ae
6 changed files with 352 additions and 4 deletions

View File

@@ -587,6 +587,7 @@ export fn wwiemit(c: *checker, file: *syntax.node, path: str) i32 = {
// package line: leaf of the first primary decl's module tag.
let pkg: str = "main";
let found: i32 = 0;
let pd: *syntax.node = file.list;
for (pd != nil) {
if (wwiprimary(pd) && pd.nmod.len > 0) {
@@ -604,11 +605,35 @@ export fn wwiemit(c: *checker, file: *syntax.node, path: str) i32 = {
} else {
pkg = pd.nmod;
};
found = 1;
pd = nil;
} else {
pd = pd.next;
};
};
// #11: a decl-less / export-less primary body carries no
// module-tagged decl, so the scan above finds nothing; fall back to
// the primary module identity stamped on the N_FILE node at parse
// time. A real root `package main` arrives via a bare module-reset
// and leaves file.nmod empty, so it stays "main". The detector is
// scan-miss (found==0), NOT pkg=="main", to match cstage byte-for-
// byte (rule 10) when a tagged decl legitimately leafs to "main".
if (found == 0 && file.nmod.len > 0) {
let dotidx: i32 = -1;
let i: i32 = 0;
for (i < file.nmod.len) {
if (file.nmod[i] == 46u8) { dotidx = i; };
i += 1;
};
if (dotidx >= 0) {
let leaf: str;
leaf.ptr = file.nmod.ptr + ((dotidx + 1): u64);
leaf.len = file.nmod.len - dotidx - 1;
pkg = leaf;
} else {
pkg = file.nmod;
};
};
wputs(fd, "package ");
wputs(fd, pkg);
wputs(fd, ";\n");