test: banner purge + WHY-only comment sweep (rule 8)
Every section banner dies (103 -> 0) across test/lang, the observer suites, the C carriers, and the five comment-heavy corpus fixtures; banner provenance (#N cites, carrier numbers, repair-cluster labels) folded into headers or adjacent WHY comments. Narration deleted; row provenance, ref cites, divergence pins, and layout contracts kept (fwd-ref decl-order guards and bootstrap-gate corpus rationale restored where the sweep over-cut). Comment-only proven: all 3742 wwbuild workdir .s byte-identical before/after; test-commit and test-byteid (161 lang + 1399 data, 0 pinned-divergent) green.
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
/*
|
||||
* 000_smoke — Phase 0 smoke test.
|
||||
*
|
||||
* Asserts arena allocation and growth through libwcc, plus the configured
|
||||
* version constant. Driver behavior belongs to the driver integration tests.
|
||||
*/
|
||||
/* Driver behavior belongs to the driver integration tests. */
|
||||
#include "ww.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
/*
|
||||
* 100_lex — table-driven lexer tests.
|
||||
*
|
||||
* Each row is a (src, expected) pair. The expected string is the
|
||||
* concatenation of token names, space-separated. For literals we
|
||||
* also encode the value: e.g. INT(42), STR("hi"), IDENT(foo).
|
||||
*
|
||||
* EOF is implicit: the harness checks that lexnext returns TK_EOF
|
||||
* after the last expected token.
|
||||
*/
|
||||
#include "ww.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -75,7 +65,6 @@ static const struct row rows[] = {
|
||||
{ "// comment\n", "" },
|
||||
{ "/* a /b/ c */", "" },
|
||||
|
||||
/* identifiers + keywords */
|
||||
{ "foo", "IDENT(foo)" },
|
||||
{ "fn", "fn" },
|
||||
{ "fn main", "fn IDENT(main)" },
|
||||
@@ -84,7 +73,6 @@ static const struct row rows[] = {
|
||||
{ "if else for switch case return import type struct defer break continue proc chan nil true false package",
|
||||
"if else for switch case return import type struct defer break continue proc chan nil true false package" },
|
||||
|
||||
/* numbers */
|
||||
{ "0", "INT(0)" },
|
||||
{ "42", "INT(42)" },
|
||||
{ "1_000_000", "INT(1000000)" },
|
||||
@@ -95,7 +83,6 @@ static const struct row rows[] = {
|
||||
{ "3.14", "FLOAT(3.14)" },
|
||||
{ "1.5e3", "FLOAT(1500)" },
|
||||
|
||||
/* strings & runes */
|
||||
{ "\"hello\"", "STR(hello)" },
|
||||
{ "\"a\\nb\"", "STR(a\nb)" },
|
||||
{ "'A'", "RUNE(65)" },
|
||||
@@ -122,7 +109,6 @@ static const struct row rows[] = {
|
||||
{ "'\\uD7FF'", "RUNE(55295)" },
|
||||
{ "'\\uE000'", "RUNE(57344)" },
|
||||
|
||||
/* operators & punct */
|
||||
{ "+ - * / % == != < > <= >= && || !",
|
||||
"+ - * / % == != < > <= >= && || !" },
|
||||
{ "= += -= *= /= %= &= |= ^= <<= >>=",
|
||||
@@ -136,15 +122,14 @@ static const struct row rows[] = {
|
||||
{ "@symbol(\"malloc\")",
|
||||
"@ IDENT(symbol) ( STR(malloc) )" },
|
||||
|
||||
/* mixed */
|
||||
{ "fn add(a: i32, b: i32) i32 = { return a + b; };",
|
||||
"fn IDENT(add) ( IDENT(a) : IDENT(i32) , IDENT(b) : IDENT(i32) ) IDENT(i32) = { return IDENT(a) + IDENT(b) ; } ;" },
|
||||
};
|
||||
|
||||
/* Escape error cases. A bad escape sets l.errs (the string/rune still
|
||||
* lexes with the offending codepoint zeroed), so detection is via the
|
||||
* error counter, not the token stream. The verbatim Hare messages live
|
||||
* at lexunicode in cmd/wcc/lex.c. */
|
||||
/* A bad escape sets l.errs (the string/rune still lexes with the
|
||||
* offending codepoint zeroed), so detection is via the error counter,
|
||||
* not the token stream. The verbatim Hare messages live at lexunicode
|
||||
* in cmd/wcc/lex.c. */
|
||||
static int
|
||||
runerr(const char *src)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 200_parse — parser tests.
|
||||
*
|
||||
* Two flavours:
|
||||
* 1) "must parse": source must produce a Node and no errors.
|
||||
* 2) "shape match": parsed AST printed via astprint, compared against
|
||||
* expected substring (so tests stay readable without binding to
|
||||
* every position field).
|
||||
* Shape rows compare astprint output against a substring, not a full
|
||||
* golden, so tests stay readable without binding to every position
|
||||
* field.
|
||||
*/
|
||||
#include "ww.h"
|
||||
#include <stdio.h>
|
||||
@@ -136,34 +132,20 @@ main(void)
|
||||
"fn fnt(f: fn(i32) i32, x: i32) i32 = { return f(x); };",
|
||||
"fn anontype() void = { let f: fn(i32) i32 = id; };",
|
||||
|
||||
/* multiple decls */
|
||||
"import io;\nimport fmt;\ndef N: i32 = 8;\ntype p = struct{x:i32};\nfn f() void = {};",
|
||||
/* attribute on FFI decl */
|
||||
"@symbol(\"strlen\") fn cstrlen(s: *u8) u64;",
|
||||
/* trailing comma */
|
||||
"fn f(a: i32, b: i32,) void = {};",
|
||||
/* nil/true/false */
|
||||
"fn f() void = { let p: *i32 = nil; let x: bool = true; let y: bool = false; };",
|
||||
/* chan */
|
||||
"fn ch() void = { let c: chan i32; let v = <-c; };",
|
||||
/* nested struct lit */
|
||||
"fn lit2() void = { let q = box { p = nil, n = 0, items = [1, 2] }; };",
|
||||
/* defer with call */
|
||||
"fn f() void = { defer close(fd); return; };",
|
||||
/* break / continue */
|
||||
"fn f() void = { for () { if (x) { break; }; continue; }; };",
|
||||
/* deeply nested expr */
|
||||
"fn deep() i32 = { return ((((((1 + 2) * 3) - 4) / 5) % 6) << 7); };",
|
||||
/* index chain */
|
||||
"fn ix() i32 = { return a[b][c[d]]; };",
|
||||
/* dot chain */
|
||||
"fn dot() i32 = { return a.b.c.d; };",
|
||||
/* call chain */
|
||||
"fn cc() i32 = { return f()()(); };",
|
||||
/* mixed postfix */
|
||||
"fn mx() i32 = { return obj.method(arg)[idx].field; };",
|
||||
|
||||
/* multi-return tuples */
|
||||
"fn divmod(a: i64, b: i64) (i64, i64) = { return a / b, a % b; };",
|
||||
"fn try() (i32, str) = { return 0, \"\"; };",
|
||||
"fn use_tuple() void = { let q, r = divmod(10, 3); };",
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
* 300_check — type-checker tests.
|
||||
*
|
||||
* Each row is (src, expect) where expect is "ok" (no errors) or a
|
||||
* substring that must appear in the captured stderr.
|
||||
*/
|
||||
#include "ww.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -54,7 +48,6 @@ runrow(const char *src, const char *expect)
|
||||
struct row { const char *src, *expect; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* OK cases */
|
||||
{ "fn main() void = {};", "ok" },
|
||||
{ "fn id(x: i32) i32 = { return x; };", "ok" },
|
||||
{ "fn add(a: i32, b: i32) i32 = { return a + b; };", "ok" },
|
||||
@@ -81,14 +74,12 @@ static const struct row rows[] = {
|
||||
"type point = struct { x: i32 };", "ok" },
|
||||
{ "fn loops() void = { for () { break; }; for () { continue; }; };", "ok" },
|
||||
|
||||
/* multi-return tuples */
|
||||
{ "fn divmod(a: i64, b: i64) (i64, i64) = { return a / b, a % b; };", "ok" },
|
||||
{ "fn dm(a: i64, b: i64) (i64, i64) = { return a, b; };\n"
|
||||
"fn caller() i64 = { let q, r = dm(10, 3); return q + r; };", "ok" },
|
||||
{ "fn dm() (i64, i64) = { return 1, 2; };\n"
|
||||
"fn ass() void = { let q: i64 = 0; let r: i64 = 0; q, r = dm(); };", "ok" },
|
||||
|
||||
/* error cases */
|
||||
{ "fn f() void = { return 1; };", "return value in void" },
|
||||
{ "fn f() i32 = { return; };", "not assignable" },
|
||||
{ "fn f() void = { x = 1; };", "undefined" },
|
||||
@@ -111,7 +102,6 @@ static const struct row rows[] = {
|
||||
"not enough arguments" },
|
||||
{ "fn f() void = { if (1) { }; };", "if condition" },
|
||||
|
||||
/* tagged-union normalization & exhaustiveness */
|
||||
{ "fn f() (i32 | never) = { return 7; }; "
|
||||
"fn g() i32 = { return f(); };", "ok" }, /* (T|never) → T */
|
||||
{ "fn f() (i32 | i32) = { return 5; }; "
|
||||
@@ -130,7 +120,6 @@ static const struct row rows[] = {
|
||||
{ "fn die() never = { for (true) { let _: i32 = 1; }; }; "
|
||||
"fn f() i32 = { die(); };", "ok" }, /* never assignable to anything */
|
||||
|
||||
/* ? error-subset propagation typecheck */
|
||||
{ "fn inner() (i32 | str) = { return 1; }; "
|
||||
"fn outer() i32 = { let v: i32 = inner()?; return v; };",
|
||||
"enclosing function must return a tagged union" },
|
||||
@@ -155,7 +144,6 @@ static const struct row rows[] = {
|
||||
{ "fn lookup(p: *i32) (*i32 | void) = { return p; };", "ok" },
|
||||
{ "fn lookup() (*i32 | void) = { return; };", "ok" }, /* bare return → null */
|
||||
|
||||
/* `case T` must name a variant of the scrutinee */
|
||||
{ "fn pick() (i32 | str) = { return 1; }; "
|
||||
"fn caller() void = { let v: (i32 | str) = pick(); "
|
||||
"match (v) { case let n: i32 => { }; case let s: str => { }; "
|
||||
@@ -168,7 +156,6 @@ static const struct row rows[] = {
|
||||
"return 0; };",
|
||||
"case: f64 is not a variant" },
|
||||
|
||||
/* enum types */
|
||||
{ "type color = enum { RED, GREEN, BLUE };\n"
|
||||
"fn f() i32 = { return color.GREEN as i32; };", "ok" },
|
||||
{ "type mode = enum u8 { R = 1, W = 2, RW = R | W };\n"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* 400_w6c — in-process codegen smoke tests. Each row supplies one tiny ww
|
||||
* source and the assembly fragments it must emit. Full-file golden matches
|
||||
* Rows match assembly fragments, not full-file goldens: golden matches
|
||||
* would bind the test to unrelated output details.
|
||||
*/
|
||||
#include "gc.h"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* 738_module_decl — sentinel for the `package <name>;` keyword.
|
||||
*
|
||||
* Pins three invariants from the module-system rewrite:
|
||||
* 1. The parser ACCEPTS `package foo;` as the first non-comment item.
|
||||
* 2. The parser ACCEPTS multiple `package X;` decls (concatenated
|
||||
@@ -70,38 +68,32 @@ main(void)
|
||||
{
|
||||
int pass = 0, fail = 0;
|
||||
|
||||
/* Row 1: `package foo;` accepted as first non-comment item. */
|
||||
if (parses_clean("package foo;\nfn x() void = {};\n")) pass++;
|
||||
else { fprintf(stderr, "738[1] basic package accept FAILED\n"); fail++; }
|
||||
|
||||
/* Row 2: comments before `package foo;` legal. */
|
||||
if (parses_clean("// header\n// more\npackage foo;\nfn x() void = {};\n")) pass++;
|
||||
else { fprintf(stderr, "738[2] package after comments FAILED\n"); fail++; }
|
||||
|
||||
/* Row 3: subsequent decls stamped with current package. */
|
||||
if (check_module_stamps(
|
||||
"package foo;\nfn x() void = {};\nfn y() void = {};\n",
|
||||
"foo", "foo")) pass++;
|
||||
else { fprintf(stderr, "738[3] decl module stamping FAILED\n"); fail++; }
|
||||
|
||||
/* Row 4: concatenated multi-section stream — second package
|
||||
* decl switches the stamp for subsequent decls. Mirrors driver-
|
||||
* emitted multi-file modules. */
|
||||
/* Mirrors driver-emitted multi-file concatenated streams. */
|
||||
if (check_module_stamps(
|
||||
"package foo;\nfn a() void = {};\n"
|
||||
"package bar;\nfn b() void = {};\n",
|
||||
"foo", "bar")) pass++;
|
||||
else { fprintf(stderr, "738[4] mid-stream package switch FAILED\n"); fail++; }
|
||||
|
||||
/* Row 5: dotted import accepted with leaf stored on N_USE. */
|
||||
if (parses_clean(
|
||||
"package foo;\nimport encoding.utf8;\nfn x() void = {};\n")) pass++;
|
||||
else { fprintf(stderr, "738[5] dotted import accept FAILED\n"); fail++; }
|
||||
|
||||
/* Row 6: dotted import stores only the leaf identifier on
|
||||
* N_USE.str (post-task-#22 — the driver translates the full
|
||||
* dotted path to a directory walk; the checker only needs the
|
||||
* package bareword for n_use → decl disambiguation). */
|
||||
/* Dotted import stores only the leaf identifier on N_USE.str
|
||||
* (post-task-#22 — the driver translates the full dotted path to
|
||||
* a directory walk; the checker only needs the package bareword
|
||||
* for n_use → decl disambiguation). */
|
||||
{
|
||||
Arena *a = newarena();
|
||||
Lex l;
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
/*
|
||||
* 810_dyn — end-to-end test of w6l's dynamic linker.
|
||||
* Covers the claims the exit status alone can't show: dyn.c reading
|
||||
* ET_DYN and extracting exports, PLT/GOT generation with JUMP_SLOT
|
||||
* relocations, and PT_INTERP/PT_DYNAMIC emission.
|
||||
*
|
||||
* Drives `ww build -L /usr/lib -l c` over a small ww program that
|
||||
* binds libc symbols via @symbol, then runs the produced binary and
|
||||
* checks the exit status. Verifies:
|
||||
*
|
||||
* - the .so loader (dyn.c) reads ET_DYN and extracts exports
|
||||
* - PLT/GOT generation and the JUMP_SLOT relocation
|
||||
* - PT_INTERP/PT_DYNAMIC emission
|
||||
* - symbol versioning (.gnu.version + .gnu.version_r) — clock_gettime
|
||||
* has both GLIBC_2.2.5 (compat) and GLIBC_2.17 (default) on glibc;
|
||||
* the loader requires the right .gnu.version_r entry to bind
|
||||
* the default vDSO-aware impl.
|
||||
*
|
||||
* Reports the harness skip status on systems without a supported libc.so.6.
|
||||
* Symbol versioning (.gnu.version + .gnu.version_r): clock_gettime has
|
||||
* both GLIBC_2.2.5 (compat) and GLIBC_2.17 (default) on glibc; the
|
||||
* loader requires the right .gnu.version_r entry to bind the default
|
||||
* vDSO-aware impl.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -122,7 +115,6 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
/* Probe each common libc dir to find the right -L. */
|
||||
const char *libdir = NULL;
|
||||
if (access("/usr/lib/libc.so.6", 0) == 0) libdir = "/usr/lib";
|
||||
else if (access("/lib/x86_64-linux-gnu/libc.so.6", 0) == 0) libdir = "/lib/x86_64-linux-gnu";
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/*
|
||||
* 950_selfcheck — selfhost typechecker emits the same errors the
|
||||
* C-side checker does for tagged-union misuse.
|
||||
*
|
||||
* Each row is a .ww fixture + an expected stderr substring. We run
|
||||
* `wwdump_ww -r` (which invokes the selfhost checker's resolve +
|
||||
* typed passes) and grep for the substring.
|
||||
* Parity pin: the selfhost typechecker must emit the same errors the
|
||||
* C-side checker does for tagged-union misuse. `wwdump_ww -r` is the
|
||||
* probe — it invokes the selfhost checker's resolve + typed passes.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -75,7 +72,6 @@ writefile(const char *path, const char *src)
|
||||
struct row { const char *src; const char *expect; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* match: missing variant */
|
||||
{ "fn pick() (i32 | str | bool) = { return 1; };\n"
|
||||
"fn caller() void = {\n"
|
||||
" let v: (i32 | str | bool) = pick();\n"
|
||||
@@ -85,14 +81,12 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
"};\n",
|
||||
"match: variant not handled" },
|
||||
/* ?: enclosing not tagged */
|
||||
{ "fn inner() (i32 | str) = { return 1; };\n"
|
||||
"fn caller() i32 = {\n"
|
||||
" let v: i32 = inner()?;\n"
|
||||
" return v;\n"
|
||||
"};\n",
|
||||
"?: enclosing fn return is not tagged" },
|
||||
/* ?: error variant not in enclosing return */
|
||||
{ "fn inner() (i32 | str | bool) = { return 1; };\n"
|
||||
"fn caller() (i32 | str) = {\n"
|
||||
" let v: i32 = inner()?;\n"
|
||||
@@ -117,7 +111,6 @@ static const struct row rows[] = {
|
||||
" return v + 1;\n"
|
||||
"};\n",
|
||||
"?: error variant not in enclosing return" },
|
||||
/* case T => names a non-variant */
|
||||
{ "fn pick() (i32 | str) = { return 1; };\n"
|
||||
"fn caller() void = {\n"
|
||||
" let v: (i32 | str) = pick();\n"
|
||||
@@ -128,19 +121,16 @@ static const struct row rows[] = {
|
||||
" };\n"
|
||||
"};\n",
|
||||
"case: not a variant" },
|
||||
/* is T where T isn't a variant of the operand */
|
||||
{ "fn pick() (i32 | str) = { return 1; };\n"
|
||||
"fn caller() void = {\n"
|
||||
" let v: (i32 | str) = pick();\n"
|
||||
" if (v is f64) { };\n"
|
||||
"};\n",
|
||||
"is/as: not a variant" },
|
||||
/* let init-type mismatch on primitives */
|
||||
{ "fn caller() void = {\n"
|
||||
" let x: bool = 42;\n"
|
||||
"};\n",
|
||||
"let: not assignable" },
|
||||
/* return type mismatch */
|
||||
{ "fn caller() i32 = {\n"
|
||||
" return \"hi\";\n"
|
||||
"};\n",
|
||||
|
||||
@@ -44,8 +44,6 @@ runwait(const char *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Harvest up to `max` default-versioned libc text exports into syms[][].
|
||||
* Returns the count, or -1 if nm/libc unavailable. */
|
||||
static int
|
||||
harvest_syms(const char *libc, char syms[][32], int max)
|
||||
{
|
||||
@@ -68,8 +66,6 @@ harvest_syms(const char *libc, char syms[][32], int max)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Build with `driver` into <tmpdir>/main, run, return exit code (or -1 on
|
||||
* build failure). Sets *outbin to the produced binary path. */
|
||||
static int
|
||||
build_run(const char *driver, const char *src, const char *libdir,
|
||||
const char *tmpdir, char *outbin, size_t obsz)
|
||||
@@ -119,7 +115,8 @@ main(void)
|
||||
}
|
||||
int fail = 0, total = 0;
|
||||
|
||||
/* ---- big: ~160 gated dead PLT calls, return 42 ---- */
|
||||
/* big: the s%03d calls are gated dead — they exist only to force
|
||||
* enough PLT/dynsym entries to push the headers past one page. */
|
||||
char bigsrc[1024], smallsrc[1024];
|
||||
snprintf(bigsrc, sizeof bigsrc, "%s/big.ww", td);
|
||||
snprintf(smallsrc, sizeof smallsrc, "%s/small.ww", td);
|
||||
@@ -140,7 +137,6 @@ main(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ---- small: 1 dyn sym, headers fit the page ---- */
|
||||
f = fopen(smallsrc, "wb");
|
||||
if (!f) {
|
||||
perror(smallsrc);
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
/*
|
||||
* 991_w6a_ww — explicit bootstrap gate for the ww-side w6a port.
|
||||
*
|
||||
* Diffs the C-built `w6a` against the ww-built `w6a_ww` on a corpus of
|
||||
* .s files. Both must produce byte-identical ELF .o output. The corpus
|
||||
* spans:
|
||||
* - rt/X.s hand-written runtime; small, varied operands
|
||||
* - generated .s from the existing selfhost cgen pipeline
|
||||
* (wwdump/w6a/w6l main.s) - large, exercises
|
||||
* every encoding path w6c emits
|
||||
*
|
||||
* Any divergence is a port bug in selfhost/cmd/w6a/.
|
||||
* Explicit bootstrap gate: the C-built `w6a` and the ww-built `w6a_ww`
|
||||
* must produce byte-identical ELF .o output over the corpus. Any
|
||||
* divergence is a port bug in selfhost/cmd/w6a/. The corpus pairs
|
||||
* hand-written rt/X.s (small, varied operands) with cgen-generated .s
|
||||
* (large — exercises every encoding path w6c emits).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
/*
|
||||
* 992_w6l_ww — explicit bootstrap gate for the ww-side w6l port.
|
||||
*
|
||||
* Diffs the C-built `w6l` against the ww-built `w6l_ww` on a corpus of
|
||||
* link inputs. Both must produce byte-identical static ELF binaries.
|
||||
* The corpus mixes:
|
||||
* - a single .o input (no archive resolution)
|
||||
* - a .o + libwwrt.a link, exercising the SysV `ar` two-pass loader
|
||||
*
|
||||
* Any divergence is a port bug in selfhost/cmd/w6l/.
|
||||
* Explicit bootstrap gate: the C-built `w6l` and the ww-built `w6l_ww`
|
||||
* must produce byte-identical static ELF binaries on the same link
|
||||
* inputs. Any divergence is a port bug in selfhost/cmd/w6l/. The
|
||||
* corpus mixes a single-.o link (no archive resolution) with a
|
||||
* .o + libwwrt.a link exercising the SysV `ar` two-pass loader.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
/*
|
||||
* 993_ww_ww — explicit bootstrap gate for the ww-side driver port.
|
||||
*
|
||||
* Diffs the C-built `ww` against the ww-built `ww_ww`. Both drivers
|
||||
* Explicit bootstrap gate: the C-built `ww` and the ww-built `ww_ww`
|
||||
* orchestrate the same w6c/w6a/w6l, so the resulting binaries must be
|
||||
* byte-identical for every program in the corpus. The corpus mixes:
|
||||
* - a tiny single-file program (no -I flags)
|
||||
* - a multi-import build (selfhost/cmd/wwdump/main.ww), exercising
|
||||
* `use` resolution + the -I search path + the libwwrt.a link.
|
||||
*
|
||||
* Each build runs from a per-driver scratch directory so the
|
||||
* intermediate .s/.o files don't collide.
|
||||
* byte-identical for every program in the corpus. The corpus includes
|
||||
* a multi-import build (selfhost/cmd/wwdump/main.ww) exercising `use`
|
||||
* resolution, the -I search path, and the libwwrt.a link. Each build
|
||||
* runs from a per-driver scratch directory so the intermediate .s/.o
|
||||
* files don't collide.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -62,10 +58,8 @@ slurp_eq(const char *a, const char *b)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Build `src` via the named driver, expecting output binary `out` in
|
||||
* the build directory. `incs` may be a colon-separated list of include
|
||||
* dirs (the ww driver accepts -I path1:path2:path3). Returns 0 on
|
||||
* success. */
|
||||
/* `incs` may be a colon-separated list of include dirs (the ww driver
|
||||
* accepts -I path1:path2:path3). */
|
||||
static int
|
||||
build_via(const char *bin, const char *driver, const char *src,
|
||||
const char *workdir, const char *incs, const char *out_basename)
|
||||
@@ -129,10 +123,8 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Stage a program whose main() returns `code`, build+exec it via the
|
||||
* named driver's `run` subcommand, and return the propagated exit code
|
||||
* (-1 on staging/spawn failure). #16: ww_ww must report the child's real
|
||||
* exit code, not collapse every non-zero exit to 1. */
|
||||
/* #16: `run` must report the child's real exit code, not collapse
|
||||
* every non-zero exit to 1. Returns -1 on staging/spawn failure. */
|
||||
static int
|
||||
run_exit_code(const char *bin, const char *driver, int code)
|
||||
{
|
||||
@@ -160,11 +152,10 @@ run_exit_code(const char *bin, const char *driver, int code)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Stage a program that fails to compile, run it via the named driver,
|
||||
* and return the exit code. Pins the build-step caller contract: a
|
||||
* failing build must still report failure (non-zero). The process mechanism's
|
||||
* exact exit-code return must not regress this, since the
|
||||
* w6c/w6a/w6l callers only test `!= 0`. */
|
||||
/* Pins the build-step caller contract: a failing build must still
|
||||
* report failure (non-zero). The process mechanism's exact exit-code
|
||||
* return must not regress this, since the w6c/w6a/w6l callers only
|
||||
* test `!= 0`. */
|
||||
static int
|
||||
run_build_fail(const char *bin, const char *driver)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/*
|
||||
* 994_w6c_ww — explicit bootstrap gate for the ww-side w6c port.
|
||||
*
|
||||
* w6c_ww is a thin packaging of selfhost/cmd/wcc/cgen.ww: it slurps a
|
||||
* .ww file, runs lex+parse+cgen, and writes Plan 9 amd64 asm to the
|
||||
* file given by -o. The same cgen is reached through `wwdump_ww -c`,
|
||||
* so w6c_ww must produce byte-identical output to wwdump_ww -c on
|
||||
* every program — this test pins that.
|
||||
* w6c_ww and `wwdump_ww -c` reach the same selfhost cgen, so they must
|
||||
* produce byte-identical output on every program — this test pins
|
||||
* that.
|
||||
*
|
||||
* (We do not diff against C-side `w6c` here: this carrier's oracle is
|
||||
* the wwdump_ww -c TOOL OUTPUT, not the tool binary. The C-vs-ww diff
|
||||
@@ -354,7 +350,7 @@ main(void)
|
||||
n++;
|
||||
}
|
||||
|
||||
/* ---- Tier-C capstone (#46 c6, rob-c6-spec §2 / amendment-B; M4 #89) ---
|
||||
/* Tier-C capstone (#46 c6, rob-c6-spec §2 / amendment-B; M4 #89).
|
||||
* The load-bearing M4 oracle: build w6c by SEPARATE compilation under
|
||||
* BOTH driver stages and prove they sep-produce byte-identical per-package
|
||||
* .s/.o/.wwi (cs==ww on the real tool's sep artifacts, rule 10). The
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
/*
|
||||
* 995_self_rebuild — the wwstage rebuilds itself.
|
||||
*
|
||||
* Drives ww_ww (the ww-side driver, which shells to w6c_ww/w6a_ww/w6l_ww)
|
||||
* over each wwstage tool's source and diffs the result byte-for-byte
|
||||
* against the cstage-built binary in $BIN. A green run means the
|
||||
* toolchain can recompile itself without touching cc, modulo the
|
||||
* cold-start binary — which is the v1.0 lock from PLAN.md.
|
||||
* A green run means the toolchain can recompile itself without
|
||||
* touching cc, modulo the cold-start binary — which is the v1.0 lock
|
||||
* from PLAN.md.
|
||||
*
|
||||
* This is stricter than `make bootstrap`: that loop only proves the
|
||||
* wwdump cgen self-stabilises; this proves every wwstage tool round-
|
||||
* trips through the wwstage pipeline.
|
||||
*
|
||||
* The five tool builds run concurrently: fork() per tool, parent
|
||||
* collects each pid with waitpid() and then byte-compares. Wall drops
|
||||
* The five tool builds run concurrently (fork() per tool): wall drops
|
||||
* from sum(builds) to max(builds).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
@@ -84,8 +79,8 @@ struct buildjob {
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
/* Fork a child that runs the `ww_ww build` for this tool. The child
|
||||
* inherits no concurrent siblings — system() spawns a fresh /bin/sh -c.
|
||||
/* The child inherits no concurrent siblings — system() spawns a fresh
|
||||
* /bin/sh -c.
|
||||
* stderr lands in <workdir>/build.err so concurrent builds don't merge
|
||||
* their diagnostics. `-o <workdir>/main` (T3) makes the driver write its
|
||||
* intermediates (main.{s,o} and the sepwork tree) beside the output in <workdir>
|
||||
@@ -137,8 +132,6 @@ spawn_build(const char *bin, const char *cwd, struct buildjob *j)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reap one job, byte-diff rebuilt vs canonical, replay captured stderr
|
||||
* on build failure, rm workdir. Returns 0 on byte-match, -1 otherwise. */
|
||||
static int
|
||||
collect_build(const char *bin, struct buildjob *j)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/*
|
||||
* 996_dyn_ww — phase-8 marker for ET_DYN linking on the ww side.
|
||||
*
|
||||
* Drives w6l_ww with -L/-l flags over examples/mandelbrot/mandelbrot.o and diffs
|
||||
* the result against the C-built w6l on the same inputs. A green run
|
||||
* means the ww-side linker emits PT_INTERP/PT_DYNAMIC binaries byte-
|
||||
* for-byte identical to the C linker — i.e. the dynamic linking story
|
||||
* is fully ported.
|
||||
* Phase-8 marker for ET_DYN linking on the ww side: a green run means
|
||||
* the ww-side linker emits PT_INTERP/PT_DYNAMIC binaries byte-for-byte
|
||||
* identical to the C linker on the same inputs — i.e. the dynamic
|
||||
* linking story is fully ported.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -85,7 +82,6 @@ main(void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* C-side w6l with the dynamic flags. */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/w6l -o %s %s -L /usr/lib "
|
||||
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
||||
@@ -96,7 +92,6 @@ main(void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* ww-side w6l with the same flags. */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/w6l_ww -o %s %s -L /usr/lib "
|
||||
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
|
||||
|
||||
@@ -24,8 +24,6 @@ import os;
|
||||
import strconv;
|
||||
import ascii;
|
||||
|
||||
// --- bump arena ---------------------------------------------------------
|
||||
|
||||
type arena = struct {
|
||||
buf: *u8,
|
||||
off: u64,
|
||||
@@ -49,18 +47,14 @@ fn arena_alloc(a: *arena, n: u64) *u8 = {
|
||||
return p;
|
||||
};
|
||||
|
||||
// --- (i32 | str) error idiom -------------------------------------------
|
||||
|
||||
fn checked_div(num: i32, den: i32) (i32 | str) = {
|
||||
if (den == 0) { return "div by zero"; };
|
||||
return num / den;
|
||||
};
|
||||
|
||||
// --- struct-of-fn-pointer polymorphism ---------------------------------
|
||||
//
|
||||
// A trivial "writer" abstraction: a function pointer plus a context.
|
||||
// This mirrors how io.stream / Plan 9 Bio work. The ctx pointer lets
|
||||
// the implementation own its own state without a global.
|
||||
// A "writer" is a function pointer plus a context, mirroring how
|
||||
// io.stream / Plan 9 Bio work. The ctx pointer lets the implementation
|
||||
// own its own state without a global.
|
||||
|
||||
type counter = struct {
|
||||
n: i32,
|
||||
@@ -76,22 +70,19 @@ fn count_emit(ctx: *void, b: u8) void = {
|
||||
c.n += 1;
|
||||
};
|
||||
|
||||
// --- size/align/offset typed-builtin fixtures (#42) --------------------
|
||||
|
||||
type point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
// Mixed-alignment struct: i8 lays at 0, then i64 needs to skip to
|
||||
// offset 8 (the i64's natural align). Probe asserts both ends.
|
||||
// #42 size/align/offset typed-builtin fixture. Mixed-alignment struct:
|
||||
// i8 lays at 0, then i64 needs to skip to offset 8 (the i64's natural
|
||||
// align). Probe asserts both ends.
|
||||
type mixalign = struct {
|
||||
tag: i8,
|
||||
val: i64,
|
||||
};
|
||||
|
||||
// --- byte scanner like lex.ww's hot path -------------------------------
|
||||
|
||||
fn count_digits(s: str) i32 = {
|
||||
let i: i32 = 0;
|
||||
let n: i32 = 0;
|
||||
@@ -105,8 +96,6 @@ fn count_digits(s: str) i32 = {
|
||||
return n;
|
||||
};
|
||||
|
||||
// --- entry --------------------------------------------------------------
|
||||
|
||||
export fn main() i32 = {
|
||||
// Probe 1 — arena hands out distinct pointers, refuses oversize.
|
||||
let buf: [256]u8;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* wwtestpkg.h — strict-package (#24a) test support.
|
||||
* Strict-package (#24a) test support.
|
||||
*
|
||||
* Inline ww test fixtures historically omitted the `package main;` clause
|
||||
* that the parser now requires (a missing clause is a hard error). These
|
||||
|
||||
Reference in New Issue
Block a user