lib: collapse the parallel vstream scaffold onto the single Hare io surface (#94 fold-eFinal)

The Option-C parallel _v vstream API was scaffolding to bring the io stack up alongside the old surface; carrying both permanently is a rule-9 divergence from ref/hare, which has exactly one io surface. Collapse onto that surface (stream = *vtable, ref/hare/io/stream.ha) and rename the _v symbols to their Hare names (io vstream->stream, fmt vfprint->fprint, bufio/memio/log surfaces, log.new). Deletes the 4 lib/*/vstream.ww scaffold files; regenerates w6c/wwdump combined.ww. cstage and wwstage stay byte-identical and combined_ww_fresh holds; all 220 tests pass.
This commit is contained in:
2026-05-30 03:24:23 +09:00
parent 80184a3acf
commit 7d39f6d623
31 changed files with 2371 additions and 4834 deletions

View File

@@ -1,25 +1,24 @@
/*
* 776_memio_vstream_run — project #94 fold-eFinal(PREP) sentinel. Pins
* the additive lib/memio/vstream.ww parallel API: a single unified
* 776_memio_vstream_run — project #94 fold-eFinal sentinel. Pins
* the single-surface lib/memio: a unified
* `stream` struct with `vt: io.vtable` as the first field for the
* intrusive cast, three constructors (fixed_vstream / dynamic_vstream /
* dynamicfrom_vstream) that return the `stream` BY VALUE (sret —
* intrusive cast, three constructors (fixed / dynamic /
* dynamicfrom) that return the `stream` BY VALUE (sret —
* field-by-field build then `return r;`, ref/hare/memio/stream.ha:46,
* 58,64), the unified read_v / fixedwrite_v / dynamicwrite_v /
* dynamicclose_v callbacks that recover the outer stream via a
* 58,64), the unified read / fixedwrite / dynamicwrite /
* dynamicclose callbacks that recover the outer stream via a
* vstream→*stream pointer cast, and the collapsed single accessors
* (string_v / buffer_v / reset_v / borrowedread_v) over the common
* header. Coexists with the pre-vtable memio.fixed/dynamic/dynamicfrom
* + `state` surface in memio.ww (fold-eFinal FLIP retires the latter
* and drops the `_vstream`/`_v` suffix wholesale).
* (string / buffer / reset / borrowedread) over the common
* header. The fold-eFinal FLIP collapsed the dual memio surface into
* this one Hare-shaped surface (bare names, no suffix).
*
* Each row imports memio + io, calls one or more constructors, drives
* the io.st_read/st_write/st_close dispatchers, and asserts an exit
* the io.read/io.write/io.close dispatchers, and asserts an exit
* constant. Both stages run; cs.s == ww.s byte-id on every row.
*
* row | what it pins
* --------------------------+--------------------------------------
* fixed_read_5 | fixed_vstream + io.st_read of 5 bytes
* fixed_read_5 | fixed + io.read of 5 bytes
* | over an 8-byte source. Asserts the
* | return is `size` and equal to 5, and
* | that out[0]/out[4] mirror the buffer.
@@ -27,14 +26,14 @@
* | stream field-by-field → return r (sret);
* | caller takes &st.vt; dispatcher recovers
* | via s: *stream).
* dynamic_write_grow | dynamic_vstream + io.st_write of 3
* dynamic_write_grow | dynamic + io.write of 3
* | bytes. Asserts the write reports 3
* | and that the dynamicgrow_v path
* | and that the dynamicgrow path
* | allocated the backing buffer (initial
* | cap=0 forces growth on the first
* | write). Closes via io.st_close to
* | exercise dynamicclose_v's free.
* dynamicfrom_alt_rw | dynamicfrom_vstream seeded with a
* | write). Closes via io.close to
* | exercise dynamicclose's free.
* dynamicfrom_alt_rw | dynamicfrom seeded with a
* | 4-byte slice. Alternates st_read
* | (4 bytes back) → st_write (2 bytes,
* | grows past cap=4 → realloc). Asserts
@@ -42,7 +41,7 @@
* | Single ctx flavour, two dispatcher
* | paths through the same vtable.
* branched_fixed | branched callee per #105: two
* | fixed_vstream instances with
* | fixed instances with
* | different buffer sizes (3 and 5),
* | runtime-selected by the exit code
* | nudge. st_read on each returns the
@@ -62,25 +61,24 @@
* the order no longer matters and all 4 rows now run STAGE_CS|STAGE_WW
* byte-id. The earlier `import os;`-FIRST workaround is retired here.
*
* SIBLINGS (filed inline, NOT fixed here — fold-e2 is purely
* additive over fold-e1's frozen io.* surface):
* DEFERRALS / RELATED (NOT addressed by this row):
*
* - #173 (TRY-on-tagged-return both-stages broken) blocks
* fixed_write_v from returning Hare's `nomem` when full;
* vstream.ww surfaces 0 instead (memio.ww:155 OLD divergence).
* fixedwrite from returning Hare's `nomem` when full;
* memio.ww surfaces 0 instead (documented divergence).
* The probe doesn't pin Hare-equivalent nomem behaviour;
* fold-eFinal can graduate once #173 closes.
* it can graduate once #173 closes.
*
* - #195 (cgassign N_DOT TK_ASSIGN on aliased-ptr receiver):
* not bitten — the value-return constructor builds the stream in
* a local `let r: stream;` and field-assigns each slot (including
* r.vt.reader) through a plain pointer-to-local, not an aliased-ptr
* receiver. The flat ptr/len/cap fields (memio.ww:39) stay flat.
* receiver. The flat ptr/len/cap fields stay flat.
*
* GATE POLARITY: must stay GREEN. A red here means vstream.ww
* regressed, the alloc-struct-? path miscompiled, the intrusive
* vstream→*ctx cast miscomputed offsets, or io.vtable's first-field
* embed lost its offset-0 invariant.
* GATE POLARITY: must stay GREEN. A red here means lib/memio
* regressed, the sret value-return path miscompiled, the intrusive
* io.stream→*stream cast miscomputed offsets, or io.vtable's
* first-field embed lost its offset-0 invariant.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -118,11 +116,11 @@ static const struct row rows[] = {
" let buf: [8]u8;\n"
" buf[0] = 65u8; buf[1] = 66u8; buf[2] = 67u8; buf[3] = 68u8;\n"
" buf[4] = 69u8; buf[5] = 70u8; buf[6] = 71u8; buf[7] = 72u8;\n"
" let st: memio.stream = memio.fixed_vstream(buf[0:8]);\n"
" let s: io.vstream = &st.vt;\n"
" let st: memio.stream = memio.fixed(buf[0:8]);\n"
" let s: io.stream = &st.vt;\n"
" let out: [5]u8;\n"
" let n: size = 0;\n"
" let rd = io.st_read(s, out[0:5]);\n"
" let rd = io.read(s, out[0:5]);\n"
" if (rd is size) { n = rd as size; };\n"
" if (n == 5: size && out[0] == 65u8 && out[4] == 69u8) { return 42; };\n"
" return 99;\n"
@@ -135,14 +133,14 @@ static const struct row rows[] = {
"import io;\n"
"import os;\n"
"export fn main() i32 = {\n"
" let st: memio.stream = memio.dynamic_vstream();\n"
" let s: io.vstream = &st.vt;\n"
" let st: memio.stream = memio.dynamic();\n"
" let s: io.stream = &st.vt;\n"
" let src: [3]u8;\n"
" src[0] = 88u8; src[1] = 89u8; src[2] = 90u8;\n"
" let wr = io.st_write(s, src[0:3]);\n"
" let wr = io.write(s, src[0:3]);\n"
" let n: size = 0;\n"
" if (wr is size) { n = wr as size; };\n"
" let cl = io.st_close(s);\n"
" let cl = io.close(s);\n"
" if (cl is void && n == 3: size) { return 43; };\n"
" return 99;\n"
"};\n",
@@ -156,15 +154,15 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" let seed: [4]u8;\n"
" seed[0] = 1u8; seed[1] = 2u8; seed[2] = 3u8; seed[3] = 4u8;\n"
" let st: memio.stream = memio.dynamicfrom_vstream(seed[0:4]);\n"
" let s: io.vstream = &st.vt;\n"
" let st: memio.stream = memio.dynamicfrom(seed[0:4]);\n"
" let s: io.stream = &st.vt;\n"
" let out: [4]u8;\n"
" let rd = io.st_read(s, out[0:4]);\n"
" let rd = io.read(s, out[0:4]);\n"
" let rn: size = 0;\n"
" if (rd is size) { rn = rd as size; };\n"
" let extra: [2]u8;\n"
" extra[0] = 99u8; extra[1] = 100u8;\n"
" let wr = io.st_write(s, extra[0:2]);\n"
" let wr = io.write(s, extra[0:2]);\n"
" let wn: size = 0;\n"
" if (wr is size) { wn = wr as size; };\n"
" if (rn == 4: size && wn == 2: size && out[0] == 1u8 && out[3] == 4u8) { return 44; };\n"
@@ -182,14 +180,14 @@ static const struct row rows[] = {
" a[0] = 10u8; a[1] = 11u8; a[2] = 12u8;\n"
" let b: [5]u8;\n"
" b[0] = 20u8; b[1] = 21u8; b[2] = 22u8; b[3] = 23u8; b[4] = 24u8;\n"
" let sta: memio.stream = memio.fixed_vstream(a[0:3]);\n"
" let stb: memio.stream = memio.fixed_vstream(b[0:5]);\n"
" let sa: io.vstream = &sta.vt;\n"
" let sb: io.vstream = &stb.vt;\n"
" let sta: memio.stream = memio.fixed(a[0:3]);\n"
" let stb: memio.stream = memio.fixed(b[0:5]);\n"
" let sa: io.stream = &sta.vt;\n"
" let sb: io.stream = &stb.vt;\n"
" let outa: [3]u8;\n"
" let outb: [5]u8;\n"
" let rda = io.st_read(sa, outa[0:3]);\n"
" let rdb = io.st_read(sb, outb[0:5]);\n"
" let rda = io.read(sa, outa[0:3]);\n"
" let rdb = io.read(sb, outb[0:5]);\n"
" let na: size = 0;\n"
" let nb: size = 0;\n"
" if (rda is size) { na = rda as size; };\n"
@@ -200,10 +198,10 @@ static const struct row rows[] = {
45,
STAGE_CS | STAGE_WW, 1 },
/* accessors_string_buffer_reset — fold-eFinal PREP: the collapsed
* single accessors over the common `stream` header (string_v /
* buffer_v / reset_v, ref/hare/memio/stream.ha:81,74,87). Writes 3
* single accessors over the common `stream` header (string /
* buffer / reset, ref/hare/memio/stream.ha:81,74,87). Writes 3
* bytes through the value-returned fixed stream, then asserts
* string_v (str view), buffer_v ([]u8 view), and reset_v (rewind to
* string (str view), buffer ([]u8 view), and reset (rewind to
* 0) all read the flat header correctly. Pins the value-return
* field integrity (st.vt + st.ptr/len/cap/pos survive sret) AND the
* accessor collapse. cs.s == ww.s byte-id. */
@@ -214,23 +212,23 @@ static const struct row rows[] = {
"import os;\n"
"export fn main() i32 = {\n"
" let buf: [16]u8;\n"
" let st: memio.stream = memio.fixed_vstream(buf[0:16]);\n"
" let s: io.vstream = &st.vt;\n"
" let st: memio.stream = memio.fixed(buf[0:16]);\n"
" let s: io.stream = &st.vt;\n"
" let payload: [3]u8;\n"
" payload[0] = 65u8; payload[1] = 66u8; payload[2] = 67u8;\n"
" let wr = io.st_write(s, payload[0:3]);\n"
" let wr = io.write(s, payload[0:3]);\n"
" if (!(wr is size)) { return 90; };\n"
" let v: str = memio.string_v(&st);\n"
" let v: str = memio.string(&st);\n"
" if (v.len != 3 || v[0] != 65u8 || v[2] != 67u8) { return 91; };\n"
" let bv: []u8 = memio.buffer_v(&st);\n"
" let bv: []u8 = memio.buffer(&st);\n"
" if (bv.len != 3 || bv[1] != 66u8) { return 92; };\n"
" memio.reset_v(&st);\n"
" if (memio.string_v(&st).len != 0) { return 93; };\n"
" memio.reset(&st);\n"
" if (memio.string(&st).len != 0) { return 93; };\n"
" return 46;\n"
"};\n",
46,
STAGE_CS | STAGE_WW, 1 },
/* borrowedread_view_eof — the collapsed borrowedread_v
/* borrowedread_view_eof — the collapsed borrowedread
* (ref/hare/memio/stream.ha:94): returns an amt-byte borrowed view
* advancing the cursor, eof when fewer remain. Reads 3 of 4 seeded
* bytes (view len 3), then a 2-byte borrowedread over the remaining
@@ -243,13 +241,13 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" let seed: [4]u8;\n"
" seed[0] = 1u8; seed[1] = 2u8; seed[2] = 3u8; seed[3] = 4u8;\n"
" let st: memio.stream = memio.dynamicfrom_vstream(seed[0:4]);\n"
" let br = memio.borrowedread_v(&st, 3);\n"
" let st: memio.stream = memio.dynamicfrom(seed[0:4]);\n"
" let br = memio.borrowedread(&st, 3);\n"
" match (br) {\n"
" case let b: []u8 => { if (b.len != 3 || b[0] != 1u8 || b[2] != 3u8) { return 91; }; };\n"
" case io.eof => { return 92; };\n"
" };\n"
" let br2 = memio.borrowedread_v(&st, 2);\n"
" let br2 = memio.borrowedread(&st, 2);\n"
" match (br2) {\n"
" case let b: []u8 => { return 93; };\n"
" case io.eof => { return 47; };\n"