rm dead combined.ww + retarget 901 to sep-feed; sweep amalgamator remnants (M4 E4, #90)
The E3 flip (#87) made sep the sole compile path and deleted the
combined.ww writer, leaving the six committed *.combined.ww files dead.
Remove them and the last references to the retired amalgamator.
- rm the 6 tracked *.combined.ww (selfhost/cmd/{w6a,w6c,w6l,ww,wwdump}/
main.combined.ww + selfhost/test/smoke.combined.ww). Verified no live
build path or gate still feeds one as compiler INPUT.
- 901_asserttyped_gap: its 5 combined.ww gap fixtures were the last
combined.ww INPUT consumers (4 already missing/vacuous post-flip, only
smoke.combined.ww still fed). Retarget all 5 to sep-feed via a
resolveunit helper (whole-package-dir copy -> `ww build --sep` ->
<stem>.sepwork/__root.unit.ww), mirroring 990's #89 pattern; the 3
import-free test fixtures stay raw-fed. All 8 counts hold at 0 (A-D
coverage, vacuous since the flip, is live again).
- INV-2 (the driver's unresolvable-import-is-fatal guard) is KEPT; only
its "Mirrors the deleted expand" lineage tail is swept. The #110
combined_ww_fresh freshness gate was already removed in #89 (5f85852).
- Sweep dangling amalgamator lineage comments (build_one/buildone/expand/
peek_package/peekpackage + stale combined.ww/combined intermediates)
in cmd/ww/main.c + selfhost/cmd/ww/main.ww, symmetrically (rule-10),
and the stale Makefile combined.ww test-comments (enumcap bigmod.unit.ww
+ 784/787/792/794/848 sep .s cmp + make-smoke sep self-compile).
Closes M4 and epic #22. all 445 pass; 990/993/994/995 byte-id HOLD;
sizelint clean.
This commit is contained in:
30
Makefile
30
Makefile
@@ -1066,8 +1066,9 @@ $(BIN)/test_loopcap_run: test/wcc/989_loopcap_run.c \
|
||||
|
||||
# 989_enumcap_run (#65, F13 c3): the driver's directory enumerator grows
|
||||
# dynamically (mirror cstage realloc-doubling) instead of silently capping at
|
||||
# 256 files. Builds on both driver twins and asserts a byte-identical
|
||||
# combined.ww on a >256-file module (rule-10). See the test header.
|
||||
# 256 files. Builds on both driver twins (`--sep`) and asserts a byte-identical
|
||||
# per-package sep unit (bigmod.unit.ww) on a >256-file module (rule-10). See
|
||||
# the test header.
|
||||
$(BIN)/test_enumcap_run: test/wcc/989_enumcap_run.c \
|
||||
$(BIN)/ww $(BIN)/ww_ww \
|
||||
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
@@ -1826,9 +1827,9 @@ $(BIN)/test_type_value_shadow_run: test/wcc/788_type_value_shadow_run.c \
|
||||
|
||||
# #223: a struct-field access through a pointer-ALIAS receiver whose
|
||||
# leaf collides with another module's same-leaf STRUCT. cstage driver
|
||||
# build + run for runtime, raw w6c vs w6c_ww .s cmp on the combined.ww
|
||||
# for rule-10 byte-id (the #223 discriminator). Builds its own 2-module
|
||||
# fixtures in a private mktemp dir — not a selfhost-driver test.
|
||||
# build + run for runtime, cs-sep vs ww-sep .s cmp (concatenated
|
||||
# main.sepwork/*.s) for rule-10 byte-id (the #223 discriminator). Builds its
|
||||
# own 2-module fixtures in a private mktemp dir — not a selfhost-driver test.
|
||||
$(BIN)/test_xmod_alias_struct_collide_run: test/wcc/784_xmod_alias_struct_collide_run.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
|
||||
@@ -1837,8 +1838,8 @@ $(BIN)/test_xmod_alias_struct_collide_run: test/wcc/784_xmod_alias_struct_collid
|
||||
|
||||
# #13: cross-module decomposition of an imported union's variants
|
||||
# (`case pkg.a`). Pre-fix the wwstage checker rejected it; cstage built
|
||||
# it. cstage driver build + run pins routing; raw w6c_ww on the
|
||||
# combined.ww (must now accept) + cs==ww byte-id is the discriminator.
|
||||
# it. cstage driver build + run pins routing; ww-sep build (w6c_ww must
|
||||
# now accept) + cs-sep==ww-sep byte-id is the discriminator.
|
||||
# Builds its own 2-module fixtures in a private mktemp dir.
|
||||
$(BIN)/test_xmod_variant_match: test/wcc/787_xmod_variant_match.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
@@ -1851,8 +1852,8 @@ $(BIN)/test_xmod_variant_match: test/wcc/787_xmod_variant_match.c \
|
||||
# to an N_DOT chain the checker's resolve_type had no arm for); the fix
|
||||
# flattens the chain to one N_TNAME at the struct-lit handoff in BOTH
|
||||
# stages. cstage driver build + run pins parse + runtime field values;
|
||||
# raw w6c vs w6c_ww on the combined.ww is the rule-10 byte-id gate.
|
||||
# Builds its own 2-module fixtures in a private mktemp dir.
|
||||
# cs-sep vs ww-sep .s cmp (concatenated main.sepwork/*.s) is the rule-10
|
||||
# byte-id gate. Builds its own 2-module fixtures in a private mktemp dir.
|
||||
$(BIN)/test_xmod_qualstructlit_run: test/wcc/848_xmod_qualstructlit_run.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
|
||||
@@ -1866,7 +1867,7 @@ $(BIN)/test_xmod_qualstructlit_run: test/wcc/848_xmod_qualstructlit_run.c \
|
||||
# ("case: not a variant" / "variant not handled"), so any fmt-importing
|
||||
# unit was wwstage-uncompilable. Fix flattens the spread in the checker's
|
||||
# match validity + exhaustiveness walk (selfhost/cmd/wcc/check.ww). The
|
||||
# w6c_ww-accepts + cs==ww byte-id on the driver combined is the
|
||||
# w6c_ww-accepts + cs-sep==ww-sep byte-id on the driver sep build is the
|
||||
# discriminator. Self-contained single-file probe.
|
||||
$(BIN)/test_spread_variant_match: test/wcc/792_spread_variant_match.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
@@ -1882,7 +1883,7 @@ $(BIN)/test_widen_pad_zero_run: test/wcc/793_widen_pad_zero_run.c \
|
||||
|
||||
# #55: bare value-ident in an imported module must resolve same-module-
|
||||
# preferred (exprtype N_IDENT scopelookup -> scopelookupprefer). cstage
|
||||
# driver build + run pins routing; raw w6c_ww on the combined must ACCEPT
|
||||
# driver build + run pins routing; the ww-sep build (w6c_ww) must ACCEPT
|
||||
# (pre-fix it rejected the wrong-module-typed ident). Builds its own
|
||||
# 2-module fixtures in a private mktemp dir.
|
||||
$(BIN)/test_xmod_ident_prefer: test/wcc/794_xmod_ident_prefer.c \
|
||||
@@ -2944,7 +2945,7 @@ $(BIN)/test_self_rebuild: test/wcc/995_self_rebuild.c $(BIN)/ww_ww \
|
||||
$(BIN)/test_selfcheck: test/wcc/950_selfcheck.c $(BIN)/wwdump_ww | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/test_asserttyped_gap: test/wcc/901_asserttyped_gap.c $(BIN)/wwdump_ww | $(BIN)
|
||||
$(BIN)/test_asserttyped_gap: test/wcc/901_asserttyped_gap.c $(BIN)/ww $(BIN)/wwdump_ww | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/test_dyn_ww: test/wcc/996_dyn_ww.c $(BIN)/ww $(BIN)/w6l $(BIN)/w6l_ww \
|
||||
@@ -3589,9 +3590,10 @@ test-commit: all sizelint peellint $(TESTS)
|
||||
# w6c_ww and diffs the emitted .s. Catches a cs!=ww emission divergence
|
||||
# (rule 10) in seconds — the per-fold inner-loop check Rob's cadence
|
||||
# calls for. NOT a substitute for the full 990-997 byte-id gate, which
|
||||
# self-compiles main.combined.ww: ALWAYS run `make test` before landing
|
||||
# self-compiles the tools via `--sep`: ALWAYS run `make test` before landing
|
||||
# a cgen/ABI/compiler-lib fold. w6c consumes a flat unit (no import
|
||||
# resolution), so FIXTURE must be import-free or a pre-built .combined.ww.
|
||||
# resolution), so FIXTURE must be import-free or a pre-resolved sep unit
|
||||
# (<stem>.sepwork/__root.unit.ww).
|
||||
# make smoke # default: rt/malloc.ww
|
||||
# make smoke FIXTURE=rt/ensure.ww # any self-contained .ww
|
||||
FIXTURE ?= rt/malloc.ww
|
||||
|
||||
@@ -218,10 +218,9 @@ enumerate_dir_ww(const char *dirpath, char ***out_files)
|
||||
* but ww corpus settled on the un-underscored shape). */
|
||||
if (nl >= 7 && strcmp(nm + nl - 7, "test.ww") == 0)
|
||||
continue;
|
||||
/* skip "*.combined.ww" — driver-generated concat
|
||||
* artifacts (the previous build leaves them next to
|
||||
* the source). They look like .ww but parse-erroring
|
||||
* when re-included. */
|
||||
/* skip "*.combined.ww" — legacy amalgamator artifacts
|
||||
* (pre-#87): they look like .ww but parse-error when
|
||||
* re-included, and the sep driver no longer writes them. */
|
||||
if (nl >= 12 && strcmp(nm + nl - 12, ".combined.ww") == 0)
|
||||
continue;
|
||||
if (n + 1 > cap) {
|
||||
@@ -240,7 +239,7 @@ enumerate_dir_ww(const char *dirpath, char ***out_files)
|
||||
* ww build — separate-compilation driver (task #46/c3).
|
||||
* ====================================================================
|
||||
* This is the SOLE build path (E3-C1 flip, task #87): the legacy
|
||||
* single-file amalgamator (build_one/expand) is gone. Each imported
|
||||
* single-file amalgamator is gone. Each imported
|
||||
* package's `.wwi` interface is materialized and every package is
|
||||
* compiled on its own (`w6c -c`), then the `.o` set is flat-linked.
|
||||
*
|
||||
@@ -313,10 +312,10 @@ sep_fname(const struct sepgraph *g, int pi, const char *scratch,
|
||||
|
||||
/* unit_has_package — does `path` declare `package <leaf>;` ANYWHERE?
|
||||
* #16 ENFORCE-driver (rob A): distinguishes a genuinely-missing import
|
||||
* from one satisfied by an INLINE package in the same unit. Unlike
|
||||
* peek_package (stops at the FIRST package decl), this scans every line
|
||||
* — single-file multi-package fixtures carry several `package` decls. The
|
||||
* comment-skip line scan + name match mirror peek_package, uncapped. The
|
||||
* from one satisfied by an INLINE package in the same unit. Unlike a
|
||||
* first-package-decl scan, this checks every line — single-file
|
||||
* multi-package fixtures carry several `package` decls. The
|
||||
* comment-skip line scan + name match are uncapped. The
|
||||
* wwstage twin unithaspackage must stay byte-identical (rule 10). */
|
||||
static int
|
||||
unit_has_package(const char *path, const char *leaf)
|
||||
@@ -348,8 +347,9 @@ unit_has_package(const char *path, const char *leaf)
|
||||
/* Scan one source file for top-level `import IDENT;`, resolving each. A
|
||||
* DIRECTORY import is a package boundary: add it as a direct dep of pkg
|
||||
* `pi`. A FILE import is an intra-package split — fold its imports into
|
||||
* `pi` (its bytes join pi's body at emit time). Mirrors expand's scan
|
||||
* but collects package PATHS instead of concatenating bytes (§1.1). */
|
||||
* `pi` (its bytes join pi's body at emit time). Collects package PATHS
|
||||
* rather than concatenating bytes the way the legacy amalgamator did
|
||||
* (§1.1). */
|
||||
static int
|
||||
sep_scan_file(struct sepgraph *g, int pi, const char *file,
|
||||
const char *searchpath, struct ImportSet *filevisit)
|
||||
@@ -383,9 +383,9 @@ sep_scan_file(struct sepgraph *g, int pi, const char *file,
|
||||
/* #16 ENFORCE-driver: an unresolvable import is a hard error,
|
||||
* not a silent skip — EXCEPT when the package is defined INLINE
|
||||
* in the same unit (single-file multi-package; leaf = the last
|
||||
* dotted component). E3-C1: the combined path that used to own
|
||||
* the genuine-missing case is gone, so the sep producer enforces
|
||||
* it here (INV-2, by construction). Mirrors the deleted expand. */
|
||||
* dotted component). E3-C1 (#87): the legacy amalgamator that
|
||||
* used to own the genuine-missing case is gone, so the sep
|
||||
* producer enforces it here (INV-2, by construction). */
|
||||
if (!locate_import(searchpath, path_form, ipath, sizeof ipath,
|
||||
&is_dir)) {
|
||||
const char *dot = strrchr(name, '.');
|
||||
@@ -888,8 +888,7 @@ build_one_sep(const char *src, int entry_is_dir, const char *out,
|
||||
else if (access("lib", 0) == 0) srcdir = "lib";
|
||||
else srcdir = libdir;
|
||||
}
|
||||
/* search path: source-dir, then -I dirs, then srcdir (mirrors
|
||||
* build_one). */
|
||||
/* search path: source-dir, then -I dirs, then srcdir. */
|
||||
char srcd[1024];
|
||||
if (entry_is_dir) {
|
||||
snprintf(srcd, sizeof srcd, "%s", src);
|
||||
@@ -938,9 +937,8 @@ build_one_sep(const char *src, int entry_is_dir, const char *out,
|
||||
/* #79 (-T): lib/test is the synth main's `test.run` callee but @test
|
||||
* files never `import test;`. Inject it as a direct dep of the root so
|
||||
* sep_scan_pkg pulls test + its transitive deps; the producer adds -T
|
||||
* to the root and `test.run` links against test's `.a`. Mirrors the
|
||||
* combined path's auto-bundle (build_one is_test) and the sep_scan_file
|
||||
* dedup-guarded dep append. */
|
||||
* to the root and `test.run` links against test's `.a` — via the
|
||||
* sep_scan_file dedup-guarded dep append. */
|
||||
if (is_test) {
|
||||
char tpath[1024];
|
||||
int tdir = 0;
|
||||
@@ -1014,8 +1012,8 @@ build_one_sep(const char *src, int entry_is_dir, const char *out,
|
||||
/* wrap each DEP package's `.o` in its own deterministic `.a`
|
||||
* (5a). The ROOT stays a positional `.o` (force-loaded — it's
|
||||
* the build target, always fully linked), so `main` is defined
|
||||
* before any archive is processed, matching build_one's root
|
||||
* treatment. The link consumes `.o`/`.a`, never `.wwi`. */
|
||||
* before any archive is processed. The link consumes `.o`/`.a`,
|
||||
* never `.wwi`. */
|
||||
if (pi != root) {
|
||||
char apath[1024];
|
||||
sep_fname(g, pi, scratch, ".a", apath, sizeof apath);
|
||||
@@ -1114,7 +1112,7 @@ basename_no_ext(const char *path, char *out, size_t outsz)
|
||||
* . → cwd as a directory
|
||||
* foo (bare) → walk cwd:incs:WW_LIB; first hit is dir or file.
|
||||
* Sets *is_dir on hit. Dir resolution drives directory-as-module
|
||||
* enumeration in build_one. */
|
||||
* enumeration in build_one_sep. */
|
||||
static int
|
||||
resolve_module(const char *name, const char *incs, char *out, size_t outsz,
|
||||
int *is_dir)
|
||||
@@ -1317,8 +1315,8 @@ do_run(int argc, char **argv)
|
||||
}
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "/tmp/ww_run_%d", getpid());
|
||||
/* objstem = tmp → intermediates land at /tmp/ww_run_<pid>.{s,o,
|
||||
* combined.ww}, never next to the source (T3). */
|
||||
/* objstem = tmp → intermediates land under /tmp/ww_run_<pid>.sepwork/,
|
||||
* never next to the source (T3). */
|
||||
if (build_one_sep(resolved, is_dir, tmp, tmp, incs, libs, libdirs, 0) != 0)
|
||||
return 1;
|
||||
/* exec the built binary with any trailing argv as its argv. */
|
||||
@@ -1347,9 +1345,10 @@ do_test(int argc, char **argv)
|
||||
const char *src = NULL;
|
||||
char incs[2048] = {0};
|
||||
/* -c (compile-only, Go's `go test -c`) + -o <stem> build the test
|
||||
* binary (and its lib/test-inclusive combined, via build_one's
|
||||
* binary (and its lib/test-inclusive sep unit, via build_one_sep's
|
||||
* is_test auto-bundle + the T3 objstem redirect) WITHOUT running it —
|
||||
* the byte-id gates feed <stem>.combined.ww to raw w6c -T / w6c_ww -T.
|
||||
* the byte-id gates feed <stem>.sepwork/__root.unit.ww to raw
|
||||
* w6c -T / w6c_ww -T.
|
||||
* -T stays internal to w6c; the driver never sees it. -l/-L carry no
|
||||
* meaning for a test build, so they (and any unknown flag) are rejected
|
||||
* rather than silently swallowed — byte-identical wording to the
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -195,7 +195,7 @@ type strnode = struct {
|
||||
};
|
||||
|
||||
type expctx = struct {
|
||||
out: i32, // fd we're writing the combined source to
|
||||
out: i32, // fd we're writing the sep unit source to
|
||||
dirs: *u8, // ":"-separated search path (NUL-terminated)
|
||||
visit: *strnode,
|
||||
};
|
||||
@@ -326,9 +326,9 @@ fn locateimport(dirs: *u8, name: *u8, namelen: u64,
|
||||
};
|
||||
|
||||
// Filter for dir enumeration: keep `*.ww` minus `*test.ww` and the
|
||||
// `*.combined.ww` driver-generated concat artifacts (the previous
|
||||
// build leaves them in the source tree; they parse-error when
|
||||
// re-included). Returns true to keep.
|
||||
// `*.combined.ww` legacy amalgamator artifacts (pre-#87): they
|
||||
// parse-error when re-included, and the sep driver no longer writes
|
||||
// them. Returns true to keep.
|
||||
fn dirfilekeep(name: *u8, nlen: u64) bool = {
|
||||
// nlen<=3 guard kept: a bare ".ww" (len 3) is rejected here but
|
||||
// would pass strings.hassuffix(".ww"); preserves cstage parity.
|
||||
@@ -372,7 +372,7 @@ fn enumeratedir(dirpath: *u8) (**u8, i32) = {
|
||||
if (fd < 0) { return nil: **u8, 0; };
|
||||
// #65: grow-dynamic (mirror cstage enumerate_dir_ww realloc-doubling,
|
||||
// cmd/ww/main.c:209). The old fixed 256-name cap silently dropped every
|
||||
// eligible file past it, diverging the combined.ww from cstage on a
|
||||
// eligible file past it, diverging the package unit from cstage on a
|
||||
// module dir with >256 sources.
|
||||
let cap: i32 = 8;
|
||||
let names: []*u8 = alloc([], cap: u64)!;
|
||||
@@ -542,11 +542,10 @@ fn appendlit(stem: *u8, suffix: str) *u8 = {
|
||||
return buf.ptr;
|
||||
};
|
||||
|
||||
// linker flags (-L<dir>, -l<name>) grouped as one struct so buildone's
|
||||
// linker flags (-L<dir>, -l<name>) grouped as one struct so buildonesep's
|
||||
// param list stays readable. (The earlier note here claimed a 6-argument
|
||||
// wwstage calling-convention cap; that is stale — emittuplerowrelocs in
|
||||
// cgen.ww takes 7 params and self-compiles green, and buildone itself now
|
||||
// takes 7.)
|
||||
// cgen.ww takes 7 params and self-compiles green.)
|
||||
type lflags = struct {
|
||||
libdirs: **u8,
|
||||
nlibdirs: i32,
|
||||
@@ -559,7 +558,7 @@ type lflags = struct {
|
||||
// Port of cmd/ww/main.c build_one_sep (task #46/c3). The `--sep` path
|
||||
// materializes each imported package's `.wwi` interface and compiles
|
||||
// every package on its own (`w6c -c`), then flat-links the `.o` set.
|
||||
// combined.ww stays the DEFAULT live path; --sep is additive.
|
||||
// Separate compilation is the SOLE build path (E3-C1 flip, task #87).
|
||||
//
|
||||
// Each w6c pass is BOTH consumer (reads dep `.wwi` as import scope) AND
|
||||
// producer (writes this package's `.wwi` via -I). Reverse-topo order
|
||||
@@ -638,7 +637,7 @@ fn sepfname(g: *sepgraph, pi: i32, scratch: *u8, suffix: str) *u8 = {
|
||||
// genuinely-missing import from one satisfied by an INLINE package in the
|
||||
// same single-file multi-package unit (`package aa; ... package main;
|
||||
// import aa;`). Scans EVERY line (comment-skip) — not just the first
|
||||
// package decl (peekpackage stops there). Decision byte-identical to
|
||||
// package decl. Decision byte-identical to
|
||||
// cstage so the skip/fatal choice + driver output match (rule 10).
|
||||
fn unithaspackage(buf: *u8, buflen: u64, leafp: *u8, leafn: u64) bool = {
|
||||
let p: u64 = 0u64;
|
||||
@@ -756,10 +755,10 @@ fn sepscanfile(g: *sepgraph, pi: i32, file: *u8, searchpath: *u8,
|
||||
// when the package is defined INLINE in the same unit
|
||||
// (single-file multi-package). leaf = last dotted
|
||||
// component; inline `package <leaf>` -> skip (the
|
||||
// checker binds it), else fatal. E3-C1: the combined
|
||||
// path that owned the genuine-missing case is gone, so
|
||||
// the sep producer enforces it here (INV-2). cstage
|
||||
// twin; fatal text identical.
|
||||
// checker binds it), else fatal. E3-C1 (#87): the
|
||||
// legacy amalgamator that owned the genuine-missing
|
||||
// case is gone, so the sep producer enforces it here
|
||||
// (INV-2). cstage twin; fatal text identical.
|
||||
let lstart: u64 = 0u64;
|
||||
let lk: u64 = 0u64;
|
||||
for (lk < idn) {
|
||||
@@ -1377,7 +1376,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8,
|
||||
cstrseal(dotdotlib.ptr, off);
|
||||
};
|
||||
|
||||
// Source directory (mirrors buildone).
|
||||
// Source directory.
|
||||
let srcd: []u8 = alloc([], (os.PATH_MAX: u64))!;
|
||||
srcd.len = os.PATH_MAX;
|
||||
if (entryisdir != 0) {
|
||||
@@ -1422,7 +1421,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8,
|
||||
cstrseal(searchpath.ptr, off);
|
||||
};
|
||||
|
||||
// Stem for the scratch dir (mirrors buildone).
|
||||
// Stem for the scratch dir.
|
||||
let stem: []u8 = alloc([], (os.PATH_MAX: u64))!;
|
||||
stem.len = os.PATH_MAX;
|
||||
if (entryisdir != 0) {
|
||||
@@ -1462,8 +1461,8 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8,
|
||||
// #79 (-T): lib/test is the synth main's `test.run` callee but @test
|
||||
// files never `import test;`. Inject it as a direct dep of the root so
|
||||
// sepscanpkg pulls test + its transitive deps; the producer adds -T to
|
||||
// the root and `test.run` links against test's `.a`. Mirrors the
|
||||
// combined path's auto-bundle (buildone istest) and sepscanfile dedup.
|
||||
// the root and `test.run` links against test's `.a` — via the
|
||||
// sepscanfile dedup-guarded dep append.
|
||||
if (istest != 0) {
|
||||
let td: i32 = 0;
|
||||
let tp: *u8 = locateimport(searchpath.ptr, "test".ptr, "test".len: u64, &td);
|
||||
@@ -1575,7 +1574,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8,
|
||||
// Wrap each DEP package's `.o` in its own deterministic `.a`
|
||||
// (5a). The ROOT stays a positional `.o` (force-loaded — it's
|
||||
// the build target), so `main` is defined before any archive is
|
||||
// processed (mirrors buildone's root treatment). The link
|
||||
// processed. The link
|
||||
// consumes `.o`/`.a`, never `.wwi`.
|
||||
if (pi != root) {
|
||||
let apath: *u8 = sepfname(g, pi, scratch, ".a");
|
||||
@@ -2069,7 +2068,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
lf.nlibdirs = nlibdirs;
|
||||
lf.libs = libs.ptr;
|
||||
lf.nlibs = nlibs;
|
||||
// objstem = tmp → intermediates at /tmp/ww_run_<pid>.{s,o,combined.ww},
|
||||
// objstem = tmp → intermediates under /tmp/ww_run_<pid>.sepwork/,
|
||||
// never next to the source (T3).
|
||||
if (buildonesep(selfdir, resolved, isdir, tmp.ptr, tmp.ptr, incs.ptr, &lf, 0i32) != 0) {
|
||||
os.remove(pathstr(tmp.ptr));
|
||||
@@ -2104,8 +2103,8 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
fn runsingletest(selfdir: *u8, src: *u8, incs: *u8, compileonly: i32, outstem: *u8, pattern: *u8) i32 = {
|
||||
let tmp: []u8 = alloc([], (os.PATH_MAX: u64))!;
|
||||
tmp.len = os.PATH_MAX;
|
||||
// -o redirects the binary + its combined (objstem, T3) to <stem>; the
|
||||
// default temp keeps the combined next to the source as before.
|
||||
// -o redirects the binary + its sepwork intermediates (objstem, T3) to
|
||||
// <stem>; the default temp keeps them next to the source as before.
|
||||
let outp: *u8 = nil;
|
||||
let objstem: *u8 = nil;
|
||||
if (outstem != nil) {
|
||||
@@ -2248,7 +2247,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cstrseal(incs.ptr, 0u64);
|
||||
|
||||
// -c (compile-only) + -o <stem>: build the test binary + its lib/test-
|
||||
// inclusive combined WITHOUT running it, for the byte-id gates. cstage
|
||||
// inclusive sep unit WITHOUT running it, for the byte-id gates. cstage
|
||||
// twin: cmd/ww/main.c do_test (error wording identical).
|
||||
let compileonly: i32 = 0;
|
||||
let outstem: *u8 = nil;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,13 +12,20 @@
|
||||
* without gating on the bail's exit so a regression names its class.
|
||||
*
|
||||
* This probe runs the wwstage checker (wwdump_ww -c) over the
|
||||
* gap-bearing combined.ww corpus, counts the per-file asserttyped
|
||||
* diagnostics on stderr, and pins each count against the manifest
|
||||
* below. A fresh nil-gap (count up) or a regressed fixed class (count
|
||||
* up from 0) fails loud; a fold that closes a class drives its count
|
||||
* down, which fails until the manifest is edited to match. Every class
|
||||
* has reached all-zero, so the manifest is now the all-closed floor
|
||||
* that holds the armed bail green.
|
||||
* gap-bearing corpus, counts the per-file asserttyped diagnostics on
|
||||
* stderr, and pins each count against the manifest below. A fresh
|
||||
* nil-gap (count up) or a regressed fixed class (count up from 0) fails
|
||||
* loud; a fold that closes a class drives its count down, which fails
|
||||
* until the manifest is edited to match. Every class has reached
|
||||
* all-zero, so the manifest is now the all-closed floor that holds the
|
||||
* armed bail green.
|
||||
*
|
||||
* #90 sep-feed: the E3 flip retired the combined.ww amalgamator, so the
|
||||
* library/selfhost gap fixtures (A-D) feed their RESOLVED sep unit (see
|
||||
* resolveunit — `ww build --sep` composes <stem>.sepwork/__root.unit.ww
|
||||
* from the dep `.wwi` stubs + the root body) rather than a pre-built
|
||||
* <stem>.combined.ww. The single-file, import-free test fixtures (E-G)
|
||||
* carry no imports and stay raw-fed.
|
||||
*
|
||||
* Gap classes (counts verified empirically at this revision):
|
||||
* A module-qual N_DOT call result checked_test 0 (closed)
|
||||
@@ -39,6 +46,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
@@ -82,6 +90,52 @@ slurp(const char *path, char **outbuf, size_t *outlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* resolveunit — compose <fixture>'s RESOLVED translation unit the way the
|
||||
* sep driver does. Mirrors 990_selfhost's resolveunit: copy the fixture's
|
||||
* whole package directory into a private /tmp dir (so a white-box `_test`
|
||||
* file's sibling package sources resolve, and the sepwork lands off the repo
|
||||
* tree), `ww build --sep <base>`, then read <stem>.sepwork/__root.unit.ww —
|
||||
* the single self-contained unit w6c/wwdump consume for the root. Feeding the
|
||||
* raw module file instead would leave its import refs (os/fmt/strconv …)
|
||||
* unresolved, a partial unit the asserttyped invariant must never see. The
|
||||
* link step fails for an import-only module (no main), but the unit is
|
||||
* written before the link, so we detect the artifact rather than gating on
|
||||
* the build exit. Writes the owning tmpdir into `td` (caller rm -rf's it) and
|
||||
* the unit path into `out`. Returns 0 on success, -1 otherwise. */
|
||||
static int
|
||||
resolveunit(const char *bin, const char *cwd, const char *fixture,
|
||||
int idx, char *td, size_t tdsz, char *out, size_t outsz)
|
||||
{
|
||||
char cmd[2048];
|
||||
snprintf(td, tdsz, "/tmp/atgap_ru_%d_%d", getpid(), idx);
|
||||
snprintf(cmd, sizeof cmd, "rm -rf %s", td);
|
||||
runwait(cmd);
|
||||
mkdir(td, 0755);
|
||||
const char *slash = strrchr(fixture, '/');
|
||||
const char *base = slash ? slash + 1 : fixture;
|
||||
char dir[1024];
|
||||
if (slash) {
|
||||
size_t dl = (size_t)(slash - fixture);
|
||||
if (dl >= sizeof dir) return -1;
|
||||
memcpy(dir, fixture, dl);
|
||||
dir[dl] = '\0';
|
||||
} else {
|
||||
dir[0] = '.'; dir[1] = '\0';
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "cp %s/%s/*.ww %s/ 2>/dev/null", cwd, dir, td);
|
||||
runwait(cmd);
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && timeout 180 %s/ww build --sep %s >/dev/null 2>&1",
|
||||
td, bin, base);
|
||||
runwait(cmd);
|
||||
char stem[1024];
|
||||
snprintf(stem, sizeof stem, "%s/%s", td, base);
|
||||
char *dot = strrchr(stem, '.');
|
||||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||||
snprintf(out, outsz, "%s.sepwork/__root.unit.ww", stem);
|
||||
return access(out, 0) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Count line-leading "asserttyped:" diagnostics; each warn is one such
|
||||
* line and no other wwdump output carries the prefix. */
|
||||
static int
|
||||
@@ -109,30 +163,47 @@ main(void)
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||||
|
||||
struct { const char *rel; const char *cls; int want; } manifest[] = {
|
||||
{ "lib/math/checked/checked_test.combined.ww",
|
||||
"A module-qual N_DOT call result", 0 },
|
||||
{ "selfhost/test/smoke.combined.ww",
|
||||
"B fn-ptr struct-field call", 0 },
|
||||
{ "lib/encoding/utf8/utf8.combined.ww",
|
||||
"C abort intrinsic callee", 0 },
|
||||
{ "lib/fnmatch/fnmatchtest.combined.ww",
|
||||
"D module-leaf == type/fn name", 0 },
|
||||
{ "lib/math/random/random_test.combined.ww",
|
||||
"D module-leaf == type/fn name", 0 },
|
||||
/* sep=1 fixtures feed their resolved sep unit (resolveunit); sep=0
|
||||
* fixtures are import-free single files fed raw. */
|
||||
struct { const char *rel; const char *cls; int want; int sep; } manifest[] = {
|
||||
{ "lib/math/checked/checked_test.ww",
|
||||
"A module-qual N_DOT call result", 0, 1 },
|
||||
{ "selfhost/test/smoke.ww",
|
||||
"B fn-ptr struct-field call", 0, 1 },
|
||||
{ "lib/encoding/utf8/utf8.ww",
|
||||
"C abort intrinsic callee", 0, 1 },
|
||||
{ "lib/fnmatch/fnmatchtest.ww",
|
||||
"D module-leaf == type/fn name", 0, 1 },
|
||||
{ "lib/math/random/random_test.ww",
|
||||
"D module-leaf == type/fn name", 0, 1 },
|
||||
{ "test/wcc/901_enum_corpus.ww",
|
||||
"E computed enum-member value-expr", 0 },
|
||||
"E computed enum-member value-expr", 0, 0 },
|
||||
{ "test/wcc/901_forrange_tuple.ww",
|
||||
"F for-range tuple-destructure bind", 0 },
|
||||
"F for-range tuple-destructure bind", 0, 0 },
|
||||
{ "test/wcc/901_massign_blank.ww",
|
||||
"G tuple multi-assign discard `_`", 0 },
|
||||
{ NULL, NULL, 0 },
|
||||
"G tuple multi-assign discard `_`", 0, 0 },
|
||||
{ NULL, NULL, 0, 0 },
|
||||
};
|
||||
|
||||
int fail = 0, n = 0;
|
||||
for (int i = 0; manifest[i].rel; i++) {
|
||||
char src[2048], errf[64], cmd[4096];
|
||||
snprintf(src, sizeof src, "%s/%s", cwd, manifest[i].rel);
|
||||
char td[64] = {0}, unit[1280];
|
||||
if (manifest[i].sep) {
|
||||
if (resolveunit(bin, cwd, manifest[i].rel, i, td,
|
||||
sizeof td, unit, sizeof unit) != 0) {
|
||||
fprintf(stderr, "asserttyped_gap FAIL: %s [%s] "
|
||||
"no resolved sep unit\n",
|
||||
manifest[i].rel, manifest[i].cls);
|
||||
if (td[0]) { snprintf(cmd, sizeof cmd,
|
||||
"rm -rf %s", td); runwait(cmd); }
|
||||
fail++; n++;
|
||||
continue;
|
||||
}
|
||||
snprintf(src, sizeof src, "%s", unit);
|
||||
} else {
|
||||
snprintf(src, sizeof src, "%s/%s", cwd, manifest[i].rel);
|
||||
}
|
||||
snprintf(errf, sizeof errf, "/tmp/atgap_%d_%d.err", getpid(), i);
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"timeout 180 %s/wwdump_ww -c %s >/dev/null 2>%s",
|
||||
@@ -152,6 +223,8 @@ main(void)
|
||||
fail++;
|
||||
}
|
||||
unlink(errf);
|
||||
if (td[0]) { snprintf(cmd, sizeof cmd, "rm -rf %s", td);
|
||||
runwait(cmd); }
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
|
||||
@@ -113,7 +113,6 @@ probe_smoke(const char *bin)
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "%s/smoke.s", tmpdir); unlink(tmp);
|
||||
snprintf(tmp, sizeof tmp, "%s/smoke.o", tmpdir); unlink(tmp);
|
||||
snprintf(tmp, sizeof tmp, "%s/smoke.combined.ww", tmpdir); unlink(tmp);
|
||||
rmdir(tmpdir);
|
||||
if (rc != 42) {
|
||||
fprintf(stderr, "smoke FAIL: exit=%d (want 42; the number "
|
||||
|
||||
Reference in New Issue
Block a user