From bacc89ed5fa4b6171041f06d8124743a694b01c8 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sat, 8 Aug 2026 15:03:33 +0900 Subject: [PATCH] test: port the asserttyped stamp probes to ww; retire 954 + 956 slim carriers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 954_tuprecv_run, 956_tuprecv_f64_run and 956_modqualdestr_run shared one retained dimension: w6c_ww compiles the destructure shape cleanly AND emits no asserttyped stderr diagnostic (#121 A-narrow / #6a-A stamp nets) — a channel neither test/lang nor the fixture protocol has. All 11 rows fold into one observer with the drew-C4 non-vacuity self-check on the shared predicate. Owned legs cited, not duplicated: value rows + byte-id ride test/lang/tuprecv_test.ww, test/lang/tuprecv_f64_test.ww and the test-lang-byteid blanket; the modqual values + byte-id ride the r956_modqual_* fixtures and test-data-byteid — those four rows compile the fixture files in place so probe and fixture cannot drift. Bundled: one file, one concern (the wwstage stamp-absence dimension). --- Makefile | 3 +- test/misc/stampdiag_test.ww | 183 ++++++++++++++++++++ test/wcc/954_tuprecv_run.c | 117 ------------- test/wcc/956_modqualdestr_run.c | 284 -------------------------------- test/wcc/956_tuprecv_f64_run.c | 247 --------------------------- 5 files changed, 185 insertions(+), 649 deletions(-) create mode 100644 test/misc/stampdiag_test.ww delete mode 100644 test/wcc/954_tuprecv_run.c delete mode 100644 test/wcc/956_modqualdestr_run.c delete mode 100644 test/wcc/956_tuprecv_f64_run.c diff --git a/Makefile b/Makefile index cd5cd5bb..bb86909c 100644 --- a/Makefile +++ b/Makefile @@ -408,7 +408,8 @@ OBJECT_WW_TARGETS = $(OBJECT_WW_TESTS:%=wwtest/%) # cstage-only rejects). Compiler/driver gates like test/sep: they run # under test-compiler. MISC_WW_TESTS = test/misc/arrglob_test.ww test/misc/packedwwi_test.ww \ - test/misc/reject_test.ww test/misc/heldasym_test.ww + test/misc/reject_test.ww test/misc/heldasym_test.ww \ + test/misc/stampdiag_test.ww MISC_WW_TARGETS = $(MISC_WW_TESTS:%=wwtest/%) BOOTSTRAP_WRAPPER_SOURCES = test/wcc/950_selfcheck.c \ test/wcc/991_w6a_ww.c \ diff --git a/test/misc/stampdiag_test.ww b/test/misc/stampdiag_test.ww new file mode 100644 index 00000000..37e6d2f7 --- /dev/null +++ b/test/misc/stampdiag_test.ww @@ -0,0 +1,183 @@ +package stampdiag_test; + +// Shared wwstage stamp-diagnostic observer: w6c_ww must compile each +// row cleanly AND emit NO `asserttyped` diagnostic on its stderr — +// the #121 A-narrow checker-stamp net over destructure bindings. Port +// of the retired native carriers test/wcc/954_tuprecv_run.c, +// test/wcc/956_tuprecv_f64_run.c and test/wcc/956_modqualdestr_run.c. +// wwstage-only by construction: cstage check.c has no asserttyped +// walker, so the probe drives the *_ww binary directly (project +// memory: audit wwstage checker behavior with *_ww binaries, never +// cstage w6c). +// +// The value rows and cs==ww byte-id dimensions are owned elsewhere: +// test/lang/tuprecv_test.ww (954), test/lang/tuprecv_f64_test.ww +// (956_tuprecv_f64) plus the test-lang-byteid blanket, and the +// r956_modqual_* fixtures plus the test-data-byteid blanket +// (956_modqualdestr) — the modqual rows below compile those fixture +// files IN PLACE so probe and fixture can never drift. Only the +// stderr stamp-absence dimension lives here (fixtures check exit +// only; asserttyped is a non-fatal stderr diagnostic). +// +// Non-vacuity (drew C4 mutation gate): the same `has` predicate that +// gates every row must FIRE on a literal asserttyped line, asserted +// up front — a broken predicate fails before any row runs. + +import os; +import os.exec; +import strings; +import testenv; +import time; + +fn fail(label: str, why: str) void = { + let m: str = strings.concat("stampdiag 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 selfcheck() void = { + assert(testenv.has("error: asserttyped: e.type_ nil", + "asserttyped")); +}; + +// w6c_ww -o /dev/null : rc 0 and stderr free of asserttyped. +fn stampprobe(label: str, srcpath: str) void = { + let td: str = testenv.fresh(); + let av: []str = [testenv.driver("w6c_ww"), "-o", "/dev/null", + srcpath]; + let co: testenv.commandout; + testenv.runcommand(td, td, "probe", av, tmo(), &co); + if (co.termination != exec.termination.EXIT || co.code != 0) { + fail(label, "w6c_ww stamp probe failed to compile"); + }; + if (testenv.has(co.stderr, "asserttyped")) { + fail(label, strings.concat("w6c_ww emitted asserttyped ", + "(binding unstamped -- #121 stamp net)")); + }; + testenv.clean(td); +}; + +fn stamprow(label: str, src: str) void = { + let td: str = testenv.fresh(); + let srcpath: str = strings.concat(td, "/case.ww"); + testenv.writefile(srcpath, src); + stampprobe(label, srcpath); + testenv.clean(td); +}; + +// 954: the un-annotated float-destructure receive of a 16B tuple. +@test fn tuprecvstamp() void = { + selfcheck(); + stamprow("ctl_destr", strings.concat( + "package main;\n", + "fn mk() (f64, i64) = { return (2.5, 7); };\n", + "export fn main() i32 = {\n", + "\tlet (f, i) = mk();\n", + "\treturn (f: i32) + (i: i32);\n", + "};\n")); +}; + +// 956_tuprecv_f64: branched callees so register coincidence cannot +// mask a wrong-class receive. +@test fn tuprecvf64stamp() void = { + selfcheck(); + stamprow("destr_f64_i64_br", strings.concat( + "package main;\n", + "fn issub(n: f64) bool = { return false; };\n", + "fn norm(n: f64) (f64, i64) = {\n", + "\tif (issub(n)) { return (n*2.0, -52); };\n", + "\treturn (n, 0);\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (m, i) = norm(16.0);\n", + "\tif (m != 16.0) { return 1; };\n", + "\tif (i != 0) { return 2; };\n", + "\treturn 0;\n", + "};\n")); + stamprow("destr_i64_f64_br", strings.concat( + "package main;\n", + "fn issub(n: f64) bool = { return false; };\n", + "fn norm(n: f64) (i64, f64) = {\n", + "\tif (issub(n)) { return (-52, n*2.0); };\n", + "\treturn (0, n);\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (i, m) = norm(16.0);\n", + "\tif (m != 16.0) { return 1; };\n", + "\tif (i != 0) { return 2; };\n", + "\treturn 0;\n", + "};\n")); + stamprow("f64f64_destr_br", strings.concat( + "package main;\n", + "fn issub(n: f64) bool = { return false; };\n", + "fn pair(a: f64, b: f64) (f64, f64) = {\n", + "\tif (issub(a)) { return (a*2.0, b*2.0); };\n", + "\treturn (a, b);\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (x, y) = pair(3.0, 5.0);\n", + "\tif (x != 3.0) { return 1; };\n", + "\tif (y != 5.0) { return 2; };\n", + "\treturn 0;\n", + "};\n")); + stamprow("i64_f64_i64_destr", strings.concat( + "package main;\n", + "fn issub(n: i64) bool = { return false; };\n", + "fn tri(a: i64, b: f64, c: i64) (i64, f64, i64) = {\n", + "\tif (issub(a)) { return (a*2, b*2.0, c*2); };\n", + "\treturn (a, b, c);\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (x, y, z) = tri(3, 2.0, 7);\n", + "\tif (x != 3) { return 1; };\n", + "\tif (y != 2.0) { return 2; };\n", + "\tif (z != 7) { return 3; };\n", + "\treturn 0;\n", + "};\n")); + stamprow("f64_str_destr", strings.concat( + "package main;\n", + "fn issub(n: f64) bool = { return false; };\n", + "fn fs(n: f64) (f64, str) = {\n", + "\tif (issub(n)) { return (n*2.0, \"x\"); };\n", + "\treturn (n, \"hello\");\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (f, s) = fs(4.0);\n", + "\tif (f != 4.0) { return 1; };\n", + "\tif (s.len != 5) { return 2; };\n", + "\treturn 0;\n", + "};\n")); + stamprow("str_f64_destr", strings.concat( + "package main;\n", + "fn issub(n: f64) bool = { return false; };\n", + "fn sf(n: f64) (str, f64) = {\n", + "\tif (issub(n)) { return (\"x\", n*2.0); };\n", + "\treturn (\"hello\", n);\n", + "};\n", + "export fn main() i32 = {\n", + "\tlet (s, f) = sf(4.0);\n", + "\tif (s.len != 5) { return 1; };\n", + "\tif (f != 4.0) { return 2; };\n", + "\treturn 0;\n", + "};\n")); +}; + +// 956_modqualdestr (#6a-A): module-qualified destructure bindings — +// N_DOT callees — must carry the stamp too, plus the non-destructure +// same-leaf shadow class-closure row. +@test fn modqualstamp() void = { + selfcheck(); + let names: []str = ["mq_f64_i64_destr", "mq_i64_bool_destr", + "mq_f64_str_destr", "mq_nondestr_shadow"]; + let i: i32 = 0; + for (i < names.len) { + stampprobe(names[i], strings.concat(testenv.repo(), + "/test/wcc/data/r956_modqual_", names[i], "/case.ww")); + i += 1; + }; +}; diff --git a/test/wcc/954_tuprecv_run.c b/test/wcc/954_tuprecv_run.c deleted file mode 100644 index b84d85a6..00000000 --- a/test/wcc/954_tuprecv_run.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 954_tuprecv_run — carrier-split residue of #102 (16B whole-tuple-from-call - * receive). The VALUE rows and the cs==ww .s byte-id dimension migrated to the - * fold-2 row-table test/lang/tuprecv_test.ww (cstage run via test-lang + cs==ww - * via test-lang-byteid). What CANNOT ride a value/byte-id @test is the third - * dimension the old driver also carried: a tool-OUTPUT assertion that w6c_ww - * emits NO `asserttyped:` diagnostic on the un-annotated float-destructure - * binding `let (f, i) = mk()` — the #121 A-narrow stamp net. That is the same - * category as the Class-A asm-presence twins the Fam-7 commit deliberately KEPT - * (a diagnostic-observer grep, not a value or byte-id check), so it stays here - * as a minimal retained pin rather than being silently dropped (drew ruling, - * #5-C2). - * - * Non-vacuous: pre-stamp (HEAD before #121) w6c_ww fired `asserttyped` on the - * f64 binding ident (nil n.type_); post-fix the binder carries the checker - * stamp and the diagnostic is absent. wwstage-only — cstage's check.c has no ww - * asserttyped walker, so the pin invokes w6c_ww directly. - */ -#include -#include -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -/* the ctl_destr construct: an un-annotated float-destructure binding. */ -static const char *src = - "package main;\n" - "fn mk() (f64, i64) = { return (2.5, 7); };\n" - "export fn main() i32 = {\n" - "\tlet (f, i) = mk();\n" - "\treturn (f: i32) + (i: i32);\n" - "};\n"; - -int -main(void) -{ - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - char absbin[1024]; - if (bin[0] != '/') { - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return 1; - snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); - bin = absbin; - } - - char w6c_ww[1100]; - snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin); - if (access(w6c_ww, X_OK) != 0) { - fprintf(stderr, "tuprecv: w6c_ww missing — cannot run the " - "asserttyped-absence pin\n"); - return 1; - } - - char tmpdir[] = "/tmp/wwtuprecv_XXXXXX"; - if (mkdtemp(tmpdir) == NULL) { - fprintf(stderr, "tuprecv: mkdtemp failed\n"); - return 1; - } - char srcp[128], errf[128], cmd[2048]; - snprintf(srcp, sizeof srcp, "%s/ctl_destr.ww", tmpdir); - snprintf(errf, sizeof errf, "%s/err.txt", tmpdir); - - int fail = 0; - FILE *f = fopen(srcp, "wb"); - if (f == NULL) { - fprintf(stderr, "tuprecv: source open failed\n"); - fail++; - goto cleanup; - } - int writefail = fputs(src, f) == EOF; - if (fclose(f) != 0) writefail = 1; - if (writefail) { - fprintf(stderr, "tuprecv: source write failed\n"); - fail++; - goto cleanup; - } - - /* w6c_ww must compile the construct cleanly AND emit no asserttyped. */ - snprintf(cmd, sizeof cmd, "%s -o /dev/null %s 2>%s", w6c_ww, srcp, errf); - if (runwait(cmd) != 0) { - fprintf(stderr, "tuprecv: w6c_ww failed to compile the " - "float-destructure construct\n"); - fail++; - } - snprintf(cmd, sizeof cmd, "grep -q asserttyped %s", errf); - if (runwait(cmd) == 0) { - fprintf(stderr, "tuprecv: w6c_ww emitted asserttyped on the " - "un-annotated float destructure binding (#121 stamp net)\n"); - fail++; - } - -cleanup: - { - int cleanfail = 0; - if (unlink(errf) != 0 && errno != ENOENT) cleanfail = 1; - if (unlink(srcp) != 0 && errno != ENOENT) cleanfail = 1; - if (rmdir(tmpdir) != 0) cleanfail = 1; - if (cleanfail) { - fprintf(stderr, "tuprecv: temporary cleanup failed\n"); - fail++; - } - } - if (fail) return 1; - printf("tuprecv: asserttyped-absence pin ok (#121)\n"); - return 0; -} diff --git a/test/wcc/956_modqualdestr_run.c b/test/wcc/956_modqualdestr_run.c deleted file mode 100644 index bc15ed03..00000000 --- a/test/wcc/956_modqualdestr_run.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 956_modqualdestr_run — byte-id + stamp regression net for - * #6a-A: module-qualified destructure binding types. - * - * THE GAP: the wwstage N_MLET handler (check.ww) backfilled destructure - * binding types only when the call rhs had a bare N_IDENT callee. A - * module-qualified `let (frac, exp) = myf.frexp(x)` has an N_DOT callee, - * so the bindings stayed un-stamped (n.type_ nil). cstage never gated on - * callee kind (cmd/wcc/check.c N_MLET → cexpr ungated), so this was a - * wwstage-only stamp gap. #6a-A broadens the backfill to ANY call rhs; - * exprtype's N_CALL arm resolves the N_DOT callee's leaf for the - * resolvable case (leaf unique across modules — the myf.* shapes here). - * - * THE PAYOFF (float row): an un-stamped f64 destructure binding fed to - * float arithmetic mis-classifies as integer-kind 0 in cgen's - * exprfloatkind (n.type_ is the SSoT after the #121 collapse). The - * residual cgbin float-arith sibling-evidence guard turns that into a - * loud abort, so pre-fix w6c_ww FAILS TO COMPILE the float row (no .s - * emitted) — the cs==ww gate (b) and the stamp gate (c) both catch it. - * Post-fix the binding stamps f64, the SSE-cursor receive lands, and - * both stages emit byte-identical asm. - * - * Sibling of 956_tuprecv_f64_run (same-module float destructure, bare - * N_IDENT callee) and 953_f64crossmod_run (single-call module-qualified - * f64). Single-file multi-package form (like 953) so w6c/w6c_ww see the - * cross-module call without -I plumbing. Runtime values now live in - * r956_modqual_* fixtures. This carrier retains two dimensions: - * (a) w6c vs w6c_ww `.s` cmp — rule-10 byte-id; pre-fix the float row - * diverges (w6c_ww loud-aborts, emits no .s). - * (b) #6a-A stamp gate: w6c_ww must emit no `asserttyped:` diagnostic - * on the destructure binding idents. Pre-fix fires on every use. - */ -#include -#include -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -struct row { - const char *label; - const char *src; -}; - -static const struct row rows[] = { - /* HEADLINE — module-qualified FLOAT destructure (f64, i64). frac is - * fed to float arith (`frac + 1.0`), forcing exprfloatkind to read - * its stamp. Pre-fix frac.type_==nil -> kind 0 -> cgbin float-arith - * loud-abort in w6c_ww. Post-fix frac stamps f64. frac=8.0 -> g=9.0; - * exp=1. */ - { "mq_f64_i64_destr", - "package myf;\n" - "export fn frexp(n: f64) (f64, i64) = {\n" - "\tif (n == 0.0) { return (0.0, 0i64); };\n" - "\treturn (n, 1i64);\n" - "};\n" - "package main;\n" - "import myf;\n" - "export fn main() i32 = {\n" - "\tlet (frac, exp) = myf.frexp(8.0);\n" - "\tlet g: f64 = frac + 1.0;\n" - "\tif (g != 9.0) { return 1; };\n" - "\tif (exp != 1i64) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - /* DOMINANT CLASS-A — module-qualified INTEGER destructure (the - * checked.addXX shape: `let (res, ov) = checked.addi64(a, b)`). cgen's - * structural classifier already routed the integer codegen, so this - * is byte-id pre- and post-fix; the discriminator is the (c) stamp - * gate — pre-fix res/ov fire asserttyped. res=15, ov=false. */ - { "mq_i64_bool_destr", - "package myf;\n" - "export fn addi64(a: i64, b: i64) (i64, bool) = {\n" - "\tlet s: i64 = a + b;\n" - "\treturn (s, false);\n" - "};\n" - "package main;\n" - "import myf;\n" - "export fn main() i32 = {\n" - "\tlet (res, ov) = myf.addi64(7i64, 8i64);\n" - "\tif (res != 15i64) { return 1; };\n" - "\tif (ov) { return 2; };\n" - "\treturn (res: i32);\n" - "};\n" }, - /* MIXED — module-qualified (f64, str) destructure: the float rides - * the SSE cursor (X0), the str rides the integer cursor (AX,DX,CX). - * Confirms the stamp distributes correctly onto a wide-header binding - * alongside the float. f=4.0 -> 4; s.len=5 ("hello"). */ - { "mq_f64_str_destr", - "package myf;\n" - "export fn fs(n: f64) (f64, str) = {\n" - "\tif (n == 0.0) { return (n, \"x\"); };\n" - "\treturn (n, \"hello\");\n" - "};\n" - "package main;\n" - "import myf;\n" - "export fn main() i32 = {\n" - "\tlet (f, s) = myf.fs(4.0);\n" - "\tlet g: f64 = f + 0.0;\n" - "\tif (g != 4.0) { return 1; };\n" - "\tif (s.len != 5) { return 2; };\n" - "\treturn (f: i32);\n" - "};\n" }, - /* CLASS-CLOSURE — NON-destructure cross-module same-leaf shadow. The - * #6a-A fix lives at the exprtype N_CALL root, so it closes the whole - * class, not just the destructure surface (same coverage-trap as the - * 6.0b gap-corpus probe). beta.dup -> (i64,i64), alpha.dup -> (i64,str); - * alpha is source-ordered LAST so its (i64,str) heads the flat-scope - * bare-leaf bucket (753_convwrap_audit's trick). `let r = beta.dup()` - * is a SINGLE-VAR receive (no destructure). Pre-fix the bare-leaf - * scopelookup stamped r off alpha.dup's (i64,str) 32B shape, so the - * wwstage cglet sized a $32 / AX,DX,CX,R8 slot while cstage (typed AST) - * sized $16 -> a cs!=ww rule-10 DIVERGENCE this row catches. Post-fix - * the SK_USE-gated scopelookupinmodule resolves beta.dup -> $16, byte- - * id. r.0=3, r.1=7 -> 10. */ - { "mq_nondestr_shadow", - "package beta;\n" - "export fn dup() (i64, i64) = { return (3i64, 7i64); };\n" - "package main;\n" - "import beta;\n" - "export fn main() i32 = {\n" - "\tlet r = beta.dup();\n" - "\tif (r.1 != 7i64) { return 1; };\n" - "\treturn (r.0: i32) + (r.1: i32);\n" - "};\n" - "package alpha;\n" - "export fn dup() (i64, str) = { return (9i64, \"wrong\"); };\n" }, - { NULL, NULL } -}; - -static int -slurp_eq(const char *a, const char *b) -{ - FILE *fa = fopen(a, "rb"); - FILE *fb = fopen(b, "rb"); - if (!fa || !fb) { if (fa) fclose(fa); if (fb) fclose(fb); return -1; } - int rc = 0; - for (;;) { - int ca = fgetc(fa); - int cb = fgetc(fb); - if (ca != cb) { rc = -1; break; } - if (ca == EOF) break; - } - fclose(fa); fclose(fb); - return rc; -} - -int -main(void) -{ - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - char absbin[1024]; - if (bin[0] != '/') { - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return 1; - snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); - bin = absbin; - } - - char w6c[1100], w6c_ww[1100]; - snprintf(w6c, sizeof w6c, "%s/w6c", bin); - snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin); - if (access(w6c_ww, X_OK) != 0) { - fprintf(stderr, "modqualdestr: w6c_ww missing — cannot run the " - "cs==ww byte-id gate\n"); - return 1; - } - - int n = 0, fail = 0; - for (int i = 0; rows[i].src; i++, n++) { - /* Every compiler input, output, and capture lives under one - * collision-safe directory owned by this row. */ - char tmpdir[] = "/tmp/wwmqd_XXXXXX"; - if (mkdtemp(tmpdir) == NULL) { - fprintf(stderr, "row[%s]: mkdtemp failed\n", rows[i].label); - fail++; - continue; - } - - char src[128]; - snprintf(src, sizeof src, "%s/case.ww", tmpdir); - FILE *f = fopen(src, "wb"); - if (f == NULL) { - fprintf(stderr, "row[%s]: source open failed\n", rows[i].label); - fail++; - goto row_cleanup; - } - int writefail = fputs(rows[i].src, f) == EOF; - if (fclose(f) != 0) writefail = 1; - if (writefail) { - fprintf(stderr, "row[%s]: source write failed\n", rows[i].label); - fail++; - goto row_cleanup; - } - - char cmd[2048]; - - /* cs==ww byte-id gate: emit .s from both stages, cmp. */ - char cs_s[128], ws_s[128]; - snprintf(cs_s, sizeof cs_s, "%s/cs.s", tmpdir); - snprintf(ws_s, sizeof ws_s, "%s/ww.s", tmpdir); - - snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", - w6c, cs_s, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c failed\n", rows[i].label); - fail++; - goto row_cleanup; - } - snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", - w6c_ww, ws_s, src); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c_ww failed\n", - rows[i].label); - fail++; - goto row_cleanup; - } - if (slurp_eq(cs_s, ws_s) != 0) { - fprintf(stderr, - "row[%s]: cstage/wwstage .s DIFFER (rule-10 " - "byte-id violation)\n", rows[i].label); - fail++; - } - - /* The module-qualified destructure - * binding must carry a checker type stamp, so w6c_ww emits no - * `asserttyped:` diagnostic on its idents. Non-vacuous — - * pre-fix (HEAD) w6c_ww fires asserttyped on every binding use - * (and the float row loud-aborts in cgen above). */ - char errf[128]; - snprintf(errf, sizeof errf, "%s/err.txt", tmpdir); - snprintf(cmd, sizeof cmd, - "%s -o /dev/null %s 2>%s", w6c_ww, src, errf); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c_ww stamp probe failed\n", - rows[i].label); - fail++; - } - snprintf(cmd, sizeof cmd, "grep -q asserttyped %s", errf); - if (runwait(cmd) == 0) { - fprintf(stderr, "row[%s]: w6c_ww emitted asserttyped " - "(destructure binding unstamped)\n", rows[i].label); - fail++; - } - -row_cleanup: - { - int cleanfail = 0; - char path[128]; - const char *children[] = { - "case.ww", "cs.s", "ww.s", "err.txt", NULL - }; - for (int j = 0; children[j]; j++) { - snprintf(path, sizeof path, "%s/%s", tmpdir, children[j]); - if (unlink(path) != 0 && errno != ENOENT) cleanfail = 1; - } - if (rmdir(tmpdir) != 0) cleanfail = 1; - if (cleanfail) { - fprintf(stderr, "row[%s]: temporary cleanup failed\n", - rows[i].label); - fail++; - } - } - } - - if (fail) { - fprintf(stderr, "%d/%d modqual-destructure tests failed\n", - fail, n); - return 1; - } - printf("modqualdestr: %d/%d ok (cs==ww byte-id + " - "stamp)\n", n, n); - return 0; -} diff --git a/test/wcc/956_tuprecv_f64_run.c b/test/wcc/956_tuprecv_f64_run.c deleted file mode 100644 index 1243dab6..00000000 --- a/test/wcc/956_tuprecv_f64_run.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 956_tuprecv_f64_run (SLIM PIN, #5-C4) — the #121 A-narrow asserttyped stamp - * dimension for the f64 tuple-receive DESTRUCTURE bindings. The runtime VALUE - * rows + cs==ww byte-id migrated to test/lang/tuprecv_f64_test.ww; what stays - * here is the one dimension test-lang has no channel for: a wwstage-STDERR grep - * that w6c_ww emits NO `asserttyped:` diagnostic on the un-annotated float - * destructure binding (the binding must carry a checker type stamp so cgen's - * class-aware spill fires). cstage has no ww asserttyped pass, so this is - * w6c_ww-only by construction (project memory: audit the *_ww binary). - * - * NON-VACUITY (drew C4 mutation gate): the grep is LIVE — pre-stamp HEAD w6c_ww - * fires `asserttyped` on the f64 binding ident (nil n.type_), and the grep - * mechanically fires on a synthetic `asserttyped:` line (self-checked below at - * startup; a broken grep FAILS the test before any row runs). - * - * Slim sibling of the C2 precedent (954 ctl_destr's asserttyped sub-dimension, - * test/lang/tuprecv_test.ww). The 6 rows are the chk_stamped subset of the - * original 956 driver; non-float / control rows carry no stamp dimension and - * live only in the @test file. - */ -#include -#include -#include -#include -#include -#include - -static int -runwait(const char *cmd) -{ - int rc = system(cmd); - if (rc == -1) return -1; - if (WIFEXITED(rc)) return WEXITSTATUS(rc); - return -1; -} - -struct row { const char *label; const char *src; }; - -static const struct row rows[] = { - { "destr_f64_i64_br", - "package main;\n" - "fn issub(n: f64) bool = { return false; };\n" - "fn norm(n: f64) (f64, i64) = {\n" - "\tif (issub(n)) { return (n*2.0, -52); };\n" - "\treturn (n, 0);\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (m, i) = norm(16.0);\n" - "\tif (m != 16.0) { return 1; };\n" - "\tif (i != 0) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - { "destr_i64_f64_br", - "package main;\n" - "fn issub(n: f64) bool = { return false; };\n" - "fn norm(n: f64) (i64, f64) = {\n" - "\tif (issub(n)) { return (-52, n*2.0); };\n" - "\treturn (0, n);\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (i, m) = norm(16.0);\n" - "\tif (m != 16.0) { return 1; };\n" - "\tif (i != 0) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - { "f64f64_destr_br", - "package main;\n" - "fn issub(n: f64) bool = { return false; };\n" - "fn pair(a: f64, b: f64) (f64, f64) = {\n" - "\tif (issub(a)) { return (a*2.0, b*2.0); };\n" - "\treturn (a, b);\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (x, y) = pair(3.0, 5.0);\n" - "\tif (x != 3.0) { return 1; };\n" - "\tif (y != 5.0) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - { "i64_f64_i64_destr", - "package main;\n" - "fn issub(n: i64) bool = { return false; };\n" - "fn tri(a: i64, b: f64, c: i64) (i64, f64, i64) = {\n" - "\tif (issub(a)) { return (a*2, b*2.0, c*2); };\n" - "\treturn (a, b, c);\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (x, y, z) = tri(3, 2.0, 7);\n" - "\tif (x != 3) { return 1; };\n" - "\tif (y != 2.0) { return 2; };\n" - "\tif (z != 7) { return 3; };\n" - "\treturn 0;\n" - "};\n" }, - { "f64_str_destr", - "package main;\n" - "fn issub(n: f64) bool = { return false; };\n" - "fn fs(n: f64) (f64, str) = {\n" - "\tif (issub(n)) { return (n*2.0, \"x\"); };\n" - "\treturn (n, \"hello\");\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (f, s) = fs(4.0);\n" - "\tif (f != 4.0) { return 1; };\n" - "\tif (s.len != 5) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - { "str_f64_destr", - "package main;\n" - "fn issub(n: f64) bool = { return false; };\n" - "fn sf(n: f64) (str, f64) = {\n" - "\tif (issub(n)) { return (\"x\", n*2.0); };\n" - "\treturn (\"hello\", n);\n" - "};\n" - "export fn main() i32 = {\n" - "\tlet (s, f) = sf(4.0);\n" - "\tif (s.len != 5) { return 1; };\n" - "\tif (f != 4.0) { return 2; };\n" - "\treturn 0;\n" - "};\n" }, - { NULL, NULL } -}; - -/* The asserttyped diagnostic only appears in w6c_ww (the wwstage checker audit); - * an absent w6c_ww means the gate cannot run — fail loud. */ -int -main(void) -{ - const char *bin = getenv("BIN"); - if (!bin) bin = "out/bin"; - char absbin[1024]; - if (bin[0] != '/') { - char cwd[1024]; - if (getcwd(cwd, sizeof cwd) == NULL) return 1; - snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); - bin = absbin; - } - - char w6c_ww[1100]; - snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin); - if (access(w6c_ww, X_OK) != 0) { - fprintf(stderr, "tuprecv_f64: w6c_ww missing — cannot run the " - "asserttyped stamp gate (the whole point of this pin)\n"); - return 1; - } - - int n = 0, fail = 0; - - /* NON-VACUITY self-check: the grep must FIRE on a literal asserttyped - * line. A grep that never matches would pass every row vacuously. */ - { - char probedir[] = "/tmp/wwtupf_probe_XXXXXX"; - if (mkdtemp(probedir) == NULL) { - fprintf(stderr, "tuprecv_f64: probe mkdtemp failed\n"); - return 1; - } - char probe[128], cmd[256]; - snprintf(probe, sizeof probe, "%s/probe.txt", probedir); - int probe_fail = 0; - FILE *p = fopen(probe, "wb"); - if (!p) { - fprintf(stderr, "tuprecv_f64: probe open failed\n"); - probe_fail = 1; - } else { - int writefail = - fputs("error: asserttyped: e.type_ nil\n", p) == EOF; - if (fclose(p) != 0) writefail = 1; - if (writefail) { - fprintf(stderr, "tuprecv_f64: probe write failed\n"); - probe_fail = 1; - } else { - snprintf(cmd, sizeof cmd, "grep -q asserttyped %s", probe); - if (runwait(cmd) != 0) { - fprintf(stderr, "tuprecv_f64: grep self-check FAILED — the " - "asserttyped gate is vacuous\n"); - probe_fail = 1; - } - } - } - int cleanfail = 0; - if (unlink(probe) != 0 && errno != ENOENT) cleanfail = 1; - if (rmdir(probedir) != 0) cleanfail = 1; - if (cleanfail) - fprintf(stderr, "tuprecv_f64: probe cleanup failed\n"); - if (probe_fail || cleanfail) return 1; - } - - for (int i = 0; rows[i].src; i++, n++) { - char tmpdir[] = "/tmp/wwtupf_XXXXXX"; - if (mkdtemp(tmpdir) == NULL) { - fprintf(stderr, "row[%s]: mkdtemp failed\n", rows[i].label); - fail++; - continue; - } - char src[128], errf[128], cmd[2048]; - snprintf(src, sizeof src, "%s/case.ww", tmpdir); - snprintf(errf, sizeof errf, "%s/err", tmpdir); - - FILE *f = fopen(src, "wb"); - if (f == NULL) { - fprintf(stderr, "row[%s]: source open failed\n", rows[i].label); - fail++; - goto row_cleanup; - } - int writefail = fputs(rows[i].src, f) == EOF; - if (fclose(f) != 0) writefail = 1; - if (writefail) { - fprintf(stderr, "row[%s]: source write failed\n", rows[i].label); - fail++; - goto row_cleanup; - } - - snprintf(cmd, sizeof cmd, "%s -o /dev/null %s 2>%s", - w6c_ww, src, errf); - if (runwait(cmd) != 0) { - fprintf(stderr, "row[%s]: w6c_ww stamp probe failed\n", - rows[i].label); - fail++; - } - snprintf(cmd, sizeof cmd, "grep -q asserttyped %s", errf); - if (runwait(cmd) == 0) { - fprintf(stderr, "row[%s]: w6c_ww emitted asserttyped " - "(destructure float binding unstamped)\n", - rows[i].label); - fail++; - } - -row_cleanup: - { - int cleanfail = 0; - if (unlink(errf) != 0 && errno != ENOENT) cleanfail = 1; - if (unlink(src) != 0 && errno != ENOENT) cleanfail = 1; - if (rmdir(tmpdir) != 0) cleanfail = 1; - if (cleanfail) { - fprintf(stderr, "row[%s]: temporary cleanup failed\n", - rows[i].label); - fail++; - } - } - } - - if (fail) { - fprintf(stderr, "%d/%d tuprecv_f64 asserttyped-stamp rows failed\n", - fail, n); - return 1; - } - printf("tuprecv_f64: %d/%d ok (asserttyped stamp pin, w6c_ww)\n", n, n); - return 0; -}