ww: select build action from package declaration

This commit is contained in:
2026-08-13 13:36:10 +09:00
parent 61a2ee5221
commit dab3cb4998
61 changed files with 872 additions and 157 deletions

View File

@@ -984,7 +984,7 @@ fn mkdirall(path: str) void = {
" assert(pkg.second() == 9);\n};\n"));
let prodout: str = strings.concat(root, "/production.a");
let prodav: []str = [driver("ww"), "build", "-p", "-I", root,
let prodav: []str = [driver("ww"), "build", "-I", root,
"-o", prodout, pkg];
let out: commandout;
runcommand(root, "production-build", prodav,
@@ -2094,7 +2094,7 @@ fn mkdirall(path: str) void = {
if (rsi == 1) { uniondriver = wwtracedriver; };
let rootout: str = strings.concat(root, "/root-only-",
rootstages[rsi], ".a");
let rootav: []str = [driver(rootstages[rsi]), "build", "-p",
let rootav: []str = [driver(rootstages[rsi]), "build",
"-I", root, "-o", rootout, aaroot];
runcommand(root, strings.concat("root-only-", rootstages[rsi]), rootav,
(60i64 * (time.second: i64)): time.duration, &out);
@@ -3942,7 +3942,7 @@ fn mkdirall(path: str) void = {
let rootout: str = strings.concat(root, "/long-root-",
rootlabels[ri], "-", tags[si], ".a");
clean(compilertrace); writefile(compilertrace, "");
let rootav: []str = [driver(stages[si]), "build", "-p", "-I",
let rootav: []str = [driver(stages[si]), "build", "-I",
source, "-o", rootout, rootspellings[ri]];
runcommandenv(root, strings.concat("long-root-", rootlabels[ri],
"-", tags[si]), rootav, env,
@@ -4232,7 +4232,7 @@ fn mkdirall(path: str) void = {
clean(trace);
writefile(trace, "");
let importout: str = strings.concat(root, "/importer-", stages[si], ".a");
let importav: []str = [driver(stages[si]), "build", "-p", "-I", source,
let importav: []str = [driver(stages[si]), "build", "-I", source,
"-o", importout, importer];
runcommandenv(root, strings.concat("command-import-", stages[si]),
importav, env, (60i64 * (time.second: i64)): time.duration, &out);
@@ -4351,7 +4351,7 @@ fn mkdirall(path: str) void = {
let identitydiagnostics: []str = ["", ""];
i = 0;
for (i < stages.len) {
let av: []str = [driver(stages[i]), "build", "-p", "-I", root,
let av: []str = [driver(stages[i]), "build", "-I", root,
"-o", strings.concat(root, "/bad-identity-", stages[i], ".a"),
identityroot];
runcommandenv(root, strings.concat("duplicate-directory-identity-",
@@ -4372,7 +4372,7 @@ fn mkdirall(path: str) void = {
let reserveddiagnostics: []str = ["", ""];
i = 0;
for (i < stages.len) {
let av: []str = [driver(stages[i]), "build", "-p", "-I", root,
let av: []str = [driver(stages[i]), "build", "-I", root,
"-o", strings.concat(root, "/bad-reserved-", stages[i], ".a"),
reserved];
runcommandenv(root, strings.concat("reserved-local-import-", stages[i]),
@@ -4843,7 +4843,7 @@ fn runtimepath(relative: str) str = {
writefile(strings.concat(extra, "/extra.ww"),
"package extra;\nexport fn marker() i32 = { return 7; };\n");
let extralib: str = strings.concat(root, "/libextra.a");
let libav: []str = [driver("ww"), "build", "-p", "-o", extralib,
let libav: []str = [driver("ww"), "build", "-o", extralib,
extra];
let out: commandout;
runcommand(root, "link-flags-library", libav,

View File

@@ -150,7 +150,7 @@ fn samefile(a: str, b: str, why: str) void = {
"late/example/foo", "late/example/foo", fooalias, fooalias];
i = 0;
for (i < rootouts.len) {
let rav: []str = [testenv.driver(rootdrivers[i]), "build", "-p",
let rav: []str = [testenv.driver(rootdrivers[i]), "build",
"-I", early, "-I", late, "-o", rootouts[i], roottargets[i]];
expectcode(td, strings.concat("foo_root_", roottags[i]), rav, 0);
let rw: str = strings.concat(rootouts[i], ".sepwork/");

View File

@@ -166,9 +166,9 @@ fn rejectstable(dir: str, label: str, target: str, needle: str) void = {
"fn hidden() i32 = { return 99; };\n"));
let ca: str = strings.concat(td, "/libonly-c.a");
let wa: str = strings.concat(td, "/libonly-w.a");
let cav: []str = [testenv.driver("ww"), "build", "-p", "-I", td,
let cav: []str = [testenv.driver("ww"), "build", "-I", td,
"-o", ca, lib];
let wav: []str = [testenv.driver("ww_ww"), "build", "-p", "-I", td,
let wav: []str = [testenv.driver("ww_ww"), "build", "-I", td,
"-o", wa, lib];
if (code(td, "build_package_c", cav) != 0
|| code(td, "build_package_w", wav) != 0) {
@@ -302,10 +302,10 @@ fn rejectstable(dir: str, label: str, target: str, needle: str) void = {
strings.concat(td, "/api-c2.a"), strings.concat(td, "/api-w.a")];
i = 0;
for (i < packages.len) {
let pav: []str = [testenv.driver(drivers[i]), "build", "-p", "-I", td,
let pav: []str = [testenv.driver(drivers[i]), "build", "-I", td,
"-o", packages[i], api];
if (code(td, strings.concat("package_", tags[i]), pav) != 0) {
fail("self-contained", "ww build -p api failed");
fail("self-contained", "ww build api failed");
};
i += 1;
};
@@ -907,7 +907,7 @@ fn writediamond(td: str, reverse: bool) str = {
"/.wwtool.w6a")), testenv.readfile(assembler))
|| !testenv.same(testenv.readfile(strings.concat(work,
"/.wwtool.stamp")),
"ww workdir fmt 10 mode build asm 0\n")) {
"ww workdir fmt 12 mode build asm 0\n")) {
fail("driver-identity", "persistent artifacts or identities are incomplete");
};
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
@@ -1224,9 +1224,9 @@ fn writediamond(td: str, reverse: bool) str = {
"export fn nestedvalue() i32 = { return 41; };\n"));
let ca: str = strings.concat(td, "/nested-c.a");
let wa: str = strings.concat(td, "/nested-w.a");
let cav: []str = [testenv.driver("ww"), "build", "-p", "-I", root,
let cav: []str = [testenv.driver("ww"), "build", "-I", root,
"-o", ca, "foo.bar"];
let wav: []str = [testenv.driver("ww_ww"), "build", "-p", "-I", root,
let wav: []str = [testenv.driver("ww_ww"), "build", "-I", root,
"-o", wa, "foo.bar"];
if (code(td, "nested_package_c", cav) != 0
|| code(td, "nested_package_w", wav) != 0) {
@@ -1247,22 +1247,575 @@ fn writediamond(td: str, reverse: bool) str = {
let i: i32 = 0;
for (i < drivers.len) {
let badout: str = strings.concat(td, "/bad-flags-", drivers[i]);
let av: []str = [testenv.driver(drivers[i]), "build", "-p", "-S",
let av: []str = [testenv.driver(drivers[i]), "build", "-p",
"-I", root, "-o", badout, "foo.bar"];
let co: testenv.commandout;
command(td, strings.concat("package_flag_contract_", drivers[i]),
av, &co);
if (co.termination != exec.termination.EXIT || co.code == 0
|| !testenv.has(co.stderr,
"ww build: -p and -S cannot be combined")) {
|| !testenv.has(co.stderr, "ww build: unknown flag")) {
fail("package-flags", strings.concat(drivers[i],
" accepted -p -S"));
" accepted the removed package-action flag"));
};
i += 1;
};
testenv.clean(td);
};
@test fn package_kind_selects_build_action() void = {
let td: str = testenv.fresh();
let source: str = strings.concat(td, "/source");
let foo: str = strings.concat(source, "/foo");
let dep: str = strings.concat(foo, "/dep");
let bar: str = strings.concat(foo, "/bar");
let commanddir: str = strings.concat(foo, "/cmd");
let cyclea: str = strings.concat(foo, "/cyclea");
let cycleb: str = strings.concat(foo, "/cycleb");
let tools: str = strings.concat(td, "/tools");
mkdir(source); mkdir(foo); mkdir(dep); mkdir(bar); mkdir(commanddir);
mkdir(cyclea); mkdir(cycleb); mkdir(tools);
let depsrc: str = strings.concat(dep, "/dep.ww");
let depbase: str = strings.concat(
"package dep;\n",
"// DEP_SOURCE\n",
"fn hidden() i32 = { return 40; };\n",
"export fn value() i32 = { return hidden(); };\n");
let depprivate: str = strings.concat(
"package dep;\n",
"// DEP_SOURCE\n",
"fn hidden() i32 = { return 41; };\n",
"export fn value() i32 = { return hidden(); };\n");
let depexported: str = strings.concat(depprivate,
"export fn additional() i32 = { return 1; };\n");
testenv.writefile(depsrc, depbase);
testenv.writefile(strings.concat(bar, "/a.ww"), strings.concat(
"package bar;\nimport foo.dep;\n",
"// ROOT_A\n",
"export fn value() i32 = { return dep.value() + 2; };\n"));
testenv.writefile(strings.concat(bar, "/z.ww"), strings.concat(
"package bar;\nimport foo.dep;\n",
"// ROOT_Z\n",
"export fn other() i32 = { return 9; };\n"));
testenv.writefile(strings.concat(commanddir, "/main.ww"), strings.concat(
"package main;\nimport foo.bar;\n",
"// COMMAND_OWNER\n",
"fn main() i32 = { return bar.value(); };\n"));
testenv.writefile(strings.concat(cyclea, "/a.ww"), strings.concat(
"package cyclea;\nimport foo.cycleb;\n",
"export fn value() i32 = { return cycleb.value(); };\n"));
testenv.writefile(strings.concat(cycleb, "/b.ww"), strings.concat(
"package cycleb;\nimport foo.cyclea;\n",
"export fn value() i32 = { return cyclea.value(); };\n"));
let compiler: str = strings.concat(tools, "/w6c.sh");
let assembler: str = strings.concat(tools, "/w6a.sh");
let linker: str = strings.concat(tools, "/w6l.sh");
testenv.writeexecutable(compiler, strings.concat(
"#!/bin/sh\n",
"printf 'BEGIN' >> \"$WW_ROOT_COMPILER_TRACE\"\n",
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
"\"$WW_ROOT_COMPILER_TRACE\"; done\n",
"printf '\\n' >> \"$WW_ROOT_COMPILER_TRACE\"\n",
"exec \"$WW_ROOT_REAL_COMPILER\" \"$@\"\n"));
testenv.writeexecutable(assembler, strings.concat(
"#!/bin/sh\n",
"printf 'BEGIN' >> \"$WW_ROOT_ASSEMBLER_TRACE\"\n",
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
"\"$WW_ROOT_ASSEMBLER_TRACE\"; done\n",
"printf '\\n' >> \"$WW_ROOT_ASSEMBLER_TRACE\"\n",
"exec \"$WW_ROOT_REAL_ASSEMBLER\" \"$@\"\n"));
testenv.writeexecutable(linker, strings.concat(
"#!/bin/sh\n",
"printf 'BEGIN' >> \"$WW_ROOT_LINKER_TRACE\"\n",
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
"\"$WW_ROOT_LINKER_TRACE\"; done\n",
"printf '\\n' >> \"$WW_ROOT_LINKER_TRACE\"\n",
"exec \"$WW_ROOT_REAL_LINKER\" \"$@\"\n"));
let stages: []str = ["ww", "ww_ww"];
let compilers: []str = ["w6c", "w6c_ww"];
let assemblers: []str = ["w6a", "w6a_ww"];
let linkers: []str = ["w6l", "w6l_ww"];
let tags: []str = ["c", "ww"];
let suffixes: []str = [".unit.ww", ".wwi", ".s", ".o", ".a"];
let rootreference: []str = ["", "", "", "", ""];
let depreference: []str = ["", "", "", "", ""];
let commandreference: []str = ["", "", "", "", ""];
let nooutrootreference: []str = ["", "", "", "", ""];
let nooutdepreference: []str = ["", "", "", "", ""];
let publishreference: str = "";
let exportreference: str = "";
let binaryreference: str = "";
let diagnosticreference: str = "";
let cyclediagreference: str = "";
let cyclepathdiagreference: str = "";
let pathdiagreference: str = "";
let runtime: str = strings.concat(testenv.repo(), "/out/lib");
let si: i32 = 0;
for (si < stages.len) {
let work: str = strings.concat(td, "/work-", tags[si]);
let outpath: str = strings.concat(td, "/libbar-", tags[si], ".a");
let compilertrace: str = strings.concat(td, "/compiler-", tags[si]);
let assemblertrace: str = strings.concat(td, "/assembler-", tags[si]);
let linkertrace: str = strings.concat(td, "/linker-", tags[si]);
mkdir(work);
testenv.writefile(compilertrace, "");
testenv.writefile(assemblertrace, "");
testenv.writefile(linkertrace, "");
let env: []str = roottraceenv(source, runtime,
compiler, assembler, linker,
compilertrace, assemblertrace, linkertrace,
testenv.driver(compilers[si]),
testenv.driver(assemblers[si]),
testenv.driver(linkers[si]));
let av: []str = [testenv.driver(stages[si]), "build",
"-w", work, "-I", source, "-o", outpath, "foo.bar"];
let out: testenv.commandout;
testenv.runcommandenv(td, td, strings.concat("auto-cold-", tags[si]),
av, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0) {
fail("package-autoaction", strings.concat(tags[si],
" cold library build failed: ", out.stderr));
};
let ctrace: str = testenv.readfile(compilertrace);
let atrace: str = testenv.readfile(assemblertrace);
let wantcompiler: str = strings.concat(
"BEGIN<-c><-I><", work,
"/foo.dep.wwi.new><-o><", work,
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
"BEGIN<-c><--import><foo.dep><", work,
"/foo.dep.wwi><-I><", work,
"/foo.bar.wwi.new><-o><", work,
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
let wantassembler: str = strings.concat(
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
"/foo.dep.s.new>\n",
"BEGIN<-o><", work, "/foo.bar.o.new><", work,
"/foo.bar.s.new>\n");
if (!testenv.same(ctrace, wantcompiler)
|| !testenv.same(atrace, wantassembler)
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"library action tool arguments are not compile-only/direct");
};
let rootunit: str = testenv.readfile(strings.concat(work,
"/foo.bar.unit.ww"));
if (testenv.pos(rootunit, "// ROOT_A") < 0
|| testenv.pos(rootunit, "// ROOT_Z")
<= testenv.pos(rootunit, "// ROOT_A")
|| testenv.has(rootunit, "DEP_SOURCE")
|| testenv.occurrences(rootunit,
"//ww:module-reset foo.bar\n") != 2) {
fail("package-autoaction",
"library unit is not owner-only and byte-sorted");
};
if (!testenv.exists(outpath)
|| !testenv.exists(strings.concat(outpath, ".wwi"))
|| !testenv.same(testenv.readfile(outpath),
testenv.readfile(strings.concat(work, "/foo.bar.a")))
|| !testenv.same(testenv.readfile(strings.concat(outpath, ".wwi")),
testenv.readfile(strings.concat(work, "/foo.bar.wwi")))) {
fail("package-autoaction", "explicit package publication changed bytes");
};
let ai: i32 = 0;
for (ai < suffixes.len) {
let rootbytes: str = testenv.readfile(strings.concat(work,
"/foo.bar", suffixes[ai]));
let depbytes: str = testenv.readfile(strings.concat(work,
"/foo.dep", suffixes[ai]));
if (si == 0) {
rootreference[ai] = strings.dup(rootbytes);
depreference[ai] = strings.dup(depbytes);
} else { if (!testenv.same(rootreference[ai], rootbytes)
|| !testenv.same(depreference[ai], depbytes)) {
fail("package-autoaction",
"Cstage and WWstage package artifacts differ");
}; };
ai += 1;
};
if (si == 0) {
publishreference = strings.dup(testenv.readfile(outpath));
exportreference = strings.dup(testenv.readfile(strings.concat(
outpath, ".wwi")));
} else { if (!testenv.same(publishreference,
testenv.readfile(outpath)) || !testenv.same(exportreference,
testenv.readfile(strings.concat(outpath, ".wwi")))) {
fail("package-autoaction", "published stage artifacts differ");
}; };
// The other AutoAction half remains declaration-selected: package main
// alone receives --entry and its complete archive-only link closure.
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let commandwork: str = strings.concat(td, "/command-work-", tags[si]);
let commandbin: str = strings.concat(td, "/command-", tags[si]);
mkdir(commandwork);
let commandav: []str = [testenv.driver(stages[si]), "build",
"-w", commandwork, "-I", source, "-o", commandbin, "foo.cmd"];
testenv.runcommandenv(td, td, strings.concat("auto-command-", tags[si]),
commandav, env, tmo(), &out);
ctrace = testenv.readfile(compilertrace);
atrace = testenv.readfile(assemblertrace);
let commandlink: str = testenv.readfile(linkertrace);
let wantcommandcompiler: str = strings.concat(
"BEGIN<-c><-I><", commandwork,
"/foo.dep.wwi.new><-o><", commandwork,
"/foo.dep.s.new><", commandwork, "/foo.dep.unit.new>\n",
"BEGIN<-c><--import><foo.dep><", commandwork,
"/foo.dep.wwi><-I><", commandwork,
"/foo.bar.wwi.new><-o><", commandwork,
"/foo.bar.s.new><", commandwork, "/foo.bar.unit.new>\n",
"BEGIN<--entry><-c><--import><foo.bar><", commandwork,
"/foo.bar.wwi><-I><", commandwork,
"/foo.cmd.wwi.new><-o><", commandwork,
"/foo.cmd.s.new><", commandwork, "/foo.cmd.unit.new>\n");
let wantcommandassembler: str = strings.concat(
"BEGIN<-o><", commandwork, "/foo.dep.o.new><", commandwork,
"/foo.dep.s.new>\n",
"BEGIN<-o><", commandwork, "/foo.bar.o.new><", commandwork,
"/foo.bar.s.new>\n",
"BEGIN<-o><", commandwork, "/foo.cmd.o.new><", commandwork,
"/foo.cmd.s.new>\n");
let wantcommandlink: str = strings.concat("BEGIN<-o><", commandbin,
"><", commandwork, "/foo.cmd.a><", commandwork,
"/foo.bar.a><", commandwork, "/foo.dep.a><", runtime,
"/libwwrt.a>\n");
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0
|| !testenv.same(ctrace, wantcommandcompiler)
|| !testenv.same(atrace, wantcommandassembler)
|| !testenv.same(commandlink, wantcommandlink)
|| testenv.has(commandlink, ".wwi>")) {
fail("package-autoaction",
"main action arguments or archive closure changed");
};
let commandunit: str = testenv.readfile(strings.concat(commandwork,
"/foo.cmd.unit.ww"));
if (!testenv.has(commandunit, "// COMMAND_OWNER")
|| testenv.has(commandunit, "// ROOT_A")
|| testenv.has(commandunit, "// DEP_SOURCE")) {
fail("package-autoaction", "command unit contains foreign sources");
};
ai = 0;
for (ai < suffixes.len) {
let commandbytes: str = testenv.readfile(strings.concat(commandwork,
"/foo.cmd", suffixes[ai]));
if (si == 0) { commandreference[ai] = strings.dup(commandbytes); }
else { if (!testenv.same(commandreference[ai], commandbytes)) {
fail("package-autoaction",
"Cstage and WWstage command artifacts differ");
}; };
ai += 1;
};
let commandrun: []str = [commandbin];
if (code(td, strings.concat("auto-command-run-", tags[si]),
commandrun) != 42) {
fail("package-autoaction", "main action binary returned wrong value");
};
// The public run command must make the same declaration-driven choice;
// its private temp paths make exact argv intentionally inapplicable here.
let drivercommandrun: []str = [testenv.driver(stages[si]), "run",
"-I", source, "foo.cmd"];
testenv.runcommand(td, td, strings.concat("auto-driver-command-run-",
tags[si]), drivercommandrun, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 42
|| out.stdout.len != 0 || out.stderr.len != 0) {
fail("package-autoaction", "ww run rejected or misran package main");
};
if (si == 0) {
binaryreference = strings.dup(testenv.readfile(commandbin));
} else { if (!testenv.same(binaryreference,
testenv.readfile(commandbin))) {
fail("package-autoaction", "linked stage binaries differ");
}; };
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let nooutwork: str = strings.concat(td, "/no-output-work-", tags[si]);
mkdir(nooutwork);
let noout: []str = [testenv.driver(stages[si]), "build",
"-w", nooutwork, "-I", source, "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-no-output-", tags[si]),
noout, env, tmo(), &out);
ctrace = testenv.readfile(compilertrace);
atrace = testenv.readfile(assemblertrace);
let wantnooutcompiler: str = strings.concat(
"BEGIN<-c><-I><", nooutwork,
"/foo.dep.wwi.new><-o><", nooutwork,
"/foo.dep.s.new><", nooutwork, "/foo.dep.unit.new>\n",
"BEGIN<-c><--import><foo.dep><", nooutwork,
"/foo.dep.wwi><-I><", nooutwork,
"/foo.bar.wwi.new><-o><", nooutwork,
"/foo.bar.s.new><", nooutwork, "/foo.bar.unit.new>\n");
let wantnooutassembler: str = strings.concat(
"BEGIN<-o><", nooutwork, "/foo.dep.o.new><", nooutwork,
"/foo.dep.s.new>\n",
"BEGIN<-o><", nooutwork, "/foo.bar.o.new><", nooutwork,
"/foo.bar.s.new>\n");
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0 || testenv.exists(strings.concat(td, "/bar"))
|| !testenv.same(ctrace, wantnooutcompiler)
|| !testenv.same(atrace, wantnooutassembler)
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"cold no-output library build did not remain compile-only");
};
ai = 0;
for (ai < suffixes.len) {
let nooutroot: str = testenv.readfile(strings.concat(nooutwork,
"/foo.bar", suffixes[ai]));
let nooutdep: str = testenv.readfile(strings.concat(nooutwork,
"/foo.dep", suffixes[ai]));
if (!testenv.same(nooutroot, rootreference[ai])
|| !testenv.same(nooutdep, depreference[ai])) {
fail("package-autoaction",
"publication request changed package artifact bytes");
};
if (si == 0) {
nooutrootreference[ai] = strings.dup(nooutroot);
nooutdepreference[ai] = strings.dup(nooutdep);
} else { if (!testenv.same(nooutrootreference[ai], nooutroot)
|| !testenv.same(nooutdepreference[ai], nooutdep)) {
fail("package-autoaction",
"cold no-output artifacts differ by stage");
}; };
ai += 1;
};
// An explicitly empty -o is observably the same no-publication request
// in both drivers and therefore reuses the same semantic actions.
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let emptyout: []str = [testenv.driver(stages[si]), "build",
"-w", nooutwork, "-I", source, "-o", "", "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-empty-output-",
tags[si]), emptyout, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"empty -o changed no-publication action semantics");
};
// Publication is not semantic action identity: an already-populated
// package workdir is reusable when the next request omits -o.
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let warmnoout: []str = [testenv.driver(stages[si]), "build",
"-w", work, "-I", source, "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-warm-no-output-",
tags[si]), warmnoout, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"publication request entered persistent action identity");
};
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let pathwork: str = strings.concat(td, "/path-work-", tags[si]);
mkdir(pathwork);
let longout: str = strings.concat(td, "/");
for (longout.len < 4090) { longout = strings.concat(longout, "x"); };
let pathav: []str = [testenv.driver(stages[si]), "build",
"-w", pathwork, "-I", source, "-o", longout, "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-output-path-", tags[si]),
pathav, env, tmo(), &out);
let wantpathdiag: str = "ww: package output path is too long\n";
if (out.termination != exec.termination.EXIT || out.code != 1
|| !testenv.same(out.stderr, wantpathdiag)
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0
|| testenv.exists(strings.concat(pathwork, "/foo.dep.unit.ww"))
|| testenv.exists(strings.concat(pathwork, "/foo.bar.unit.ww"))) {
fail("package-autoaction",
"package publication path failed after the tool boundary");
};
if (si == 0) { pathdiagreference = strings.dup(out.stderr); }
else { if (!testenv.same(pathdiagreference, out.stderr)) {
fail("package-autoaction", "output path diagnostics differ by stage");
}; };
// Output publication is unused under -S, so even this spelling must not
// participate in an assembly-only action or its failure behavior.
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let asmwork: str = strings.concat(td, "/asm-work-", tags[si]);
mkdir(asmwork);
let asmav: []str = [testenv.driver(stages[si]), "build", "-S",
"-w", asmwork, "-I", source, "-o", longout, "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-asm-long-output-",
tags[si]), asmav, env, tmo(), &out);
let wantasmcompiler: str = strings.concat(
"BEGIN<-c><-I><", asmwork,
"/foo.dep.wwi.new><-o><", asmwork,
"/foo.dep.s.new><", asmwork, "/foo.dep.unit.new>\n",
"BEGIN<-c><--import><foo.dep><", asmwork,
"/foo.dep.wwi><-I><", asmwork,
"/foo.bar.wwi.new><-o><", asmwork,
"/foo.bar.s.new><", asmwork, "/foo.bar.unit.new>\n");
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0
|| !testenv.same(testenv.readfile(compilertrace), wantasmcompiler)
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0
|| testenv.exists(strings.concat(asmwork, "/foo.dep.o"))
|| testenv.exists(strings.concat(asmwork, "/foo.dep.a"))
|| testenv.exists(strings.concat(asmwork, "/foo.bar.o"))
|| testenv.exists(strings.concat(asmwork, "/foo.bar.a"))) {
fail("package-autoaction",
"assembly-only action consumed an unused publication path");
};
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
let runav: []str = [testenv.driver(stages[si]), "run",
"-I", source, "foo.bar"];
testenv.runcommandenv(td, td, strings.concat("auto-run-reject-", tags[si]),
runav, env, tmo(), &out);
let wantdiag: str = "ww: package foo.bar is not a main package\n";
if (out.termination != exec.termination.EXIT || out.code != 1
|| !testenv.same(out.stderr, wantdiag)
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction", "run crossed the non-main tool boundary");
};
if (si == 0) { diagnosticreference = strings.dup(out.stderr); }
else { if (!testenv.same(diagnosticreference, out.stderr)) {
fail("package-autoaction", "run diagnostics differ by stage");
}; };
let cyclerun: []str = [testenv.driver(stages[si]), "run",
"-I", source, "foo.cyclea"];
testenv.runcommandenv(td, td, strings.concat("auto-run-cycle-", tags[si]),
cyclerun, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 1
|| !testenv.has(out.stderr,
"ww: dependency cycle: foo.cyclea -> foo.cycleb -> foo.cyclea\n")
|| testenv.has(out.stderr, "is not a main package")
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"run command-kind validation masked a graph failure");
};
if (si == 0) { cyclediagreference = strings.dup(out.stderr); }
else { if (!testenv.same(cyclediagreference, out.stderr)) {
fail("package-autoaction", "run cycle diagnostics differ by stage");
}; };
let cyclepathwork: str = strings.concat(td, "/cycle-path-work-",
tags[si]);
mkdir(cyclepathwork);
let cyclepathav: []str = [testenv.driver(stages[si]), "build",
"-w", cyclepathwork, "-I", source, "-o", longout,
"foo.cyclea"];
testenv.runcommandenv(td, td, strings.concat("auto-cycle-path-", tags[si]),
cyclepathav, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 1
|| !testenv.has(out.stderr, "ww: dependency cycle: ")
|| !testenv.has(out.stderr, "foo.cyclea")
|| !testenv.has(out.stderr, "foo.cycleb")
|| testenv.has(out.stderr, "package output path is too long")
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
strings.concat("publication path validation masked a graph failure: ",
out.stderr));
};
if (si == 0) { cyclepathdiagreference = strings.dup(out.stderr); }
else { if (!testenv.same(cyclepathdiagreference, out.stderr)) {
fail("package-autoaction",
"cycle/output-path diagnostic differs by stage");
}; };
assert(os.remove(depsrc) == 0);
testenv.writefile(depsrc, depprivate);
testenv.runcommandenv(td, td, strings.concat("auto-private-", tags[si]),
av, env, tmo(), &out);
ctrace = testenv.readfile(compilertrace);
atrace = testenv.readfile(assemblertrace);
let wantprivatecompiler: str = strings.concat(
"BEGIN<-c><-I><", work,
"/foo.dep.wwi.new><-o><", work,
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n");
let wantprivateassembler: str = strings.concat(
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
"/foo.dep.s.new>\n");
if (out.termination != exec.termination.EXIT || out.code != 0
|| !testenv.same(ctrace, wantprivatecompiler)
|| !testenv.same(atrace, wantprivateassembler)
|| testenv.readfile(linkertrace).len != 0
|| !testenv.same(rootreference[4], testenv.readfile(strings.concat(
work, "/foo.bar.a")))) {
fail("package-autoaction",
"private dependency change escaped its export boundary");
};
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
assert(os.remove(depsrc) == 0);
testenv.writefile(depsrc, depexported);
testenv.runcommandenv(td, td, strings.concat("auto-export-", tags[si]),
av, env, tmo(), &out);
ctrace = testenv.readfile(compilertrace);
atrace = testenv.readfile(assemblertrace);
let wantexportcompiler: str = strings.concat(
"BEGIN<-c><-I><", work,
"/foo.dep.wwi.new><-o><", work,
"/foo.dep.s.new><", work, "/foo.dep.unit.new>\n",
"BEGIN<-c><--import><foo.dep><", work,
"/foo.dep.wwi><-I><", work,
"/foo.bar.wwi.new><-o><", work,
"/foo.bar.s.new><", work, "/foo.bar.unit.new>\n");
let wantexportassembler: str = strings.concat(
"BEGIN<-o><", work, "/foo.dep.o.new><", work,
"/foo.dep.s.new>\n",
"BEGIN<-o><", work, "/foo.bar.o.new><", work,
"/foo.bar.s.new>\n");
if (out.termination != exec.termination.EXIT || out.code != 0
|| !testenv.same(ctrace, wantexportcompiler)
|| !testenv.same(atrace, wantexportassembler)
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction",
"exported dependency change did not reach its direct importer");
};
testenv.clean(compilertrace); testenv.writefile(compilertrace, "");
testenv.clean(assemblertrace); testenv.writefile(assemblertrace, "");
testenv.clean(linkertrace); testenv.writefile(linkertrace, "");
testenv.runcommandenv(td, td, strings.concat("auto-warm-", tags[si]),
av, env, tmo(), &out);
if (out.termination != exec.termination.EXIT || out.code != 0
|| out.stderr.len != 0
|| testenv.readfile(compilertrace).len != 0
|| testenv.readfile(assemblertrace).len != 0
|| testenv.readfile(linkertrace).len != 0) {
fail("package-autoaction", "warm library build did not fully reuse");
};
assert(os.remove(depsrc) == 0);
testenv.writefile(depsrc, depbase);
si += 1;
};
testenv.clean(td);
};
@test fn generated_test_hook_is_not_a_user_exemption() void = {
let td: str = testenv.fresh();
let src: str = strings.concat(td, "/case.ww");

View File

@@ -249,6 +249,7 @@ fn runrootargv(dir: str, root: str, name: str, drv: str,
let td: str = testenv.fresh();
let src: str = strings.concat(td, "/inline.ww");
testenv.writefile(src, strings.concat(
"package main;\n",
"package aa;\n",
"export fn getv() i32 = { return 7; };\n",
"package main;\n",

View File

@@ -19,7 +19,7 @@ package rejects_test;
// paramshadow (#19/#16) — value names and module names are disjoint:
// a param/let/mlet/for-range/match-case binding named `shadowmod` in
// a file importing module shadowmod is rejected at the decl site; the
// renamed binding builds+runs 42 (no over-trigger); a param named
// renamed binding in a real `package main` builds+runs 42 (no over-trigger); a param named
// like a module a SIBLING module imports does not trip (src_imports
// filters by the binding's own module — build+run exit 2). The
// carrier's neg_selfimp leg is DROPPED here:

View File

@@ -12,7 +12,7 @@
// p2() = mod2.ping = 31
// total = 112
package fnlabelmangle;
package main;
import mod1;
import mod2;

View File

@@ -6,7 +6,7 @@
// own module — must NOT trip crossmod's param, even though a sibling
// module in the same bundle imports that leaf. Build + run; exit = 2.
package paramshadowmod;
package main;
import shadowmod;
import crossmod;

View File

@@ -2,7 +2,7 @@
// imported module's bareword, so the rule doesn't fire and the body
// can call `shadowmod.say()` cleanly. Built + run; exit code = 42.
package paramshadowmod;
package main;
import shadowmod;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 26
package main;
// migrated from test/wcc/696_modtype_leaf_collision.c: same-leaf cross-module `type stream` must stay mod-tagged (pre-fix sym smash cross-bound the fields).
package mod1;
export type stream = struct {

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_DEF promotion must keep use_alias so `defmod.flag` resolves.
package defmod;
export def defmod: i32 = 0i32;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_FN promotion (the original bug) must keep use_alias or `fnmod.flag` fails "unknown type".
package fnmod;
export type flag = enum i32 {

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_TYPE in-place promotion keeps use_alias so `typmod.flag` resolves (check.c self-import branch).
package typmod;
export type typmod = struct {

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_VAR promotion must keep use_alias so `varmod.flag` resolves.
package varmod;
export let varmod: i32 = 0i32;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 107
package main;
// Migrated from 700_e2e row 40.
package myos;
fn alloc(n: i64) i64 = { return n + 100; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// Migrated from 700_e2e row 123.
package pkg;
export type base = enum i32 { DEC = 10, HEX = 16 };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 1
package main;
// Migrated from 700_e2e row 118.
package pkg;
type dir = enum { NORTH, SOUTH, EAST, WEST };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/732_def_const_fold.c: cross-module def-RHS fold (`def K = a.J + 1`) must emit the folded DATA row; run-exit links AND reads the value.
package a;
export def J: i32 = 41;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 5
package main;
package aa;
export def K: i32 = 5;
export fn getk() i32 = { return K; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 7
package main;
package aa;
export let v: i32 = 7;
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 7
package main;
package aa;
export let v: i32 = 7;
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 2
package main;
package aa;
export let f: f64 = 2.5;
export fn getf() f64 = { return f; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 7
package main;
package aa;
export let v: i32 = 7;
export fn getv() i32 = { return v; };

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: A6 — concrete e.myerr returned into e.res (bare-vs-qualified nominal forward), both stages accept.
package e;
export type myerr = !i64;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// migrated from test/wcc/839_xmod_nominal_typeeqast.c: bare-spelled union variants matched via QUALIFIED case patterns (`case let x: e.myerr`) — cross-module nominal cover.
package e;
export type myerr = !i64;

View File

@@ -1,3 +1,4 @@
//ww:run-exit 7
package main;
package cmatrix;
fn main() i32 = { return 7; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 37
package main;
package pkg;
export type point = struct { x: i64, y: i64 };
export type rect = struct { lo: point, hi: point };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 18
package main;
package pkg;
export type point = struct { x: i64, y: i64 };
export type rect = struct { lo: point, hi: point };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 27
package main;
package pkg;
export type point = struct { x: i64, y: i64 };
export type rect = struct { lo: point, hi: point };

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/915_arr_module_index_run.c: cross-package mod.arr[0] — LEAQ base + u16 load width (#128b).
package wcmodarr;
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];

View File

@@ -1,4 +1,5 @@
//ww:run-exit 1
package main;
// migrated from test/wcc/915_arr_module_index_run.c: nontrivial index — the pre-fix MOVQ-not-LEAQ segfault repro; 0x0801 mod 256 = 1.
package wcmodarr;
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];

View File

@@ -1,4 +1,5 @@
//ww:run-exit 6
package main;
// migrated from test/wcc/915_arr_module_index_run.c: per-element stride pin; 0x1006 mod 256 = 6.
package wcmodarr;
export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, 0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];

View File

@@ -1,4 +1,5 @@
//ww:run-exit 18
package main;
package myf;
export type pt = struct { x: i32, y: i32 };
export def P: pt = pt{x=7, y=11};

View File

@@ -1,4 +1,5 @@
//ww:run-exit 7
package main;
package myf;
export fn helper() i32 = { return 42; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 18
package main;
package myf;
export type pt = struct { x: i32, y: i32 };
export let L: pt = pt{x=7, y=11};

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
package myf;
export let S: i32 = 42;
package main;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 3-arm boundary — arm 2 must reach its body under the shadowed callee.
package a;
export type more = void;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: mixed variant kinds (i32|str|rune|u8) — the shadowed-resolution fix is not shape-specific.
package a;
export fn next(k: i32) (i32 | str | rune | u8) = {

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: canonical 4-arm — caller fn `next` shadows callee a.next; every arm body must fire (#31 fnretlookupmod).
package a;
export type more = void;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: reverse arm order — dispatch follows the callee's variant indices, not source order.
package a;
export type more = void;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 5-arm scaling — arms 3 and 4 must each reach their body.
package a;
export type more = void;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/929_match_4arm_cross_module_run.c: 6-arm — every arm beyond the caller's variant count was broken, not just arm 2/3.
package a;
export type more = void;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
// migrated from test/wcc/949_xmod_fnptr_const_run.c: cross-module &cc.fn inside const table + scalar emits the &fn->DATAR reloc (#124); DISTINCT predicates catch a swapped reloc.
package cc;
export fn isa(c: rune) bool = { return c == 'a'; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 249
package main;
package myf;
export fn g() f64 = { return -7.0; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 253
package main;
package myf;
export fn g() f64 = { return -3.9; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 3
package main;
package myf;
export fn g() f64 = { return 3.9; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 242
package main;
package myf;
export fn g() f64 = { return -7.0; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 8
package main;
package myf;
export fn g() f64 = { return -7.0; };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run
package main;
package myf;
export fn frexp(n: f64) (f64, i64) = {
if (n == 0.0) { return (0.0, 0i64); };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 4
package main;
package myf;
export fn fs(n: f64) (f64, str) = {
if (n == 0.0) { return (n, "x"); };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 15
package main;
package myf;
export fn addi64(a: i64, b: i64) (i64, bool) = {
let s: i64 = a + b;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 10
package main;
package beta;
export fn dup() (i64, i64) = { return (3i64, 7i64); };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
package m;
export fn f() i32 = {
assert(3 > 2, "m.f invariant");

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
package m;
export fn assert(b: bool, msg: str) void = { };
package main;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
// Current-module &fn lookup must beat a later same-leaf declaration.
package beta;
export type hfn = fn(x: i32) i32;

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
package beta;
export type berr = !void;
export fn op() (i32 | berr) = { return 5; };

View File

@@ -1,4 +1,5 @@
//ww:run-exit 42
package main;
package beta;
export type berr = !void;
export fn op() (i32 | berr) = { return 5; };

View File

@@ -18,7 +18,7 @@
// task; until then we exercise polymorphism via ctx pointers, which
// is what the real port wants anyway.
package test;
package main;
import os;
import strconv;

View File

@@ -15,7 +15,7 @@ package direnum_test;
// Both stages must FAIL with "conflicting package names", and the
// two stages' diagnostics must be byte-identical.
//
// rootorder — a private rootok/ dir built DIRECTLY (z.ww ORDER-Z
// rootorder — a private rootok/ command dir built DIRECTLY (z.ww ORDER-Z
// value()=17 vs a.ww ORDER-A leading comment + main): build exit 0,
// the binary exits 17, and the driver's local-identity owner unit
// stores ORDER-A strictly before ORDER-Z (byte-sorted deterministic
@@ -121,14 +121,14 @@ fn rejectpair(label: str, td: str, target: str, needle: str) void = {
let rootok: str = strings.concat(td, "/rootok");
assert(os.mkdir(rootok, 493) == 0);
testenv.writefile(strings.concat(rootok, "/z.ww"), strings.concat(
"package rootok;\n// ORDER-Z\n",
"package main;\n// ORDER-Z\n",
"fn value() i32 = { return 17; };\n"));
testenv.writefile(strings.concat(rootok, "/a.ww"), strings.concat(
"// leading comment is part of the loader grammar\n",
"package rootok;\n// ORDER-A\n",
"package main;\n// ORDER-A\n",
"fn main() i32 = { return value(); };\n"));
let drvs: []str = ["ww", "ww_ww"];
let identity: str = testenv.localpackageidentity(rootok, "rootok");
let identity: str = testenv.localpackageidentity(rootok, "main");
let units: []str = ["", ""];
let s: i32 = 0;
for (s < 2) {