test: port the asserttyped stamp probes to ww; retire 954 + 956 slim carriers
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).
This commit is contained in:
3
Makefile
3
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 \
|
||||
|
||||
183
test/misc/stampdiag_test.ww
Normal file
183
test/misc/stampdiag_test.ww
Normal file
@@ -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 <src>: 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;
|
||||
};
|
||||
};
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user