ww: preserve command package identities
This commit is contained in:
@@ -67,6 +67,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
let testsupport: *u8 = nil;
|
||||
let testmode: i32 = 0i32; // #15: `-T` test-mode
|
||||
let testpackage: i32 = 0i32;
|
||||
let commandpackage: i32 = 0i32;
|
||||
let entrymode: i32 = 0i32;
|
||||
let sepmode: i32 = 0i32; // -c: #22 M3 separate-compile / primary-
|
||||
// only codegen (emit imported==0 decls
|
||||
@@ -100,6 +101,8 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
testmode = 1i32;
|
||||
} else { if (cstreq(a, "--test-package")) {
|
||||
testpackage = 1i32;
|
||||
} else { if (cstreq(a, "--command-package")) {
|
||||
commandpackage = 1i32;
|
||||
} else { if (cstreq(a, "--entry")) {
|
||||
entrymode = 1i32;
|
||||
} else { if (cstreq(a, "--test-support-module")) {
|
||||
@@ -133,12 +136,12 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
return 2;
|
||||
};
|
||||
src = a;
|
||||
}; }; }; }; }; }; }; }; };
|
||||
}; }; }; }; }; }; }; }; }; };
|
||||
i += 1;
|
||||
};
|
||||
|
||||
if (src == nil) {
|
||||
let m: str = "usage: w6c_ww [-T|--test-package] [--entry] [-c] [-I out.wwi] [--import path dep.wwi]... [-o out.s] file.ww\n";
|
||||
let m: str = "usage: w6c_ww [-T|--test-package] [--command-package] [--entry] [-c] [-I out.wwi] [--import path dep.wwi]... [-o out.s] file.ww\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
return 2;
|
||||
};
|
||||
@@ -147,8 +150,9 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
return 2;
|
||||
};
|
||||
if ((entrymode != 0 || testpackage != 0) && sepmode == 0) {
|
||||
let m: str = "w6c: --entry and --test-package require -c\n";
|
||||
if ((entrymode != 0 || testpackage != 0 || commandpackage != 0)
|
||||
&& sepmode == 0) {
|
||||
let m: str = "w6c: --entry, --test-package, and --command-package require -c\n";
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
return 2;
|
||||
};
|
||||
@@ -233,6 +237,9 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
let ps: parser;
|
||||
parserinit(&ps, &l);
|
||||
if (testsupport != nil) { ps.testmodule = pathstr(testsupport); };
|
||||
// Entry compilation classifies an ordinary command package. The explicit
|
||||
// marker carries only that parser fact for non-entry command test variants.
|
||||
ps.commandpackage = commandpackage != 0 || entrymode != 0;
|
||||
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
|
||||
|
||||
@@ -899,6 +899,33 @@ fn sepimportbasevalid(base: *u8) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Go-style command packages keep their canonical import identity while
|
||||
// declaring main; an external command-test variant declares main_test. These
|
||||
// declarations classify package kind but never enter action identity.
|
||||
fn sepcommanddeclaredname(p: *seppkg) bool = {
|
||||
if (p.name == nil) { return false; };
|
||||
if (p.variant == SEP_VARIANT_EXTERNAL) {
|
||||
return cstreqlit(p.name, "main_test");
|
||||
};
|
||||
return cstreqlit(p.name, "main");
|
||||
};
|
||||
|
||||
fn sepforbiddencommandimport(g: *sepgraph, importer: i32, dep: i32) bool = {
|
||||
let from: *seppkg = &g.pkg[importer];
|
||||
let to: *seppkg = &g.pkg[dep];
|
||||
if (to.name == nil || !cstreqlit(to.name, "main")
|
||||
|| to.role != SEP_ROLE_NORMAL) { return false; };
|
||||
// An external test's exact colocated production edge is variant wiring,
|
||||
// not a general source-importable command-package alias.
|
||||
return !(from.variant == SEP_VARIANT_EXTERNAL
|
||||
&& sepcommanddeclaredname(from)
|
||||
&& cstreq(from.canon, to.canon));
|
||||
};
|
||||
|
||||
fn sepcommandcompilermarker(g: *sepgraph, pi: i32) bool = {
|
||||
return sepcommanddeclaredname(&g.pkg[pi]) && !g.pkg[pi].linkentry;
|
||||
};
|
||||
|
||||
// Bind a provisional directory action to its canonical ordinary import
|
||||
// identity. The compiler path is derived from that base and the semantic
|
||||
// variant; root/product/artifact state never participates.
|
||||
@@ -1458,7 +1485,8 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, searchpath: *u8,
|
||||
sepbindadd(bindings, 'D': u8, u.usepath, ipath);
|
||||
let self: bool = os.samefile(pathstr(ipath),
|
||||
pathstr(g.pkg[pi].entry));
|
||||
if (self && sepexternalname(&g.pkg[pi], idp, idn, true)) {
|
||||
if (self && (sepexternalname(&g.pkg[pi], idp, idn, true)
|
||||
|| sepcommanddeclaredname(&g.pkg[pi]))) {
|
||||
externalproduction = true;
|
||||
};
|
||||
if (self && !externalproduction) {
|
||||
@@ -1719,7 +1747,8 @@ fn seploadpkg(g: *sepgraph, pi: i32, context: i32) i32 = {
|
||||
if (g.pkg[pi].path[j] == '.') { leaf = g.pkg[pi].path + j + 1u64; };
|
||||
j += 1u64;
|
||||
};
|
||||
if (!cstreq(g.pkg[pi].name, leaf)) {
|
||||
if (!cstreq(g.pkg[pi].name, leaf)
|
||||
&& !sepcommanddeclaredname(&g.pkg[pi])) {
|
||||
cerr("ww: package ");
|
||||
cerr(pathstr(g.pkg[pi].name));
|
||||
cerr(" does not match import path ");
|
||||
@@ -1765,7 +1794,17 @@ fn seploadpkg(g: *sepgraph, pi: i32, context: i32) i32 = {
|
||||
g.pkg[pi].contextstate[context] = 2u8;
|
||||
let k: i32 = 0;
|
||||
for (k < g.pkg[pi].ndeps) {
|
||||
if (seploadpkg(g, g.pkg[pi].deps[k], context) < 0) {
|
||||
let dep: i32 = g.pkg[pi].deps[k];
|
||||
if (seploadpkg(g, dep, context) < 0) {
|
||||
g.pkg[pi].failed = true;
|
||||
return -1;
|
||||
};
|
||||
if (dep != pi && sepforbiddencommandimport(g, pi, dep)) {
|
||||
cerr("ww: package ");
|
||||
if (g.pkg[dep].path[0u64] != 0u8) {
|
||||
cerr(pathstr(g.pkg[dep].path));
|
||||
} else { cerr(pathstr(g.pkg[dep].canon)); };
|
||||
cerr(" is a program, not an importable package\n");
|
||||
g.pkg[pi].failed = true;
|
||||
return -1;
|
||||
};
|
||||
@@ -1997,7 +2036,8 @@ fn sepfinalizedirectoryidentities(g: *sepgraph) i32 = {
|
||||
let supportalias: bool = p.role == SEP_ROLE_TEST_SUPPORT
|
||||
&& cstreqlit(p.path, SEP_TEST_SUPPORT_MODULE)
|
||||
&& cstreqlit(p.name, "test");
|
||||
if (!supportalias && !cstreq(p.name, leaf)) {
|
||||
if (!supportalias && !cstreq(p.name, leaf)
|
||||
&& !sepcommanddeclaredname(p)) {
|
||||
cerr("ww: package "); cerr(pathstr(p.name));
|
||||
cerr(" does not match import path "); cerr(pathstr(p.path));
|
||||
cerr("\n");
|
||||
@@ -2969,12 +3009,14 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let gent: bool = g.pkg[pi].generatedmain || rawtest;
|
||||
let testpkg: bool = g.pkg[pi].variant == SEP_VARIANT_SAME_TEST
|
||||
|| g.pkg[pi].variant == SEP_VARIANT_EXTERNAL;
|
||||
let commandpkg: bool = sepcommandcompilermarker(g, pi);
|
||||
let entry: bool = g.pkg[pi].linkentry;
|
||||
let supportpkg: bool = g.pkg[pi].testsupport;
|
||||
let alen: u64 = 8u64;
|
||||
if (gent) { alen += 4u64; }
|
||||
else {
|
||||
if (testpkg) { alen += 1u64; };
|
||||
if (commandpkg) { alen += 1u64; };
|
||||
if (entry) { alen += 1u64; };
|
||||
if (supportpkg) { alen += 2u64; };
|
||||
};
|
||||
@@ -2988,6 +3030,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
append(argv, testsupportmodule);
|
||||
} else {
|
||||
if (testpkg) { append(argv, "--test-package"); };
|
||||
if (commandpkg) { append(argv, "--command-package"); };
|
||||
if (entry) { append(argv, "--entry"); };
|
||||
if (supportpkg) {
|
||||
append(argv, "--test-support-module");
|
||||
|
||||
Reference in New Issue
Block a user