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:
@@ -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