Commit Graph

17 Commits

Author SHA1 Message Date
25da54936d ww: preserve compiler sink outputs 2026-08-14 19:10:36 +09:00
c6bec0914d ww: implement package initialization 2026-08-14 19:02:35 +09:00
792b6ecbe5 ww: add file-scoped import aliases 2026-08-14 10:56:34 +09:00
6efe9b70d4 ww: separate package identity from declared name 2026-08-14 03:07:58 +09:00
b84fb3ff25 ww: implement local vendor package semantics 2026-08-13 19:18:00 +09:00
c3df0afeb0 build: separate package identity from storage paths 2026-08-13 05:37:56 +09:00
4377634bb9 ww: preserve command package identities 2026-08-13 03:37:08 +09:00
fc4bde703e compiler: separate package exports from entry roots 2026-08-12 21:59:51 +09:00
edd3f4ee83 build: pass direct exports to package compilers 2026-08-12 18:42:22 +09:00
e59881cb30 compiler: support package test runtime aliases 2026-08-12 03:46:28 +09:00
db96422f74 compiler: load imports and enforce package exports 2026-08-11 22:25:59 +09:00
62b9d20383 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).
2026-08-08 23:14:03 +09:00
7b6f24adea w6c,ww: mangle an imported package's fn main under separate compilation (M4 E3, #99)
The bare-`main` carve-out (which keeps the link entry's main unmangled)
keyed on `leaf == "main" && imported == 0`. Under the combined path a
dependency's body folds in with imported==1, so only the root's main
stayed bare. Under separate compilation each package is its own unit and
a dependency's body carries a path-mangling module-reset but imported==0
(#57) — so an imported `fn main` matched the carve-out, emitted a bare
`TEXT main`, and collided with the root entry (`w6l: duplicate symbol
main`). The combined path was unaffected, so this only surfaced under sep.

Gate the carve-out with sep_isdep = (wwiout != NULL): the producer emits a
.wwi output only for dependency units, never for the root/link-entry unit
(root stripped, #69), symmetric on both stages. Only the root unit's main
now stays bare; an imported package's main mangles on its import path
(e.g. aa.bb.main). Both stages.

Gate: test/wcc/989_depmain_sep.c (table-driven, dotted + single-component
shapes, both stages; asserts the mangled dep main + a single bare root
main + cs==ww byte-id; combined path stays neutral).
2026-06-18 12:47:41 +09:00
13e5e35f81 wcc/ww: .wwi separate-compile consumer — w6c -c codegen filter (#22 M3)
New `w6c -c` (both stages): separate-compile / primary-only codegen.
Emit code+DATA ONLY for a package's own (imported==0) decls; treat every
`.wwi`-sourced (imported==1) dep decl as an external. Pure addition behind
the flag — combined.ww stays the LIVE path, `-c` is off on every existing
invocation, so the 990-997 byte-id gates + all prior tests are unperturbed.

The keystone (rob): a `.wwi` is body-less/init-less prototype source, and
cgen already skips body-less fns as externs, so dep fns/types/defs emit
NOTHING for free. The single genuinely-new guard is an imported value-
global (`export let`): its DATAW would DUPLICATE the dep's own definition
(link collision), so it is skipped. The `imported==0` gate is applied at
all top-level emit sites for uniformity (close-by-construction): the fn
loop, emit_lets/emitletdataw, emit_defs/emitdefconstants, and
let_pre_intern/letpreintern — that last one because an imported dep's body
initializer interns strlits while its rhs-stripped `.wwi` does not, which
would shift the _S_ sequence; gating it keeps the strlit table a pure
function of the package's own decls. EXACTLY symmetric with M2's producer
`imported==0` filter — same predicate both directions.

Driver `--sep` build_one_sep + per-package archives + multi-.a link +
cache + BROAD real-target dual-path soak are M3-tail (#46, rob ruling B):
M3-core ships the codegen spine + a self-contained gate that proves all
codegen correctness without a production driver.

Gate 989_m3sep_run: a synth leaf->mid->root fixture carrying all four
cross-boundary fact-classes (fn signature, struct LAYOUT, `def` const
VALUE, `export let` value-global). Per package, holding `-c` constant:
`w6c -c` of (deps-as-bodies) == (deps-as-.wwi) byte-for-byte (the .wwi
conveys exactly the dep facts P's codegen needs); cs==ww at the .s AND
final-exe level (rule 10); sep-path determinism; the value-global guard
(imported origin_tag never re-emits DATAW); and behavioral identity (the
linked program's exit code is the real cross-boundary computation). COLD:
.wwi materialized fresh every run (no warm cache).

combined.ww regen'd for wwdump + w6c (both embed cgen.ww); diff is exactly
the four guards + the flag wiring, nothing spurious.
2026-06-15 22:33:39 +09:00
e8d3d89fef wcc/ww: .wwi export-data producer + check_exported_type (#22 M2)
New `w6c -I <out.wwi>` flag (both stages) writes a re-parseable
ww-prototype rendering of a package's EXPORTED surface. M2 dead-code:
nothing consumes .wwi yet (combined.ww stays the live path); the flag is
off on every existing invocation, so the 990-997 byte-id gates and all
prior tests are unperturbed.

The unparse walks the AST type-expr subtree (N_T* nodes), not the
tinfo Type* (which collapses nominal pkg.Name identity). Deterministic
output: package line, byte-sorted imports, byte-sorted decls — a pure
function of the exported API. cmd/w6c/wwi.c + selfhost/cmd/wcc/wwi.ww
emit byte-identical .wwi (new cross-stage byte-id substrate, rule 10).

check_exported_type (drew) rides the producer entry, flag-gated: an
exported signature naming a non-exported nominal is loud-rejected before
any byte is written, identically on both stages. Ports harec
check.c:4092-4168, recursing the type-AST and gating on the resolved
SK_TYPE sym's decl export flag (Sym.exported is vestigial in both
stages; the predeclared synthetic `nomem` decl carries no source
position and is treated as a builtin leaf — cstage parity).

Two wwstage checker AST-mutations are normalized to cstage's pristine
view for byte-id: the N_TPARAM tuple-element wrapper (unwrapped) and the
variadic `T...`→`[]T` param desugar (peeled).

Gate 989_m2wwi_run: ascii/strings/getopt each produce a .wwi that
re-parses (wwdump -a) and is cs==ww byte-identical; a private-type-leak
fixture is rejected identically by both stages (non-vacuous check).
2026-06-15 20:58:08 +09:00
b795c320c9 wcc: -T test-mode collects @test fns + synthesizes entry, both stages (#15)
@test was parsed then dropped (no consumer); `ww test` needed a hand-written
main listing each test by hand, so adding a @test and forgetting the call
silently skipped it. -T makes the checker collect @test N_FNDECLs in source
order, loud-reject a user main, and append a synthetic
`export fn main() i32 { t0(); ...; return 0; }` at the install->body-check seam;
the existing cgfn emits it (cgen untouched) -> byte-identical by construction.
Mirrors harec's checker-side is_test placement.

Plan-9-lean reduction (user-sanctioned, reinstatable post-CSP): sequential,
abort/nonzero=fail; no setjmp isolation, no fnmatch filter, no file:line.

910/997 rewired from a regex scanner to driving `w6c -T` directly (thin trusted
drivers; the @test content stays ww), with a cross-stage byte-id assert on the
-T output. attest_userman/attest_badsig pin the user-main and bad-signature
rejects.
2026-06-10 02:01:20 +09:00
2c33228b7e ww: rename toolchain to w-prefix + hare-style build/run/test driver
Plan 9-style w-prefix on the per-arch tools, disambiguating from the
real Plan 9 6c/6a/6l in ref/plan9front/:

    cmd/wwc/      → cmd/wcc/        libwwc.a → libwcc.a
    cmd/6{c,a,l}  → cmd/w6{c,a,l}   binary names too
    test/wwc/     → test/wcc/       6 test files w/ w6 prefix
    selfhost/cmd  mirror in lockstep
    bootstrap/amd64/{w6c,w6a,w6l}   snapshot binaries (gitignored)
    WW_6{C,A,L}   → WW_W6{C,A,L}    env-var overrides

Plan 9 source-tree refs ("Plan 9 6c shape", ref/plan9front/, etc.)
preserved. Hare-style driver, both C and ww sides:

    ww test [path]   discover *_test.ww in a directory module, run
                     each; single-file mode for `ww test foo.ww`
    Module-by-name   `ww build foo` resolves to foo.ww or foo/foo.ww
                     via search path (cwd : -I dirs : $WW_LIB)
    Default-to-cwd   `ww build` / `ww test` build the cwd module
    Run pass-through `ww run path arg1 arg2` reaches the program

lib/os: getcwd (79) and getdents64 (217) syscalls power `.` resolution
and directory enumeration on the ww side.

Makefile: wwstage tool deps now include lib/os/os.ww (+ lib/strconv
for wwdump_ww) so lib/* edits force their rebuild instead of leaving
stale binaries — surfaced when test 995 first failed against a stale
w6c_ww built before the lib/os additions.

Test 993 byte-identical parity gate (C-side ww vs ww-side ww_ww on a
build corpus) stays green; all 19 tests pass.
2026-05-11 13:49:27 +09:00