Commit Graph

16 Commits

Author SHA1 Message Date
e1141330f2 test: retire 13 byteid carriers into the corpus blanket
Ten of the thirteen were already fully twinned — their runtime rows
migrated in earlier waves (r56_def_*, r79_*, r78_*, r926_*,
r989_m1union_*) and the carriers survived only for a cstage-vs-wwstage
byte-compare the blanket test-data-byteid comparator owns once the
source is a corpus fixture. The other three needed their remaining
inline sources added first: r756_* (4, alias-chain unwrap),
r844_bid_src (size(u64) untyped-int compare), r989_structframe_* (3,
struct-local frame layout). Every new fixture was verified both-stage:
compile exit 0 twice, .s byte-identical, runtime exit as pinned.

The five ww_ww-driver-leg carriers among them (785/786/789/790/
m1union) follow the 815/940/951 precedent: content identity owned by
their corpus twins, driver-leg identity owned by 989_lib_byteid's
sweep. Byte/artifact partition 24 -> 11; carriers 147 -> 134; corpus
pin 1495/2990; the stale 915 sweep figure in the docs corrected to
the true 1,157 non-error count.
2026-08-08 02:57:55 +09:00
67f39256f6 cgen: resolve chained-DOT fn-ptr field callees
fnptrcalleetfn's N_DOT arm required an N_IDENT base, so a.b.cb(...)
fell to the name registry with an empty module hint and emitted
CALL cb(SB) (undefined symbol; cstage calls the stamped ptr indirect).
dotbasestructinfo resolves the base chain through the struct registry
— each link a struct- or *struct-typed field — and the single-dot
path routes through the same resolver unchanged. Closes the last open
shape of the #59.8 name-keyed callee family. Fixture fnptrfield_chain;
corpus pin 1487/2974.
2026-08-08 02:48:05 +09:00
430c7e0546 check: compare variadic fn params at the declared element type
installparams normalizes a decl's `T...` param lhs to []T in place
(cstage instead sets the resolved tp->type and never mutates AST), so
typeeqast compared a decl-synthesized fn type's []i64 against a fn
TYPE expr's surface i64 and confidently rejected
`let f: fn(args: i64...) void = sum;` — cstage accepts and runs. The
normalization wrapper now carries an op marker and typeeqast peels
exactly it, so both sides compare at the declared element type without
admitting genuinely different element depths. Fixture fnptrlet_variadic;
corpus pin 1486/2972.
2026-08-08 02:47:08 +09:00
5abb1e6069 wwstage: port struct embedding; graduate #59.13
The last frontend-gap pin: wwstage had no Hare struct embedding
(struct { hash.hash, ... }), rejecting lib/crypto/sha256 at parse.

- parse.ww: the three member forms (named / anonymous struct / bare
  dotted-ident embed), consume-then-branch since this parser has no
  peek; embeds carry f.str == "" and the type in f.lhs.
- check.ww N_TSTRUCT flatten: promote the inner struct's flattened
  fields at base+src.offset (check.c:961-990); the embed is one
  nested-struct unit in the slot ladder; the resolved inner AST is
  planted on the TFIELD rhs for cgen.
- check.ww walkers: astoffset / exprtype N_DOT / #251 struct-lit
  field lookups descend embeds through shared helpers; the collision
  and non-struct-embed rejects live in validatestructfields (the
  once-per-decl diagnostic site).
- cgenutil.ww registerstruct: regfieldrun walks the AST against the
  flattened tfield cursor, descending embeds via the planted inner
  AST so promoted fieldinfo entries keep the inner field's own name
  and type node.
- wwi printers unchanged (both stages already emit nameless fields).

