/* * 630_let_global — top-level mutable `let` end-to-end through the * full Cstage pipeline (w6c → w6a → w6l). Each fixture is a tiny * .ww program that exercises one path: literal-init read, plain * assignment, compound assignment, and address-of. * * Exit code = the value the runtime feeds to `exit(2)`. main's * return value flows into DI via rt/start.s and ends up as the * shell's $?. */ #include #include #include #include static int run_exit(const char *cmd) { int rc = system(cmd); if (rc == -1) return -1; if (WIFEXITED(rc)) return WEXITSTATUS(rc); return -1; } static int build_and_run(const char *bin, const char *prog) { /* `ww run` builds with the driver (w6c → w6a → w6l + libwwrt.a) * and executes the result. The exit code propagates back as the * shell's $? so we just compare against the fixture's want. */ char src[64], cmd[1024]; snprintf(src, sizeof src, "/tmp/wwt_lg_%d.ww", getpid()); FILE *f = fopen(src, "wb"); if (!f) return -1; fputs(prog, f); fclose(f); snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, src); int rc = run_exit(cmd); unlink(src); return rc; } struct fixture { const char *label; const char *prog; int want; }; static const struct fixture fixtures[] = { { "read", "let counter: i32 = 42;\n" "fn main() i32 = { return counter; };\n", 42, }, { "assign", "let counter: i32 = 0;\n" "fn main() i32 = { counter = 99; return counter; };\n", 99, }, { "compound", "let counter: i32 = 1;\n" "fn inc() void = { counter += 1; };\n" "fn main() i32 = { inc(); inc(); inc(); return counter; };\n", 4, }, { "zero-init", /* No initialiser → zero-filled DATAW slot. */ "let counter: i32;\n" "fn main() i32 = { counter = 7; return counter; };\n", 7, }, { "addr-of", "let counter: i32 = 11;\n" "fn main() i32 = {\n" "\tlet p: *i32 = &counter;\n" "\t*p = 55;\n" "\treturn counter;\n" "};\n", 55, }, { "u64-read", "let val: u64 = 123u64;\n" "fn main() i32 = { return val: i32; };\n", 123, }, { NULL, NULL, 0 } }; int main(void) { const char *bin = getenv("BIN"); if (!bin) bin = "out/bin"; int fail = 0, ran = 0; for (int i = 0; fixtures[i].label; i++, ran++) { int got = build_and_run(bin, fixtures[i].prog); if (got != fixtures[i].want) { fprintf(stderr, "let_global[%s]: exit=%d, want %d\n", fixtures[i].label, got, fixtures[i].want); fail++; } } if (fail) { fprintf(stderr, "let_global: %d/%d fixtures failed\n", fail, ran); return 1; } printf("let_global: %d/%d ok\n", ran, ran); return 0; }