toolchain: banner purge + WHY-only comment sweep (rule 8)
selfhost/, cmd/, internal/ join the tree-wide sweep: every section banner dies (91 selfhost + the cmd C-style dividers -> 0); narration and stale contracts deleted (pre-#22 bundler notes, retired single-PT_LOAD and no-archive claims, superseded ABI tables); every ref/harec/qbe cite, task cite, encoding/ELF contract, and rule-10 twin pointer kept; lost lifetime/rationale lines restored where the sweep over-cut (elf_globals ownership, kwtab linear-scan). Comment- only proven: all five wwstage tool binaries byte-identical across the sweep; test-commit, test-byteid (161+1399, 0 pinned-divergent), and test-bootstrap (fixed point + 991-995 byte-id) all exit 0. The read-through banked 66 latent-bug leads (checkpoint).
This commit is contained in:
@@ -1,11 +1,6 @@
|
||||
/*
|
||||
* ww — the user-facing driver. Plan 9 cc(1) / Hare hare(1) analogue.
|
||||
*
|
||||
* Pipeline:
|
||||
* ww build foo.ww → w6c foo.ww > foo.s ; w6a foo.s > foo.o ;
|
||||
* w6l -o foo foo.o <runtime.o>
|
||||
* ww run foo.ww → build then exec ./foo
|
||||
*
|
||||
* Tool paths default to siblings of $0 (so a fresh build runs out of
|
||||
* out/bin/), and can be overridden with WW_W6C / WW_W6A / WW_W6L.
|
||||
*/
|
||||
@@ -35,7 +30,7 @@ static const char *usage =
|
||||
" lib/... every package under lib, recursively (test only)\n"
|
||||
" . build the cwd's <basename>.ww\n";
|
||||
|
||||
static char *self_dir; /* directory containing this binary */
|
||||
static char *self_dir;
|
||||
|
||||
static const char *
|
||||
toolpath(const char *envvar, const char *name)
|
||||
@@ -125,8 +120,7 @@ exec_package_tests(int argc, char **argv, const char *target,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set of imported module paths, kept on the heap. Used to break
|
||||
* cycles in `use` resolution. Linear because typical imports are
|
||||
/* Breaks cycles in `use` resolution. Linear because typical imports are
|
||||
* a handful per build. */
|
||||
struct ImportSet {
|
||||
char **paths;
|
||||
@@ -151,8 +145,7 @@ import_add(struct ImportSet *s, const char *path)
|
||||
s->paths[s->n++] = strdup(path);
|
||||
}
|
||||
|
||||
/* Translate dots in an `import` name to slashes for path lookup.
|
||||
* `encoding.utf8` → `encoding/utf8`. Mirrors Hare hare(1)'s
|
||||
/* `encoding.utf8` → `encoding/utf8`. Mirrors Hare hare(1)'s
|
||||
* use-path → fs-path mapping (ref/hare/hare/module/srcs.ha:78
|
||||
* builds the same shape via path::push per ident part). */
|
||||
static void
|
||||
@@ -164,12 +157,11 @@ import_path_form(const char *name, char *out, size_t outsz)
|
||||
out[i] = '\0';
|
||||
}
|
||||
|
||||
/* try <dir>/<path>/ as a directory (want_dir), else <dir>/<path>.ww as
|
||||
* a file. Sets *is_dir on hit. Symmetric with wwstage locatein for
|
||||
* byte-id driver output (rule 10). The legacy <dir>/<name>/<name>.ww
|
||||
* form was dropped in task #22 — directory-as-module enumeration
|
||||
* replaces it, mirroring ref/hare/hare/module/srcs.ha (Hare has no
|
||||
* fallback matching `foo/foo.ha`; a module IS the directory). */
|
||||
/* Symmetric with wwstage locatein for byte-id driver output (rule 10).
|
||||
* The legacy <dir>/<name>/<name>.ww form was dropped in task #22 —
|
||||
* directory-as-module enumeration replaces it, mirroring
|
||||
* ref/hare/hare/module/srcs.ha (Hare has no fallback matching
|
||||
* `foo/foo.ha`; a module IS the directory). */
|
||||
static int
|
||||
locate_import_in(const char *dir, const char *path_form, char *out,
|
||||
size_t outsz, int *is_dir, int want_dir)
|
||||
@@ -191,10 +183,7 @@ locate_import_in(const char *dir, const char *path_form, char *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Walk a colon-separated dirlist trying to resolve `path_form`. Returns
|
||||
* 1 on the first hit and writes the concrete path + dir/file marker.
|
||||
*
|
||||
* #98: "a module IS the directory" — a directory-package on ANY entry
|
||||
/* #98: "a module IS the directory" — a directory-package on ANY entry
|
||||
* wins over a same-named sibling FILE on an EARLIER entry. The driver
|
||||
* builds the searchpath srcd-first; a co-located `lib/<mod>/<x>_test.ww`
|
||||
* entry makes srcd = lib/<mod>, so a self-named `import <mod>` would
|
||||
@@ -231,10 +220,10 @@ locate_import(const char *dirs, const char *path_form, char *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* memcmp-based string compare for qsort. Byte-wise total order is
|
||||
* locale-independent; rule-10 byte-id requires the two stages sort
|
||||
* the same way. (strcmp would work today but Hare-fidelity points
|
||||
* at memcmp via ref/hare/sort/cmp/cmp.ha:9.) */
|
||||
/* Byte-wise total order is locale-independent; rule-10 byte-id requires
|
||||
* the two stages sort the same way. strcmp diverges from Hare's memcmp
|
||||
* (ref/hare/sort/cmp/cmp.ha:9); the order is identical for NUL-free
|
||||
* filenames. */
|
||||
static int
|
||||
strs_cmp(const void *a, const void *b)
|
||||
{
|
||||
@@ -266,11 +255,9 @@ file_has_line_test(const char *path)
|
||||
return found;
|
||||
}
|
||||
|
||||
/* enumerate_dir_ww — collect production *.ww paths in `dirpath`, excluding
|
||||
* *_test.ww test sources, then sort byte-wise. A line-leading @test in
|
||||
* any other source is diagnosed here and returns -2. This is the sole
|
||||
* directory-membership discovery path; the owning seppkg retains the
|
||||
* returned list. */
|
||||
/* A line-leading @test in a production source is diagnosed here and
|
||||
* returns -2. This is the sole directory-membership discovery path; the
|
||||
* owning seppkg retains the returned list. */
|
||||
static int
|
||||
enumerate_dir_ww(const char *dirpath, char ***out_files)
|
||||
{
|
||||
@@ -310,9 +297,8 @@ enumerate_dir_ww(const char *dirpath, char ***out_files)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
* ww build — separate-compilation driver (task #46/c3).
|
||||
* ====================================================================
|
||||
/* ww build — separate-compilation driver (task #46/c3).
|
||||
*
|
||||
* This is the SOLE build path (E3-C1 flip, task #87): the legacy
|
||||
* single-file amalgamator is gone. Each imported
|
||||
* package's `.wwi` interface is materialized and every package is
|
||||
@@ -357,7 +343,6 @@ struct sepgraph {
|
||||
int n;
|
||||
};
|
||||
|
||||
/* Find a package by dotted path, or add it. Returns its index, -1 full. */
|
||||
static int
|
||||
sep_find_or_add(struct sepgraph *g, const char *path, const char *entry,
|
||||
int is_dir)
|
||||
@@ -395,8 +380,7 @@ sep_graph_free(struct sepgraph *g)
|
||||
free(g);
|
||||
}
|
||||
|
||||
/* Sanitize a package's dotted path into a scratch-file basename. Dots
|
||||
* stay (legal in filenames); the root's empty path becomes "__root". */
|
||||
/* Dots stay (legal in filenames); the root's empty path becomes "__root". */
|
||||
static void
|
||||
sep_fname(const struct sepgraph *g, int pi, const char *scratch,
|
||||
const char *suffix, char *out, size_t outsz)
|
||||
@@ -451,9 +435,8 @@ sep_ident_continue(int c)
|
||||
return sep_ident_start(c) || (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
/* Skip the whitespace and comments accepted before and within the leading
|
||||
* package clause. This is deliberately only the loader's small header
|
||||
* grammar, not a second compiler lexer. */
|
||||
/* Deliberately only the loader's small header grammar for the leading
|
||||
* package clause, not a second compiler lexer. */
|
||||
static int
|
||||
sep_skip_space(const char *src, size_t n, size_t *off)
|
||||
{
|
||||
@@ -481,7 +464,6 @@ sep_skip_space(const char *src, size_t n, size_t *off)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse exactly the leading loader grammar `package ident;`. */
|
||||
static int
|
||||
sep_package_clause(const char *src, size_t n, char *name, size_t namesz)
|
||||
{
|
||||
@@ -509,9 +491,7 @@ sep_package_clause(const char *src, size_t n, char *name, size_t namesz)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scan one source file's already-selected bytes for its leading package
|
||||
* clause (when it is an owned directory source) and top-level imports. A
|
||||
* DIRECTORY import is a package boundary: add it as a direct dep of pkg
|
||||
/* 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). Collects package PATHS
|
||||
* rather than concatenating bytes the way the legacy amalgamator did
|
||||
@@ -715,7 +695,6 @@ sep_topo_visit(struct sepgraph *g, int pi, int *order, int *no,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Mark pi's transitive deps (excluding pi) in inset[]. */
|
||||
static void
|
||||
sep_mark_deps(struct sepgraph *g, int pi, char *inset)
|
||||
{
|
||||
@@ -881,9 +860,9 @@ archive_o(const char *objpath, const char *apath)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- -w workdir freshness ---------------------------------------------
|
||||
* A `-w DIR` workdir is a caller-owned persistent package-artifact tree
|
||||
* that replaces the fresh `.sepwork` scratch. Staleness is pure content
|
||||
/* -w workdir freshness: a `-w DIR` workdir is a caller-owned persistent
|
||||
* package-artifact tree that replaces the fresh `.sepwork` scratch.
|
||||
* Staleness is pure content
|
||||
* identity, never mtime: a package is reused only when its freshly
|
||||
* composed unit byte-equals the committed unit AND the tool copies
|
||||
* recorded in the dir byte-equal the live tools — every decision is
|
||||
@@ -997,7 +976,6 @@ build_one_sep_impl(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. */
|
||||
char srcd[1024];
|
||||
if (entry_is_dir) {
|
||||
snprintf(srcd, sizeof srcd, "%s", src);
|
||||
@@ -1110,7 +1088,6 @@ build_one_sep_impl(const char *src, int entry_is_dir, const char *out,
|
||||
}
|
||||
free(stack);
|
||||
|
||||
/* producer loop — dep-first, one `w6c -c -I` pass per package. */
|
||||
for (int oi = 0; oi < norder; oi++) {
|
||||
int pi = order[oi];
|
||||
char unitf[1024], wwi[1024], asmf[1024], obj[1024], apath[1024];
|
||||
@@ -1250,7 +1227,6 @@ build_one_sep_impl(const char *src, int entry_is_dir, const char *out,
|
||||
char objs[8192] = {0};
|
||||
for (int oi = norder - 1; oi >= 0; oi--) {
|
||||
char path[1024];
|
||||
/* root: positional `.o` (force-load); deps: `.a` (selective). */
|
||||
sep_fname(g, order[oi], scratch,
|
||||
order[oi] == root ? ".o" : ".a", path, sizeof path);
|
||||
size_t n = strlen(objs);
|
||||
@@ -1345,7 +1321,6 @@ search_path(const char *extra, char *buf, size_t bufsz)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* basename_no_ext: last path segment with any trailing ".ww" stripped. */
|
||||
static void
|
||||
basename_no_ext(const char *path, char *out, size_t outsz)
|
||||
{
|
||||
@@ -1356,13 +1331,6 @@ basename_no_ext(const char *path, char *out, size_t outsz)
|
||||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||||
}
|
||||
|
||||
/* resolve_module: turn a name into a concrete entry path.
|
||||
* foo.ww → use as-is if it exists
|
||||
* <existing dir> → returns the dir path (caller dir-enumerates)
|
||||
* . → 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_sep. */
|
||||
static int
|
||||
resolve_module(const char *name, const char *incs, char *out, size_t outsz,
|
||||
int *is_dir)
|
||||
@@ -1387,12 +1355,11 @@ resolve_module(const char *name, const char *incs, char *out, size_t outsz,
|
||||
return locate_import(sp, path_form, out, outsz, is_dir);
|
||||
}
|
||||
|
||||
/* Parse the standard -I/-L/-l/-o flags into incs/libdirs/libs/outpath. The
|
||||
* first non-flag positional becomes *src_out. Returns the index past the last
|
||||
* arg consumed for positionals (so callers can pick up trailing args), or -1
|
||||
* if a flag is missing its argument (diagnostic already emitted). `cmd` names
|
||||
* the subcommand for the diagnostic, byte-identical to the wwstage twin's
|
||||
* per-subcommand wording (selfhost/cmd/ww/main.ww dobuild/dorun). */
|
||||
/* Returns the index past the last arg consumed for positionals (so callers
|
||||
* can pick up trailing args), or -1 if a flag is missing its argument
|
||||
* (diagnostic already emitted). `cmd` names the subcommand for the
|
||||
* diagnostic, byte-identical to the wwstage twin's per-subcommand wording
|
||||
* (selfhost/cmd/ww/main.ww dobuild/dorun). */
|
||||
static int
|
||||
parse_build_flags(const char *cmd, int argc, char **argv,
|
||||
char *incs, size_t incsz,
|
||||
@@ -1504,7 +1471,7 @@ do_build(int argc, char **argv)
|
||||
outflag, sizeof outflag, workdir, sizeof workdir,
|
||||
&src, &emit_asm) < 0)
|
||||
return 2;
|
||||
if (src == NULL) src = "."; /* default: build cwd */
|
||||
if (src == NULL) src = ".";
|
||||
char resolved[1024];
|
||||
int is_dir = 0;
|
||||
if (!resolve_module(src, incs, resolved, sizeof resolved, &is_dir)) {
|
||||
@@ -1568,7 +1535,6 @@ do_run(int argc, char **argv)
|
||||
fputs("ww: cannot remove temporary directory\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
/* exec the built binary with any trailing argv as its argv. */
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("ww: fork");
|
||||
@@ -1823,7 +1789,6 @@ do_test(int argc, char **argv)
|
||||
"ww test: package options need a directory\n");
|
||||
return 2;
|
||||
}
|
||||
/* single .ww file — build, then run unless -c (compile-only). */
|
||||
char tmpdir[1024] = {0}, tmp[1024];
|
||||
const char *outp;
|
||||
int owntmp = !outstem[0] && !workdir[0];
|
||||
|
||||
Reference in New Issue
Block a user