Commit Graph

3 Commits

Author SHA1 Message Date
132ea4ee60 test: migrate Fam13 misc checker/coercion value tests to @test (#5-C6)
Final fold-2 chunk. The 12 Fam13 single-file value drivers move from
test/wcc/*_run.c into in-language @test row-tables under test/lang/:

- value rows -> test/lang/*_test.ww (12 files)
- reject rows -> runww //ww:error carriers (13, dual-stage non-vacuous)
- nullable abort rows -> runww //ww:run-exit 1 carriers (3)
- 953_globalslice_arg -> _runonly (cs!=ww checker divergence, #28)
- 788 value_not_type_neg + 953_arrlit_slice reject_assign kept as slim
  rc-only .c pins (divergent-diag dual-reject, mutation-gated); 788 #29

Coverage parity verified row-by-row vs each retired driver; advisor-
ratified carve taxonomy; two-round reviewed. Floor ratchet follows.
2026-06-24 22:59:32 +09:00
ce3a25a0b4 test: contain sepwork scratch per-driver tmpdir, fix /tmp+in-repo leak (#8)
The wcc test drivers ran `ww build <bare-/tmp src>` with no -o, so the
compiler's <stem>.sepwork scratch landed beside the source and was never
cleaned: unbounded /tmp growth (2195 stale dirs observed) that fills tmpfs
and fabricates phantom test failures + silent harness aborts, and for
in-repo fixture builds leaked .sepwork into the tracked tree.

Each leaking build now writes its source + output inside a per-invocation
tmpdir, passes -o <tmpdir>/<stem> so the .sepwork lands inside it, and
rm -rf's the tmpdir on every exit path -- including fopen-fail and the
expected-fail reject builds (scratch is mkdir'd before the build can fail).
`ww run` and explicit-`-o`/byte-id helpers are left as-is; the 990/993
byte-id comparison logic is byte-for-byte unchanged.

Two items filed separately (this commit holds the no-Makefile / no-main.c
rail):
- #13: a stale <src>.s byte-id readback (749) silently no-ops since
  separate-compile emits .s to <ostem>.sepwork/__root.s; documented inline.
- #14: build-system Makefile recipes build selfhost/cmd/*/main.ww with no
  -o and leak main.sepwork in-tree (bounded, gitignored; own commit).

One concern -- sepwork leak hygiene -- across 228 drivers; uniform
transform applied per-file and two-round reviewed. make test: all 402
passed, zero net-new /tmp scratch, zero test-driven in-repo .sepwork.
2026-06-22 23:29:39 +09:00
bf1037d8c4 wcc/check+w6c+w6c_ww: materialize array-literal slice-borrow base into per-fn scratch (fix #25 + #31)
A one-step `let xs: []T = [e0,e1,..]` had two faults. #31 (silent, cs!=ww):
the #258 array→slice borrow wrapped the un-addressable N_ARRLIT directly as
the N_SLICE base and cgen never spilled it to a stack slot, so .ptr dangled
(`let xs:[]i32=[10,20,30]; xs[1]` returned the un-stored header 1; []u8/[]str
segfaulted). #25 (over-strict): a slice target fell through to the exact-
element type_eq borrow gate, rejecting bare-int-width ([]u8=[1,2,3]) and str
elements the array-init path coerces.

Fix (re-stamp + per-borrow scratch; both stages byte-identical asm):
 - Checker re-stamps the slice arrlit as [count]T, reusing the array-init
   per-element coercion + range-check (#25): in-range accepts, out-of-range
   loud-rejects. cstage arrlit_init_fits gains a TY_SLICE arm; wwstage
   checkletassign mirrors it and stashes the synthesized [count]T tnode on
   arrlit.lhs (free for N_ARRLIT) so cgen can size the backing NODE-wise
   (elemsizeofc) and count from the tnode's .rhs intlit — the arrlit's own
   value tinfo carries the literal's untyped element (unsized), so node-first
   sizing is required (a cstage/wwstage representation divergence; cstage's
   Type IS sized and reads base->type).
 - cgen materialises the N_ARRLIT borrow base into a FRESH per-borrow
   @slicescr stack slot (distinct slot per borrow: a borrow's backing must
   outlive the lowering, so it can't share a cached @aggargscr/@tagscr-style
   slot — two live borrows would alias one backing; localalloc/local_alloc
   is always-fresh), filled by REUSING the array-init element fill extracted
   from the N_LET path (cstage cg_arrlit_fill_bp, wwstage cgarrlitfillbp —
   same store sequence the byte-id-green `let a:[N]T=[..]` uses, the
   frame-order + store-op guarantee), then LEAQ'd as the base.

Supported ONLY at a `let` init. In call-arg / return / assign position
there is no addressable backing, so both stages LOUD-REJECT ("bind it to a
`let` first") — aligning cstage DOWN to wwstage (which already refused the
untyped arrlit element) per rule-10; this closes #31's silent call-arg
segfault as a compile error. Full non-let support is deferred (#33).

Escape (rule-8 WHY): a `let xs:[]T=[..]; return xs;` returns a slice into a
freed frame slot = dangling, IDENTICAL to the pre-existing named-array
borrow and Hare-consistent (no escape analysis / GC / heap promotion).

Test 953_arrlit_slice_run: 8 accept rows (cstage runtime readback +
cs==ww byte-id, frame-size canary incl.) covering the #31 i32 pin, bare-int→u8
coercion, str readback, the multi-live soundness pin (xs[0]+ys[0]=5, not 8 —
proves fresh-per-borrow), and a mutate-through-borrow proof; 4 reject rows
(out-of-range element + the three non-let contexts, loud in both stages).
Tuple-element slices stay blocked by the pre-existing #30 array-init FATAL.
2026-06-04 01:44:39 +09:00