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); }; fn rejectrow(label: str, src: str, needle: str) void = { let td: str = testenv.fresh(); testenv.writefile(strings.concat(td, "/a.ww"), src); let tools: []str = ["wwdump", "wwdump_ww"]; let stages: []str = ["cstage", "wwstage"]; let errors: []str = ["", ""]; let i: i32 = 0; for (i < tools.len) { let av: []str = [testenv.driver(tools[i]), "-a", strings.concat(td, "/a.ww")]; let co: testenv.commandout; testenv.runcommand(td, td, stages[i], av, tmo(), &co); if (co.termination != exec.termination.EXIT || co.code == 0 || !testenv.has(co.stderr, needle)) { fail(label, strings.concat(stages[i], " accepted rejected import")); }; errors[i] = strings.dup(co.stderr); i += 1; }; if (!testenv.same(errors[0], errors[1])) { fail(label, "cs/ww parse diagnostics DIFFER"); }; 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); let ordinary: []str = ["(use \"codec\""]; astrow("ordinary-import", strings.concat( "package main;\n", "import acme.codec;\n", "fn main() i32 = { return 0; };\n"), ordinary); let aliased: []str = ["(use \"stable\""]; astrow("aliased-import", strings.concat( "package main;\n", "import stable acme.codec;\n", "fn main() i32 = { return 0; };\n"), aliased); rejectrow("blank-alias", strings.concat( "package main;\n", "import _ acme.codec;\n", "fn main() i32 = { return 0; };\n"), "blank import alias _ is not implemented"); };