sha256_test compiles byte-identically end to end and its 6 tests
pass; 989_lib_byteid is now 44 id / 0 divergent / 0 wwreject.
Fixtures r5913_* (promoted rw, offset shift, anonymous embed,
two-level embed + promoted fn-ptr callee, three rejects); corpus pin
1485/2970.
2026-08-08 02:37:50 +09:00
6553d60e91 cgen: peel *fn field types for local struct-field callees
fnptrcalleetfn's N_DOT arm accepted only a bare N_TFN field tnode, so
a call through a field declared `cb: *fn(...)` missed, fell through to
the name registry, and emitted CALL cb(SB) — an undefined symbol
(loud at link; cstage calls the stamped ptr-to-fn indirectly). Same
TPTR peel the N_IDENT arm already had. Fixture fnptrfield_call covers
the by-value and via-pointer shapes; corpus pin 1478/2956.
2026-08-08 02:28:33 +09:00
f6628b985e test: migrate 24 residual carriers into the fixture corpus
Audit-driven migrate-and-retire wave (one read-only auditor per
carrier batch, verdicts row-checked through the full corpus gate):
every retired carrier's assertions are now owned by declarative
fixtures or an existing owner. 238 new fixtures land (corpus 1,239 ->
1,477; cells 2,954), covering enum/str/slice/tagged array elements,
inferred-length arrays, global slice/str zero-init and literals,
global array/pointer field reads and stores, struct-literal slice
fields, struct returns, float arithmetic, size/int limits, sort and
log-vstream behavior, place-addressed stores, and append places.
Rejection rows STRENGTHEN the old nonzero-exit checks to required
diagnostic fragments; all byte-id claims fold into the blanket
test-data-byteid sweep (now 1,142 compared, 0 pinned-divergent).
Four carriers were fully redundant with existing fixtures/lang tests
(749, 722, 765, and 771's byteid rows) and retire without new rows.
Native carriers 171 -> 147 (residual 135 -> 111).
2026-08-08 01:29:15 +09:00
3f7452814b cgen: resolve local fn-ptr callees for variadic arg prep
The wwstage variadic call classification was name-keyed: a fn-ptr
FIELD call whose local base shadowed the current module name
(lib/log's log.println(log, args...)) picked the module fn's
signature — nfixed off by one, the fixed arg boxed into the gather,
the spread emitted as zeros — and a no-collision fn-ptr callee missed
the registry entirely, leaking the raw N_SPREAD as a single $0 word
(SIGSEGV / exit 255 in 8 of 11 logtest tests on the wwstage leg).
fnptrcalleetfn resolves a local fn-ptr callee (bare local or struct
field) to its N_TFN once, shared by the CALL-target choice,
callee_variadic_param (with the []T wrap registry params get from
installparams), calleecvariadic, and the widening param lookup, so
target and arg prep can never disagree. Graduates the #59.8 logtest
pin — DATABYTEID_DIVERGED-era M_DIVERGE count is now zero.
2026-08-08 01:07:23 +09:00
c18005d833 check: stamp SK_TYPE value idents with the per-decl NAMED
A TYPE name used as a VALUE (an error-singleton `return too_long;`)
stamped the flattened BODY type, so structurally identical !void
singletons in one union were indistinguishable and flatvariantidxt
loud-rejected the ambiguity — the real cause of the lib/path wwstage
reject (the pinned #120/#29 global-slice-const blame was stale; that
family had drained). The N_IDENT arm resolves through a synthesized
TNAME (the #66 N_STRUCTLIT precedent); the module-qualified N_DOT twin
reads the sym's cached NAMED. Graduates the path M_WWREJECT pin (#142).
2026-08-08 01:00:03 +09:00
125f626697 check: type the N_BIN operand of as in the wwstage
An enum OR-fold under `as` ((m.A|m.B) as u32) was never typed:
scruttype resolves IDENT/DOT only, and the post-order restamp then
re-derived the folded member literals as untyped_int. The unstamped
operand missed cgtypeassert's #27b enum-reinterpret gate and lowered
as a phantom tagged assert — unconditional exit 1 at runtime on the
wwstage leg. checkisas now types an N_BIN lhs and the N_BIN restamp
preserves an existing enum stamp. Graduates the #59.9 stattest pin.
2026-08-08 00:59:02 +09:00
c421c2b20a cgen: key the str/slice arg recognizers off the checker stamp
The wwstage nodeisstr/nodeisslice recognizers were name-keyed for
every non-local shape: an indirect fn-pointer callee ((*f)() — the
errnotest #59.5 divergence, streq receiving a shifted register file)
and module-global let/const idents (path.sepstr — union-widen pushes
zero-filled len/cap) both fell to false while cstage keys off the
checker stamp unconditionally. Both recognizers now fall back to the
stamped n.type_; push and pop sites share them, so the drain stays
balanced by construction. Graduates the #59.5 errnotest pin.
2026-08-08 00:58:04 +09:00
66251cc52b cgen: default the hi bound of a slice/str-field slice, both stages
x.slicefield[:] / x.strfield[2:] emitted MOVQ $0 for the omitted hi
bound on BOTH stages (N_IDENT-gated dispatch; symmetric, so byte
identity never caught it) in all four sites: cgexpr N_SLICE + pushargs
(cstage), cgslice + pushargsrev (wwstage). The new arm re-evaluates
the pure field read for its {ptr,len,cap} header and takes .len,
covering local, viaptr, dot-chain, (*p), arr[i], and global inners.
Call inners still loud-reject upstream. Sibling of the #252/#257
array-field arms.
2026-08-08 00:29:51 +09:00
cc22abfc04 cgen: load the full header for a wwstage global-dot slice field
let x: []T = g.buf on a module-global struct dispatched only str
fields to the 3-word header load; a []T field fell to the scalar
tail (ptr word only), so len/cap read stale registers and the shape
was byteid-divergent against cstage's TY_STR||TY_SLICE arm (#263).
2026-08-08 00:23:55 +09:00
8a9be47f65 test/wcc/data: pin the drained divergences at runtime
The four graduated pin families byte-compared under test-data-byteid
but their original fixtures masked the miscompiles at runtime (lone
frame slot, dead code path, pointer accident). Add the discriminating
programs as run fixtures: adjacent-element clobber for the 2-byte
deref store, second-variant match dispatch for fn-type dedup, payload
integrity across the tagged widen of a padded struct, and base64
clear() actually zeroing its buffers. Corpus pins move to 1,229
fixtures / 137 run / 766 run-exit / 2,458 cells with the new identity
hash; the data-byteid floor moves to 915.
2026-08-07 23:55:01 +09:00
83c8a4f34f test/wcc: retire 990_selfhost; its live assertions move to their owners
Every probe's assertion is owned by a current gate: the compile and
link probes by make all and the bootstrap fixed point; build/run and
cs/ww byte identity by the fixture corpus, test-data-byteid, and
989_lib_byteid; wwstage driver and toolchain parity by 993/995;
checker-diagnostic parity by the corpus' both-stage //ww:error rows.
The wwdump -t/-a dump-parity probes gated the frontend port's
convergence, which the compiler-output identity gates now own end to
end; carrier ran green at retirement.

What was still uniquely alive migrates: smoke.ww becomes corpus
fixture selfhost_smoke (upgraded from a cstage-only build to both
frontends, byte-identical, exit 42 on both toolchains; corpus pins
move to 1,225/763/2,450 with the new identity hash in the same
commit), and sym_link.ww's scope/sym behavior rows become in-language
lib/ww/syntax/symtest.ww under LIBRARY_TESTS. uses.ww (parser-stub-era
-a fixture) and the already-orphaned tagged_ptr_ret.ww/trypromote.ww
retire with the probe corpus. Bootstrap native gates drop to six;
frontend numeric-sync comments now cite the rule-6 mirror instead of
the retired diff probe.
2026-08-07 23:34:44 +09:00
aa0f77b891 wwfixture: declarative fixture runner
Discovers test/wcc/data, hard-pins corpus identity (1,224 fixtures,
314 error / 12 compile / 136 run / 762 run-exit, sha256 name hash),
schedules both frontend cells per fixture through os.exec with
per-cell capture dirs, and emits the strict wwfix TSV result stream.
integration.sh is the black-box owner of the CLI/protocol boundary.
2026-08-07 23:21:04 +09:00
7a2c21acfb wwtest: native package-test coordinator
Single-directory package-test planner: discovers *.ww, groups white-box
and external <pkg>_test sources, composes the combined test package,
builds it through the sibling ww driver, and runs it with the runtime's
-package/-list/-timeout-ms contract. test/package holds its E2E corpus
and the manual runtime fixture set.
2026-08-07 23:01:03 +09:00