Only the ast_proof leg was unowned: wwdump -a / wwdump_ww -a dump byte-id plus the ordered dot-over-structlit-over-tname node shape for a trailing op on a qualified struct literal (inexpressible as a runtime scenario while the #77 literal-temporary cgen gap holds; the multilevel row pins the source-order a.b.C tname flatten). The three build/run scenarios are owned by the r84_qualstruct_* fixtures plus the test-data-byteid blanket — their vestigial want_exit fields were already dead in the carrier.
96 lines
3.1 KiB
Plaintext
96 lines
3.1 KiB
Plaintext
package qualast_test;
|
|
|
|
// The ast_proof remainder of the retired native carrier
|
|
// test/wcc/848_xmod_qualstructlit_run.c (#76 qualified struct
|
|
// literals). The three build/run scenarios are owned by the
|
|
// r84_qualstruct_{fields,ret_assign,nested} fixtures plus the
|
|
// test-data-byteid blanket; what no fixture can host is the PARSE
|
|
// node-shape proof for a TRAILING op on a qualified struct literal —
|
|
// `pkg.point{...}.x` trips the pre-existing cgen literal-temporary
|
|
// gap (#77), so it can never ride a runtime scenario.
|
|
//
|
|
// Per row: `wwdump -a` (parse-only) on both stages, rc 0, dumps
|
|
// byte-identical (rule 10), then ordered substrings prove
|
|
// dot-over-structlit-over-tname — the parser's postfix loop stayed
|
|
// live past the `}` so `.x` wrapped the literal, and the dotted path
|
|
// flattened into ONE source-order N_TNAME (parsetype's dotted
|
|
// collapse, byte-identical across parse positions). astprint resolves
|
|
// no names, so `pkg` / `a.b.C` need not name a real import.
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("qualast FAIL: ", label, " -- ", why,
|
|
"\n");
|
|
os.write(2, m.ptr, m.len: u64);
|
|
assert(false);
|
|
};
|
|
|
|
fn tmo() time.duration = {
|
|
return (180i64 * (time.second: i64)): time.duration;
|
|
};
|
|
|
|
fn dumpstage(td: str, label: str, stage: str, tool: str) str = {
|
|
let av: []str = [testenv.driver(tool), "-a",
|
|
strings.concat(td, "/a.ww")];
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(td, td, stage, av, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT || co.code != 0) {
|
|
fail(label, strings.concat(stage, " ", tool, " -a failed"));
|
|
};
|
|
return co.stdout;
|
|
};
|
|
|
|
// The needles must occur in order (tree nesting without coupling to
|
|
// astprint's exact indentation).
|
|
fn ordered(hay: str, needles: []str) bool = {
|
|
let from: i32 = 0;
|
|
let i: i32 = 0;
|
|
for (i < needles.len) {
|
|
let rest: str = strings.sub(hay, from, hay.len);
|
|
let p: i32 = testenv.pos(rest, needles[i]);
|
|
if (p < 0) { return false; };
|
|
from = from + p + 1;
|
|
i += 1;
|
|
};
|
|
return true;
|
|
};
|
|
|
|
fn astrow(label: str, src: str, needles: []str) void = {
|
|
let td: str = testenv.fresh();
|
|
testenv.writefile(strings.concat(td, "/a.ww"), src);
|
|
let cs: str = dumpstage(td, label, "cstage", "wwdump");
|
|
let ws: str = dumpstage(td, label, "wwstage", "wwdump_ww");
|
|
if (!testenv.same(cs, ws)) {
|
|
fail(label, "cs/ww AST dumps DIFFER (rule-10)");
|
|
};
|
|
if (!ordered(cs, needles)) {
|
|
fail(label, strings.concat("AST node shape wrong (trailing ",
|
|
"op did not wrap the qualified struct literal)"));
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
@test fn astproof() void = {
|
|
let trailing: []str = ["(dot \"x\"", "(structlit",
|
|
"(tname \"pkg.point\""];
|
|
astrow("trailing", strings.concat(
|
|
"package main;\n",
|
|
"export fn f() i64 = {\n",
|
|
"\tlet v: i64 = pkg.point { x = 1i64, y = 2i64 }.x;\n",
|
|
"\treturn v;\n",
|
|
"};\n"), trailing);
|
|
let multilevel: []str = ["(dot \"x\"", "(structlit",
|
|
"(tname \"a.b.C\""];
|
|
astrow("multilevel", strings.concat(
|
|
"package main;\n",
|
|
"export fn g() i64 = {\n",
|
|
"\tlet v: i64 = a.b.C { x = 1i64 }.x;\n",
|
|
"\treturn v;\n",
|
|
"};\n"), multilevel);
|
|
};
|