Commit Graph

63 Commits

Author SHA1 Message Date
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