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

@@ -1372,32 +1372,30 @@ static const struct row rows[] = {
" raw[0] = 102u8; raw[1] = 111u8; raw[2] = 111u8; raw[3] = 10u8;\n"
" raw[4] = 98u8; raw[5] = 97u8; raw[6] = 114u8; raw[7] = 10u8;\n"
" raw[8] = 98u8; raw[9] = 97u8; raw[10] = 122u8;\n"
" let mem: memio.state;\n"
" let m: io.stream;\n"
" memio.fixed(&mem, &m, raw[0:11]);\n"
" let mst: memio.stream = memio.fixed(raw[0:11]);\n"
" let m: io.stream = &mst.vt;\n"
" let buf: [16]u8;\n"
" let sc: bufio.scanner;\n"
" bufio.newscanner(&sc, &m, buf[0:16]);\n"
" let sc: bufio.scanner = bufio.newscannerbuf(m, buf[0:16]);\n"
" let acc: i32 = 0;\n"
" let l1: (str | io.eof | io.closed | bufio.overflow) = bufio.scanline(&sc);\n"
" let l1: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);\n"
" match (l1) {\n"
" case let s: str => acc += s.len;\n"
" case io.eof => acc += -100;\n"
" case io.closed => acc += -1000;\n"
" case let _e: io.error => acc += -1000;\n"
" case bufio.overflow => acc += -10000;\n"
" };\n"
" let l2: (str | io.eof | io.closed | bufio.overflow) = bufio.scanline(&sc);\n"
" let l2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);\n"
" match (l2) {\n"
" case let s: str => acc += s.len;\n"
" case io.eof => acc += -100;\n"
" case io.closed => acc += -1000;\n"
" case let _e: io.error => acc += -1000;\n"
" case bufio.overflow => acc += -10000;\n"
" };\n"
" let l3: (str | io.eof | io.closed | bufio.overflow) = bufio.scanline(&sc);\n"
" let l3: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);\n"
" match (l3) {\n"
" case let s: str => acc += -100;\n"
" case io.eof => acc += 7;\n"
" case io.closed => acc += -1000;\n"
" case let _e: io.error => acc += -1000;\n"
" case bufio.overflow => acc += -10000;\n"
" };\n"
" return acc;\n"
@@ -1715,11 +1713,16 @@ static const struct row rows[] = {
* mixed-type args at the call site. End-to-end exercises the
* lib/fmt graduation: the wrapper-chain `println → fdprintln →
* fdprint` is itself variadic-forwarding, so this validates both
* gather (at main) and `args...` forward (inside lib/fmt). The
* exit code is bytes printed (`hello 7\n` = 8). */
* gather (at main) and `args...` forward (inside lib/fmt). println
* returns Hare's `(size | io.error)` (#94 fold-eFinal); the size
* arm carries bytes printed (`hello 7\n` = 8). */
{ "import fmt;\n"
"import io;\n"
"fn main() i32 = {\n"
" return fmt.println(\"hello\", 7i64): i32;\n"
" match (fmt.println(\"hello\", 7i64)) {\n"
" case let n: size => return n: i32;\n"
" case let _e: io.error => return -1;\n"
" };\n"
"};", 8 },
/* short-circuit `&&`: RHS skipped when LHS is false. Without
* short-circuit the `p.x` deref on a nil pointer segfaults.

View File

@@ -2,8 +2,8 @@
* 768_io_types_run — project #94 fold-1 step (d) (drew Fold D) sentinel.
* Pins lib/io/types.ww (ref/hare/io/types.ha) — `mode` / `whence`
* enums, `error = !(errors.unsupported | underread | nomem)` union,
* and the `reader` / `writer` / `closer` fn-type aliases. Fold-e1
* re-targeted the aliases from *stream → `vstream` (= *vtable in
* and the `reader` / `writer` / `closer` fn-type aliases. The
* fold-eFinal FLIP targets the aliases at `stream` (= *vtable in
* lib/io/stream.ww); the rows track. Hare splits the io module the
* same way: stream.ha + types.ha share the `io` module.
*
@@ -104,16 +104,16 @@ static const struct row rows[] = {
STAGE_CS | STAGE_WW },
/* reader/writer/closer alias rows. Fold-e1 re-targeted these aliases
* from *stream → vstream (= *vtable); the test fixtures track. The
* callee receivers are typed io.vstream and the call sites build a
* callee receivers are typed io.stream and the call sites build a
* stub vtable to take its address from. The vtable values are inert
* — only the dispatch type-shape is exercised. */
{ "reader_alias_param",
"package main;\n"
"import io;\n"
"fn dummy_read(s: io.vstream, buf: []u8) (size | io.eof | io.error) = {\n"
"fn dummy_read(s: io.stream, buf: []u8) (size | io.eof | io.error) = {\n"
" return 0: size;\n"
"};\n"
"fn use_reader(r: io.reader, s: io.vstream, buf: []u8) i32 = {\n"
"fn use_reader(r: io.reader, s: io.stream, buf: []u8) i32 = {\n"
" let v = r(s, buf);\n"
" if (v is size) { return 11; };\n"
" return -1;\n"
@@ -129,10 +129,10 @@ static const struct row rows[] = {
{ "writer_alias_param",
"package main;\n"
"import io;\n"
"fn dummy_write(s: io.vstream, buf: []u8) (size | io.error) = {\n"
"fn dummy_write(s: io.stream, buf: []u8) (size | io.error) = {\n"
" return buf.len: size;\n"
"};\n"
"fn use_writer(w: io.writer, s: io.vstream, buf: []u8) i32 = {\n"
"fn use_writer(w: io.writer, s: io.stream, buf: []u8) i32 = {\n"
" let v = w(s, buf);\n"
" if (v is size) { return 22; };\n"
" return -1;\n"
@@ -148,10 +148,10 @@ static const struct row rows[] = {
{ "closer_alias_param",
"package main;\n"
"import io;\n"
"fn dummy_close(s: io.vstream) (void | io.error) = {\n"
"fn dummy_close(s: io.stream) (void | io.error) = {\n"
" return void;\n"
"};\n"
"fn use_closer(c: io.closer, s: io.vstream) i32 = {\n"
"fn use_closer(c: io.closer, s: io.stream) i32 = {\n"
" let _v = c(s);\n"
" return 33;\n"
"};\n"

View File

@@ -1,10 +1,12 @@
/*
* 775_io_vtable_run — project #94 fold-e1 sentinel. Pins the additive
* lib/io/stream.ww vtable port: `vtable` (the three (*T|void) slots),
* `vstream` (= *vtable), and the `st_read`/`st_write`/`st_close`
* dispatchers (ref/hare/io/stream.ha:33-68). Coexists with lib/io/io.ww's
* legacy `stream` struct + read/write/close wrappers (fold-e2+ migrates
* them to vtable-backed implementations and retires the legacy surface).
* 775_io_vtable_run — project #94 fold-eFinal sentinel. Pins the
* single-surface lib/io/stream.ww vtable port: `vtable` (the three
* (*T|void) slots), `stream` (= *vtable), and the read/write/close
* dispatchers (ref/hare/io/stream.ha:33-68). The fold-eFinal FLIP
* retired the pre-vtable `stream` struct + `closed` tag, leaving this
* as the sole io surface. (Comment prose below predates the FLIP and
* still says `vstream`/`st_read`/`st_write`/`st_close` for the same
* `stream`/`read`/`write`/`close`.)
*
* Each row imports io, allocates a vtable, optionally points one slot at
* a user fn (via the `(&fn): *io.<role>` cast — see SIBLINGS below),
@@ -48,7 +50,7 @@
* | callee row; catches a constant-fold
* | mistake in the dispatch path.
*
* SIBLINGS (filed inline, NOT fixed here — fold-e1 is purely additive):
* DEFERRALS / RELATED (NOT addressed by these rows):
*
* - #199b layout-extension (wrapped-slot tag-remap): when widening a
* NAMED wrapper-typed value (e.g. `error`) into a tagged parent
@@ -109,16 +111,16 @@ static const struct row rows[] = {
{ "reader_set_happy",
"package main;\n"
"import io;\n"
"fn myread(s: io.vstream, buf: []u8) (size | io.eof | io.error) = {\n"
"fn myread(s: io.stream, buf: []u8) (size | io.eof | io.error) = {\n"
" return 7: size;\n"
"};\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" vt.reader = (&myread): *io.reader;\n"
" let v: io.vstream = &vt;\n"
" let v: io.stream = &vt;\n"
" let buf: [4]u8;\n"
" let bs: []u8 = buf[0:4];\n"
" let r = io.st_read(v, bs);\n"
" let r = io.read(v, bs);\n"
" if (r is size) {\n"
" let n = r as size;\n"
" if (n == 7: size) { return 70; };\n"
@@ -133,10 +135,10 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" let v: io.vstream = &vt;\n"
" let v: io.stream = &vt;\n"
" let buf: [4]u8;\n"
" let bs: []u8 = buf[0:4];\n"
" let _r = io.st_read(v, bs);\n"
" let _r = io.read(v, bs);\n"
" return 11;\n"
"};\n",
11,
@@ -144,16 +146,16 @@ static const struct row rows[] = {
{ "writer_set_happy",
"package main;\n"
"import io;\n"
"fn mywrite(s: io.vstream, buf: []u8) (size | io.error) = {\n"
"fn mywrite(s: io.stream, buf: []u8) (size | io.error) = {\n"
" return buf.len: size;\n"
"};\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" vt.writer = (&mywrite): *io.writer;\n"
" let v: io.vstream = &vt;\n"
" let v: io.stream = &vt;\n"
" let buf: [5]u8;\n"
" let bs: []u8 = buf[0:5];\n"
" let r = io.st_write(v, bs);\n"
" let r = io.write(v, bs);\n"
" if (r is size) {\n"
" let n = r as size;\n"
" if (n == 5: size) { return 80; };\n"
@@ -168,10 +170,10 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" let v: io.vstream = &vt;\n"
" let v: io.stream = &vt;\n"
" let buf: [3]u8;\n"
" let bs: []u8 = buf[0:3];\n"
" let _r = io.st_write(v, bs);\n"
" let _r = io.write(v, bs);\n"
" return 22;\n"
"};\n",
22,
@@ -181,8 +183,8 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" let v: io.vstream = &vt;\n"
" let r = io.st_close(v);\n"
" let v: io.stream = &vt;\n"
" let r = io.close(v);\n"
" if (r is void) { return 50; };\n"
" return 99;\n"
"};\n",
@@ -191,14 +193,14 @@ static const struct row rows[] = {
{ "closer_set",
"package main;\n"
"import io;\n"
"fn myclose(s: io.vstream) (void | io.error) = {\n"
"fn myclose(s: io.stream) (void | io.error) = {\n"
" return void;\n"
"};\n"
"export fn main() i32 = {\n"
" let vt: io.vtable;\n"
" vt.closer = (&myclose): *io.closer;\n"
" let v: io.vstream = &vt;\n"
" let r = io.st_close(v);\n"
" let v: io.stream = &vt;\n"
" let r = io.close(v);\n"
" if (r is void) { return 60; };\n"
" return 99;\n"
"};\n",
@@ -207,10 +209,10 @@ static const struct row rows[] = {
{ "branched_readers",
"package main;\n"
"import io;\n"
"fn r1(s: io.vstream, buf: []u8) (size | io.eof | io.error) = {\n"
"fn r1(s: io.stream, buf: []u8) (size | io.eof | io.error) = {\n"
" return 1: size;\n"
"};\n"
"fn r2(s: io.vstream, buf: []u8) (size | io.eof | io.error) = {\n"
"fn r2(s: io.stream, buf: []u8) (size | io.eof | io.error) = {\n"
" return 2: size;\n"
"};\n"
"export fn main() i32 = {\n"
@@ -220,8 +222,8 @@ static const struct row rows[] = {
" vt2.reader = (&r2): *io.reader;\n"
" let buf: [4]u8;\n"
" let bs: []u8 = buf[0:4];\n"
" let a = io.st_read(&vt1, bs);\n"
" let b = io.st_read(&vt2, bs);\n"
" let a = io.read(&vt1, bs);\n"
" let b = io.read(&vt2, bs);\n"
" let asz: size = 0;\n"
" let bsz: size = 0;\n"
" if (a is size) { asz = a as size; };\n"

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"

View File

@@ -1,14 +1,13 @@
/*
* 777_fmt_vstream_run — project #94 fold-e3 sentinel. Pins the
* additive lib/fmt/vstream.ww Option C parallel API: stack-resident
* fd_ctx with `vt: io.vtable` as the first field for the intrusive
* vstream cast, four wrappers (fdprint_v / fdprintln_v / fdprintf_v /
* fdprintfln_v) that take a raw fd, allocate fd_ctx on their own
* frame (never escapes — ken's dispatcher-CONTAINED discipline), and
* dispatch through io.st_write via the wired fdsinkwrite_v callback.
* Coexists with the pre-vtable fdprint / fdprintln / fdprintf /
* fdprintfln surface in fmt.ww (fold-eFinal, task #50, retires the
* latter once io fold-2 ports `handle = (file | int)`).
* 777_fmt_vstream_run — project #94 fold-eFinal sentinel. Pins the
* single-surface lib/fmt fd shim: stack-resident fd_ctx with
* `vt: io.vtable` as the first field for the intrusive io.stream
* cast, four wrappers (fdprint / fdprintln / fdprintf / fdprintfln)
* that take a raw fd, allocate fd_ctx on their own frame (never
* escapes — ken's dispatcher-CONTAINED discipline), and dispatch
* through io.write via the wired fdsinkwrite callback. The fd shim
* has no Hare counterpart; it folds into fNNN-over-handle once io
* fold-2 (#5) ports `handle = (file | int)`.
*
* Each row imports fmt + os + io, opens a per-process /tmp output
* file, calls one V wrapper to write through the fd, closes, re-
@@ -34,25 +33,25 @@
*
* row | what it pins
* --------------------------+--------------------------------------
* fdprintf_v_int | fdprintf_v with `"v={}\n"`-style
* fdprintf_v_int | fdprintf with `"v={}\n"`-style
* | format + one i64 arg. Asserts the
* | full intrusive shape (stack fd_ctx →
* | &c.vt → io.st_write → fdsinkwrite_v
* | &c.vt → io.write → fdsinkwrite
* | → os.write) plus the {n}-placeholder
* | parser routed through vformatfield.
* fdprintln_v_multi | fdprintln_v with three positional
* fdprintln_v_multi | fdprintln with three positional
* | args (i64 + str + bool). Asserts the
* | space-separator + trailing newline
* | shape mirrors OLD fdprintln (fmt.ww:
* | 145), routed through io.st_write.
* fdprint_v_raw | fdprint_v with one str arg, no
* | 145), routed through io.write.
* fdprint_v_raw | fdprint with one str arg, no
* | format mods (zero-format raw). Pins
* | the per-arg loop without the
* | placeholder parser (vfprint code
* | path, fmt/vstream.ww).
* branched_fdprintf_v | branched callee per #105: two
* | placeholder parser (fprint code
* | path, fmt.ww).
* branched_fdprintf | branched callee per #105: two
* | distinct format strings runtime-
* | selected from a single fdprintf_v
* | selected from a single fdprintf
* | call site. Catches a constant-fold
* | mistake in the format-string
* | dispatch (mirror of 776's
@@ -63,24 +62,24 @@
* (wwstage checker ordering-sensitivity on os.tryread/trywrite/
* tryopen's bare `return r;` over a tagged return type).
*
* SIBLINGS (filed inline, NOT fixed here — fold-e3 is purely
* additive over fold-e1/e2's frozen io.* + memio.* surface):
* DEFERRALS / RELATED (NOT addressed by these rows):
*
* - io fold-2 (handle port): drew-deferred per fold-d/fold-e3
* precedent. Hare's ref/hare/fmt/wrappers.ha:9-25 routes through
* io::handle; fdNNN_v collapses into bare fNNN_v once handle =
* (file | int) lands. eFinal (#50) graduates.
* - io fold-2 (handle port): drew-deferred. Hare's
* ref/hare/fmt/wrappers.ha:9-25 routes through io::handle; fdNNN
* collapses into bare fNNN once handle = (file | int) lands.
* #5 graduates.
*
* - #206 (bare &fn → (*alias|void)): 2 cast sites per wrapper
* vtable wire-up; drop out wholesale on close.
* vtable wire-up; explicit casts KEPT (ken/#214 — cast-drop
* deferred, gated on #214).
*
* - #173 (TRY-on-tagged-return both-stages broken): fdsinkwrite_v
* - #173 (TRY-on-tagged-return both-stages broken): fdsinkwrite
* constructs nomem and widens to io.error explicitly rather
* than using `os.trywrite(...)?`; same memio.vstream.ww shape.
* than using `os.trywrite(...)?`; same shape memio.ww adopts.
*
* GATE POLARITY: must stay GREEN. A red here means vstream.ww
* regressed, the stack fd_ctx → vstream cast miscomputed offsets,
* the {n}-placeholder dispatch through vformatfield regressed, or
* GATE POLARITY: must stay GREEN. A red here means lib/fmt
* regressed, the stack fd_ctx → io.stream cast miscomputed offsets,
* the {n}-placeholder dispatch through formatfield regressed, or
* io.vtable's first-field embed lost its offset-0 invariant.
*/
#include <stdio.h>
@@ -119,7 +118,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_777_a\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"v={}\\n\", 42i64);\n"
" let wr = fmt.fdprintf(fd, \"v={}\\n\", 42i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -147,7 +146,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_777_b\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintln_v(fd, 7i64, \"hi\", true);\n"
" let wr = fmt.fdprintln(fd, 7i64, \"hi\", true);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -175,7 +174,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_777_c\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprint_v(fd, \"raw\");\n"
" let wr = fmt.fdprint(fd, \"raw\");\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -194,7 +193,7 @@ static const struct row rows[] = {
"};\n",
44,
STAGE_CS, 0 },
{ "branched_fdprintf_v",
{ "branched_fdprintf",
"package main;\n"
"import os;\n"
"import fmt;\n"
@@ -208,7 +207,7 @@ static const struct row rows[] = {
" let f2: str = \"B{}\";\n"
" let fmtstr: str = f1;\n"
" if (sel == 0) { fmtstr = f2; };\n"
" let wr = fmt.fdprintf_v(fd, fmtstr, 9i64);\n"
" let wr = fmt.fdprintf(fd, fmtstr, 9i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"

View File

@@ -1,22 +1,18 @@
/*
* 778_bufio_vstream_run — project #94 fold-eFinal(PREP) sentinel. Pins
* the lib/bufio/vstream.ww parallel API — a COLLAPSE of the OLD bufio
* surface onto the io.vtable, NOT a port of Hare's missing scanner
* 778_bufio_vstream_run — project #94 fold-eFinal sentinel. Pins
* the single-surface lib/bufio over io.stream — the unified surface
* the eFinal FLIP collapsed to, NOT a port of Hare's missing scanner
* features (those are #217, OUT of eFinal). Covers:
* - buffered stream: `bufio_ctx` (vt@offset0 for the intrusive cast),
* `bufio_vstream` (returns the ctx BY VALUE; sret field-by-field)
* over an underlying **io.vstream** src — every underlying read/
* write/close goes through io.st_read/io.st_write/io.st_close (the
* - buffered stream: `stream` (vt@offset0 for the intrusive cast),
* `init` (returns the stream BY VALUE; sret field-by-field)
* over an underlying **io.stream** src — every underlying read/
* write/close goes through io.read/io.write/io.close (the
* vtable dispatchers), io.error forwards directly (no nomem-widen).
* Plus setflush_v / flush_v (public + internal drain) / unread_v /
* isbuffered_v (fn-ptr-equality discriminator).
* - scanner: `scanner_v` (value-return newscannerbuf_v over an
* io.vstream src) + scanbyte_v / scanbytes_v (single-byte delim) /
* scanline_v / finish_v.
* Coexists with the pre-vtable bufio.init / scanner / isbuffered surface
* in bufio.ww (fold-eFinal FLIP retires the latter + drops the `_v`
* suffix: bufio_ctx→stream, bufio_vstream→init, scanner_v→scanner,
* scanbytes_v→scanbytes, newscannerbuf_v→newscannerbuf, …).
* Plus setflush / flush (public + internal drain) / unread /
* isbuffered (fn-ptr-equality discriminator).
* - scanner: `scanner` (value-return newscannerbuf over an
* io.stream src) + scanbyte / scanbytes (single-byte delim) /
* scanline / finish.
*
* Each row imports os + bufio + memio + io (NOT fmt — bufio doesn't
* transitively pull fmt, so #209's formattable-match bail doesn't
@@ -25,89 +21,79 @@
*
* row | what it pins
* --------------------------+--------------------------------------
* stream_write_flush | bufio_vstream init + io.st_write
* | through bwrite_v + bufio.flush_v via
* | io.st_close. Asserts the data
* stream_write_flush | bufio.init + io.write
* | through bwrite + bufio.flush via
* | io.close. Asserts the data
* | reaches the underlying memio buffer
* | after close drains wbuf. Full chain:
* | bufio_ctx built field-by-field →
* | stream built field-by-field →
* | return r (sret) → caller takes &b.vt →
* | dispatcher recovers via *bufio_ctx
* | flush_v → io.write(b.src, ...).
* stream_read_unread | bufio_vstream read path: io.st_read
* | dispatcher recovers via *stream
* | flush → io.write(b.src, ...).
* stream_read_unread | init read path: io.read
* | refills rbuf from src, serves first
* | N bytes. Pins bread_v's read path
* | through the intrusive cast. unread_v
* | N bytes. Pins bread's read path
* | through the intrusive cast. unread
* | not exposed yet (no bufio.unread
* | equivalent on the V API surface
* | until eFinal); this row exercises
* | the base read path instead.
* isbuffered_v_discriminate | isbuffered_v on a fresh bufio_vstream
* | returns true; isbuffered_v on a
* | plain memio.fixed_vstream (no bufio
* isbuffered_v_discriminate | isbuffered on a fresh init
* | returns true; isbuffered on a
* | plain memio.fixed (no bufio
* | wrap) returns false. Pins the
* | fn-ptr-equality discriminator
* | (ref/hare/bufio/stream.ha:179) over
* | the new `_v` callback symbols.
* isbuffered_v_boundary | NEW isbuffered_v on bufio_vstream
* | returns true AND OLD bufio.isbuffered
* | on a bytewise-cast view of the same
* | vstream returns false. Boundary
* | check: the OLD discriminator reads
* | (s.read == bread) but the bytes at
* | &bufio_ctx.vt are vt.reader (tagged
* | union) — the cast reinterprets vt's
* | tag+ptr layout as the OLD stream's
* | ctx/read/write/close 4-fnptr layout,
* | and the OLD `bread` symbol address
* | is distinct from the NEW `bread_v`,
* | so the OLD discriminator returns
* | false. Proves the OLD + NEW worlds
* | use independent fn symbols.
* branched_bufio_vstream | branched callee per #105: two
* | the bread/bwrite callback symbols.
* isbuffered_v_boundary | isbuffered discriminates by vtable
* | identity: true on the bufio.init
* | wrapper stream, false on the
* | underlying (non-bufio) memio stream.
* | Pins the fn-ptr-equality discriminator
* | (ref/hare/bufio/stream.ha:179) over
* | the single-surface io.stream.
* branched_bufio_wrap | branched callee per #105: two
* | distinct underlying *io.stream's
* | runtime-selected; bufio_vstream
* | wraps the picked one. st_read
* | runtime-selected; bufio.init
* | wraps the picked one. io.read
* | returns the matching source's
* | content. Catches a constant-fold
* | mistake in the dispatch path
* | (mirror of 775's branched_readers
* | for the bufio-wrap side).
*
* SIBLINGS (filed inline, NOT fixed here — fold-e4 is purely
* additive over fold-e1/e2/e3's frozen io.* + memio.* + fmt.*
* surface):
* DEFERRALS / RELATED (NOT addressed by this row):
*
* - io fold-2 (handle port): drew-deferred. Hare's
* ref/hare/bufio/stream.ha:69 takes `src: io::handle`; once
* handle = (file | int) lands, bufio_vstream's src parameter
* collapses accordingly. eFinal (#50) graduates.
* handle = (file | int) lands, init's src parameter
* collapses accordingly. #5 graduates.
*
* - #206 (bare &fn → (*alias|void)): 5 cast sites in vstream.ww
* (3 vtable wire-up + 2 in isbuffered_v); drop out wholesale
* on close.
* - #206 (bare &fn → (*alias|void)): 5 cast sites in bufio.ww
* (3 vtable wire-up + 2 in isbuffered); explicit casts KEPT
* (ken/#214 — cast-drop deferred, gated on #214).
*
* - #173 (TRY-on-tagged-return both-stages broken): flush_v
* - #173 (TRY-on-tagged-return both-stages broken): flush
* constructs nomem and widens to io.error explicitly rather
* than using `io.write(...)?`; same memio.vstream.ww +
* fmt.vstream.ww shape.
* than using `io.write(...)?`; same shape memio.ww + fmt.ww
* adopt.
*
* - #207 (struct-lit multi-tagged-field copy drops past first) and
* #210 (slice-field struct-lit drop): not reachable from the
* value-return form — bufio_ctx is built field-by-field in a
* value-return form — stream is built field-by-field in a
* local then sret-returned, no `alloc(T{...})` struct-lit.
*
* BOOTSTRAP-EMBED CHECK: bufio is NOT embedded in any selfhost
* combined.ww (grep confirmed). Adding lib/bufio/vstream.ww does
* NOT require a Makefile regen (#110); only lib/bufio/ test paths
* see the new module. 990-997 byte-id gates stay green by virtue
* combined.ww (grep confirmed), so the fold-eFinal bufio collapse
* does NOT require a Makefile regen (#110); only lib/bufio/ test
* paths see the surface. 990-997 byte-id gates stay green by virtue
* of bufio being test-only.
*
* GATE POLARITY: must stay GREEN. A red here means vstream.ww
* regressed, the alloc-struct-? path miscompiled, the intrusive
* vstream→*bufio_ctx cast miscomputed offsets, the io.vtable
* GATE POLARITY: must stay GREEN. A red here means lib/bufio
* regressed, the sret value-return path miscompiled, the intrusive
* io.stream→*stream cast miscomputed offsets, the io.vtable
* first-field embed lost its offset-0 invariant, or the fn-ptr-
* equality discriminator in isbuffered_v stopped resolving.
* equality discriminator in isbuffered stopped resolving.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -144,20 +130,20 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let raw: [16]u8;\n"
" let mst: memio.stream = memio.fixed_vstream(raw[0:16]);\n"
" let msrc: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.fixed(raw[0:16]);\n"
" let msrc: io.stream = &mst.vt;\n"
" let rbuf: [8]u8;\n"
" let wbuf: [8]u8;\n"
" let b: bufio.bufio_ctx = bufio.bufio_vstream(msrc, rbuf[0:8], wbuf[0:8]);\n"
" let vs: io.vstream = &b.vt;\n"
" let b: bufio.stream = bufio.init(msrc, rbuf[0:8], wbuf[0:8]);\n"
" let vs: io.stream = &b.vt;\n"
" let payload: [5]u8;\n"
" payload[0] = 104u8; payload[1] = 105u8;\n"
" payload[2] = 33u8; payload[3] = 98u8; payload[4] = 121u8;\n"
" let wr = io.st_write(vs, payload[0:5]);\n"
" let wr = io.write(vs, payload[0:5]);\n"
" let nw: size = 0;\n"
" if (wr is size) { nw = wr as size; };\n"
" if (mst.pos != 0) { return 91; };\n"
" let cl = io.st_close(vs);\n"
" let cl = io.close(vs);\n"
" if (cl is io.error) { return 92; };\n"
" if (mst.pos != 5) { return 93; };\n"
" if (nw != 5: size) { return 94; };\n"
@@ -176,19 +162,19 @@ static const struct row rows[] = {
" let raw: [8]u8;\n"
" raw[0] = 65u8; raw[1] = 66u8; raw[2] = 67u8; raw[3] = 68u8;\n"
" raw[4] = 69u8; raw[5] = 70u8; raw[6] = 71u8; raw[7] = 72u8;\n"
" let mst: memio.stream = memio.fixed_vstream(raw[0:8]);\n"
" let msrc: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.fixed(raw[0:8]);\n"
" let msrc: io.stream = &mst.vt;\n"
" let rbuf: [8]u8;\n"
" let wbuf: [4]u8;\n"
" let b: bufio.bufio_ctx = bufio.bufio_vstream(msrc, rbuf[0:8], wbuf[0:4]);\n"
" let vs: io.vstream = &b.vt;\n"
" let b: bufio.stream = bufio.init(msrc, rbuf[0:8], wbuf[0:4]);\n"
" let vs: io.stream = &b.vt;\n"
" let out: [4]u8;\n"
" let rd1 = io.st_read(vs, out[0:3]);\n"
" let rd1 = io.read(vs, out[0:3]);\n"
" let n1: size = 0;\n"
" if (rd1 is size) { n1 = rd1 as size; };\n"
" if (n1 != 3: size) { return 91; };\n"
" if (out[0] != 65u8 || out[2] != 67u8) { return 92; };\n"
" let rd2 = io.st_read(vs, out[0:4]);\n"
" let rd2 = io.read(vs, out[0:4]);\n"
" let n2: size = 0;\n"
" if (rd2 is size) { n2 = rd2 as size; };\n"
" if (n2 != 4: size) { return 93; };\n"
@@ -205,17 +191,17 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let raw: [8]u8;\n"
" let mst: memio.stream = memio.fixed_vstream(raw[0:8]);\n"
" let msrc: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.fixed(raw[0:8]);\n"
" let msrc: io.stream = &mst.vt;\n"
" let rbuf: [4]u8;\n"
" let wbuf: [4]u8;\n"
" let b: bufio.bufio_ctx = bufio.bufio_vstream(msrc, rbuf[0:4], wbuf[0:4]);\n"
" let vsbuf: io.vstream = &b.vt;\n"
" let b: bufio.stream = bufio.init(msrc, rbuf[0:4], wbuf[0:4]);\n"
" let vsbuf: io.stream = &b.vt;\n"
" let buf2: [4]u8;\n"
" let st2: memio.stream = memio.fixed_vstream(buf2[0:4]);\n"
" let vsplain: io.vstream = &st2.vt;\n"
" if (!bufio.isbuffered_v(vsbuf)) { return 91; };\n"
" if (bufio.isbuffered_v(vsplain)) { return 92; };\n"
" let st2: memio.stream = memio.fixed(buf2[0:4]);\n"
" let vsplain: io.stream = &st2.vt;\n"
" if (!bufio.isbuffered(vsbuf)) { return 91; };\n"
" if (bufio.isbuffered(vsplain)) { return 92; };\n"
" return 48;\n"
"};\n",
48,
@@ -228,30 +214,19 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let raw: [8]u8;\n"
" let mst: memio.stream = memio.fixed_vstream(raw[0:8]);\n"
" let msrc: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.fixed(raw[0:8]);\n"
" let msrc: io.stream = &mst.vt;\n"
" let rbuf: [4]u8;\n"
" let wbuf: [4]u8;\n"
" let bc: bufio.bufio_ctx = bufio.bufio_vstream(msrc, rbuf[0:4], wbuf[0:4]);\n"
" let vs: io.vstream = &bc.vt;\n"
" if (!bufio.isbuffered_v(vs)) { return 91; };\n"
" let raw2: u64 = vs: u64;\n"
" let asold: *io.stream = raw2: *io.stream;\n"
" if (bufio.isbuffered(asold)) { return 92; };\n"
" let b: bufio.stream;\n"
" let rb: [4]u8;\n"
" let wb: [4]u8;\n"
" let raw3: [8]u8;\n"
" let mem3: memio.state;\n"
" let m3: io.stream;\n"
" memio.fixed(&mem3, &m3, raw3[0:8]);\n"
" bufio.init(&b, &m3, rb[0:4], wb[0:4]);\n"
" if (!bufio.isbuffered(&b.vtable)) { return 93; };\n"
" let bc: bufio.stream = bufio.init(msrc, rbuf[0:4], wbuf[0:4]);\n"
" let vs: io.stream = &bc.vt;\n"
" if (!bufio.isbuffered(vs)) { return 91; };\n"
" if (bufio.isbuffered(msrc)) { return 92; };\n"
" return 49;\n"
"};\n",
49,
STAGE_CS | STAGE_WW, 1 },
{ "branched_bufio_vstream",
{ "branched_bufio_wrap",
"package main;\n"
"import os;\n"
"import bufio;\n"
@@ -262,17 +237,17 @@ static const struct row rows[] = {
" raA[0] = 10u8; raA[1] = 11u8; raA[2] = 12u8; raA[3] = 13u8;\n"
" let raB: [4]u8;\n"
" raB[0] = 20u8; raB[1] = 21u8; raB[2] = 22u8; raB[3] = 23u8;\n"
" let mstA: memio.stream = memio.fixed_vstream(raA[0:4]);\n"
" let mstB: memio.stream = memio.fixed_vstream(raB[0:4]);\n"
" let mstA: memio.stream = memio.fixed(raA[0:4]);\n"
" let mstB: memio.stream = memio.fixed(raB[0:4]);\n"
" let sel: i32 = 1;\n"
" let src: io.vstream = &mstA.vt;\n"
" let src: io.stream = &mstA.vt;\n"
" if (sel == 0) { src = &mstB.vt; };\n"
" let rbuf: [4]u8;\n"
" let wbuf: [4]u8;\n"
" let bc: bufio.bufio_ctx = bufio.bufio_vstream(src, rbuf[0:4], wbuf[0:4]);\n"
" let vs: io.vstream = &bc.vt;\n"
" let bc: bufio.stream = bufio.init(src, rbuf[0:4], wbuf[0:4]);\n"
" let vs: io.stream = &bc.vt;\n"
" let out: [4]u8;\n"
" let rd = io.st_read(vs, out[0:4]);\n"
" let rd = io.read(vs, out[0:4]);\n"
" let n: size = 0;\n"
" if (rd is size) { n = rd as size; };\n"
" if (n != 4: size) { return 91; };\n"
@@ -282,9 +257,9 @@ static const struct row rows[] = {
51,
STAGE_CS | STAGE_WW, 1 },
/* scanner_lines — fold-eFinal PREP: the value-return scanner over an
* io.vstream src. newscannerbuf_v (Hare newscanner_buf) → scanline_v
* io.stream src. newscannerbuf (Hare newscanner_buf) → scanline
* twice ("ab", "c") → trailing "def" with no newline is EOF_DISCARD
* → io.eof → finish_v. Pins the scanner reads through io.st_read
* → io.eof → finish. Pins the scanner reads through io.read
* (vtable dispatch) on the underlying memio stream. cs.s==ww.s. */
{ "scanner_lines",
"package main;\n"
@@ -297,36 +272,36 @@ static const struct row rows[] = {
" raw[0]=97u8; raw[1]=98u8; raw[2]=10u8;\n"
" raw[3]=99u8; raw[4]=10u8;\n"
" raw[5]=100u8; raw[6]=101u8; raw[7]=102u8;\n"
" let mst: memio.stream = memio.dynamicfrom_vstream(raw[0:8]);\n"
" let vs: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.dynamicfrom(raw[0:8]);\n"
" let vs: io.stream = &mst.vt;\n"
" let win: [16]u8;\n"
" let sc: bufio.scanner_v = bufio.newscannerbuf_v(vs, win[0:16]);\n"
" let sc: bufio.scanner = bufio.newscannerbuf(vs, win[0:16]);\n"
" let ok: i32 = 0;\n"
" match (bufio.scanline_v(&sc)) {\n"
" match (bufio.scanline(&sc)) {\n"
" case let s: str => { if (s.len == 2 && s[0] == 97u8 && s[1] == 98u8) { ok += 1; }; };\n"
" case io.eof => { return 81; };\n"
" case let e: io.error => { return 82; };\n"
" case bufio.overflow => { return 83; };\n"
" };\n"
" match (bufio.scanline_v(&sc)) {\n"
" match (bufio.scanline(&sc)) {\n"
" case let s: str => { if (s.len == 1 && s[0] == 99u8) { ok += 1; }; };\n"
" case io.eof => { return 84; };\n"
" case let e: io.error => { return 85; };\n"
" case bufio.overflow => { return 86; };\n"
" };\n"
" match (bufio.scanline_v(&sc)) {\n"
" match (bufio.scanline(&sc)) {\n"
" case let s: str => { return 87; };\n"
" case io.eof => { ok += 1; };\n"
" case let e: io.error => { return 88; };\n"
" case bufio.overflow => { return 89; };\n"
" };\n"
" bufio.finish_v(&sc);\n"
" bufio.finish(&sc);\n"
" if (ok != 3) { return 90; };\n"
" return 52;\n"
"};\n",
52,
STAGE_CS | STAGE_WW, 1 },
/* scanner_byte_bytes — scanbyte_v pops 'A'; scanbytes_v(',') then
/* scanner_byte_bytes — scanbyte pops 'A'; scanbytes(',') then
* tokenizes "B" and "CD" from "AB,CD,". Single-byte delim (the OLD
* scantok behaviour; multibyte is #217). cs.s==ww.s. */
{ "scanner_byte_bytes",
@@ -339,24 +314,24 @@ static const struct row rows[] = {
" let raw: [6]u8;\n"
" raw[0]=65u8; raw[1]=66u8; raw[2]=44u8;\n"
" raw[3]=67u8; raw[4]=68u8; raw[5]=44u8;\n"
" let mst: memio.stream = memio.dynamicfrom_vstream(raw[0:6]);\n"
" let vs: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.dynamicfrom(raw[0:6]);\n"
" let vs: io.stream = &mst.vt;\n"
" let win: [8]u8;\n"
" let sc: bufio.scanner_v = bufio.newscannerbuf_v(vs, win[0:8]);\n"
" let sc: bufio.scanner = bufio.newscannerbuf(vs, win[0:8]);\n"
" let fb: u8 = 0u8;\n"
" match (bufio.scanbyte_v(&sc)) {\n"
" match (bufio.scanbyte(&sc)) {\n"
" case let b: u8 => { fb = b; };\n"
" case io.eof => { return 81; };\n"
" case let e: io.error => { return 82; };\n"
" };\n"
" if (fb != 65u8) { return 83; };\n"
" match (bufio.scanbytes_v(&sc, 44u8)) {\n"
" match (bufio.scanbytes(&sc, 44u8)) {\n"
" case let bs: []u8 => { if (bs.len != 1 || bs[0] != 66u8) { return 84; }; };\n"
" case io.eof => { return 85; };\n"
" case let e: io.error => { return 86; };\n"
" case bufio.overflow => { return 87; };\n"
" };\n"
" match (bufio.scanbytes_v(&sc, 44u8)) {\n"
" match (bufio.scanbytes(&sc, 44u8)) {\n"
" case let bs: []u8 => { if (bs.len != 2 || bs[0] != 67u8 || bs[1] != 68u8) { return 88; }; };\n"
" case io.eof => { return 89; };\n"
" case let e: io.error => { return 90; };\n"
@@ -366,9 +341,9 @@ static const struct row rows[] = {
"};\n",
53,
STAGE_CS | STAGE_WW, 1 },
/* stream_setflush — setflush_v swaps the auto-flush byte-set to ';';
/* stream_setflush — setflush swaps the auto-flush byte-set to ';';
* writing "ab;" auto-flushes (contains ';') so the sink advances to
* 3 with no explicit flush. Pins setflush_v + the flush-scan path.
* 3 with no explicit flush. Pins setflush + the flush-scan path.
* cs.s==ww.s. */
{ "stream_setflush",
"package main;\n"
@@ -378,18 +353,18 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let sinkbuf: [16]u8;\n"
" let sink: memio.stream = memio.fixed_vstream(sinkbuf[0:16]);\n"
" let sinkvs: io.vstream = &sink.vt;\n"
" let sink: memio.stream = memio.fixed(sinkbuf[0:16]);\n"
" let sinkvs: io.stream = &sink.vt;\n"
" let rb: [4]u8;\n"
" let wb: [8]u8;\n"
" let b: bufio.bufio_ctx = bufio.bufio_vstream(sinkvs, rb[0:4], wb[0:8]);\n"
" let bvs: io.vstream = &b.vt;\n"
" let b: bufio.stream = bufio.init(sinkvs, rb[0:4], wb[0:8]);\n"
" let bvs: io.stream = &b.vt;\n"
" let semi: [1]u8;\n"
" semi[0] = 59u8;\n"
" bufio.setflush_v(&b, semi[0:1]);\n"
" bufio.setflush(&b, semi[0:1]);\n"
" let payload: [3]u8;\n"
" payload[0]=97u8; payload[1]=98u8; payload[2]=59u8;\n"
" let wr = io.st_write(bvs, payload[0:3]);\n"
" let wr = io.write(bvs, payload[0:3]);\n"
" if (!(wr is size)) { return 81; };\n"
" if (sink.pos != 3) { return 82; };\n"
" if (sinkbuf[0] != 97u8 || sinkbuf[2] != 59u8) { return 83; };\n"
@@ -397,9 +372,9 @@ static const struct row rows[] = {
"};\n",
54,
STAGE_CS | STAGE_WW, 1 },
/* stream_unread — read "XYZ" then unread_v("XY") pushes the two
/* stream_unread — read "XYZ" then unread("XY") pushes the two
* bytes back in front of the read buffer; the next read returns them
* first. Pins unread_v's in-place shift through *bufio_ctx.
* first. Pins unread's in-place shift through *stream.
* cs.s==ww.s. */
{ "stream_unread",
"package main;\n"
@@ -410,22 +385,22 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" let raw: [4]u8;\n"
" raw[0]=88u8; raw[1]=89u8; raw[2]=90u8;\n"
" let mst: memio.stream = memio.dynamicfrom_vstream(raw[0:3]);\n"
" let vs: io.vstream = &mst.vt;\n"
" let mst: memio.stream = memio.dynamicfrom(raw[0:3]);\n"
" let vs: io.stream = &mst.vt;\n"
" let rbuf: [4]u8;\n"
" let wbuf: [4]u8;\n"
" let b: bufio.bufio_ctx = bufio.bufio_vstream(vs, rbuf[0:4], wbuf[0:4]);\n"
" let bvs: io.vstream = &b.vt;\n"
" let b: bufio.stream = bufio.init(vs, rbuf[0:4], wbuf[0:4]);\n"
" let bvs: io.stream = &b.vt;\n"
" let out: [4]u8;\n"
" let rd = io.st_read(bvs, out[0:3]);\n"
" let rd = io.read(bvs, out[0:3]);\n"
" let n: size = 0;\n"
" if (rd is size) { n = rd as size; };\n"
" if (n != 3: size || out[0] != 88u8 || out[2] != 90u8) { return 81; };\n"
" let push: [2]u8;\n"
" push[0]=88u8; push[1]=89u8;\n"
" bufio.unread_v(&b, push[0:2]);\n"
" bufio.unread(&b, push[0:2]);\n"
" let out2: [2]u8;\n"
" let rd2 = io.st_read(bvs, out2[0:2]);\n"
" let rd2 = io.read(bvs, out2[0:2]);\n"
" let n2: size = 0;\n"
" if (rd2 is size) { n2 = rd2 as size; };\n"
" if (n2 != 2: size || out2[0] != 88u8 || out2[1] != 89u8) { return 82; };\n"
@@ -564,7 +539,7 @@ main(void)
int got = run_row(cdrv, cwd, &rows[i], seq++);
if (got != rows[i].want_exit) {
fprintf(stderr,
"bufio_vstream_run[cs][%s]: exit=%d want=%d\n",
"init_run[cs][%s]: exit=%d want=%d\n",
rows[i].label, got, rows[i].want_exit);
fail++;
}
@@ -574,7 +549,7 @@ main(void)
int got = run_row(wdrv, cwd, &rows[i], seq++);
if (got != rows[i].want_exit) {
fprintf(stderr,
"bufio_vstream_run[ww][%s]: exit=%d want=%d\n",
"init_run[ww][%s]: exit=%d want=%d\n",
rows[i].label, got, rows[i].want_exit);
fail++;
}
@@ -582,7 +557,7 @@ main(void)
total++;
if (asm_byte_identical(cdrv, wdrv, cwd, &rows[i], seq++) != 0) {
fprintf(stderr,
"bufio_vstream_run[byte-id][%s]: cstage vs wwstage asm differs\n",
"init_run[byte-id][%s]: cstage vs wwstage asm differs\n",
rows[i].label);
fail++;
}
@@ -591,13 +566,13 @@ main(void)
}
if (!wwpresent)
fprintf(stderr, "bufio_vstream_run: skip wwstage (no %s)\n", wdrv);
fprintf(stderr, "init_run: skip wwstage (no %s)\n", wdrv);
if (fail) {
fprintf(stderr, "bufio_vstream_run: %d/%d fixtures failed\n",
fprintf(stderr, "init_run: %d/%d fixtures failed\n",
fail, total);
return 1;
}
printf("bufio_vstream_run: %d/%d ok\n", total, total);
printf("init_run: %d/%d ok\n", total, total);
return 0;
}

View File

@@ -1,16 +1,13 @@
/*
* 779_log_vstream_run — project #94 fold-e5 sentinel. Pins the
* additive lib/log/vstream.ww Option C parallel API: module-static
* stderrsink_ctx_g with `vt: io.vtable` as the first field for the
* intrusive vstream cast, the 10 _v variants of OLD log.ww's surface
* (new_v / lprintln_v / println_v / lprintfln_v / printfln_v / lfatal_v
* / fatal_v / lfatalf_v / fatalf_v / setlogger_v), a vlogger vtable +
* vstdlogger over io.vstream sink, and lazy ensureinit_v wiring the
* stderr default + silent_v / default_v / global_v *vlogger globals.
* Coexists with the pre-vtable log.logger / log.stdlogger / log.new /
* log.println / etc. surface in log.ww (fold-eFinal, task #50, retires
* the latter and drops the `_v` suffix wholesale to match Hare's bare
* names).
* 779_log_vstream_run — project #94 fold-eFinal sentinel. Pins the
* single-surface lib/log: module-static stderrsink_ctx_g with
* `vt: io.vtable` as the first field for the intrusive cast, the 10
* exported variants of log.ww's surface (new / lprintln / println /
* lprintfln / printfln / lfatal / fatal / lfatalf / fatalf /
* setlogger), a logger vtable + stdlogger over an io.stream sink, and
* lazy ensureinit wiring the stderr default + silent / default /
* global *logger globals. The fold-eFinal FLIP collapsed the dual
* surface into this one Hare-shaped surface (bare names, no suffix).
*
* Each row imports os + log + memio + io. log itself imports fmt,
* so the formattable / field types flow through transitively.
@@ -18,8 +15,8 @@
* Cstage-only per row (no STAGE_WW, no byte_id) — pre-existing
* wwstage bug #209 (sibling of #190): the wwstage checker bails on
* match-arm-over-formattable when fmt is imported transitively, which
* lib/log does for the vlogger vtable signatures + the fmt.vfprint /
* vfprintf dispatch in stdprintln_v / stdprintfln_v. The bug bites the
* lib/log does for the logger vtable signatures + the fmt.fprint /
* fprintf dispatch in stdprintln / stdprintfln. The bug bites the
* OLD log surface identically — `log.println("hi")` from a probe
* trips the same trace. Existing 970 logtest runs the @test fixture
* under cstage `ww run` only, so the OLD surface is fine via cstage.
@@ -30,70 +27,63 @@
*
* row | what it pins
* --------------------------+--------------------------------------
* println_v_default_stderr | log.println_v through the [[default_v]]
* println_v_default_stderr | log.println through the [[default]]
* | global, routed to fd 2 via the
* | module-static stderrsink_ctx_g. Asserts
* | ensureinit_v wires + dispatches without
* | ensureinit wires + dispatches without
* | crashing; stderr capture is left to the
* | shell runner. Pins the full chain:
* | println_v → lprintln_v(global_v) →
* | (*vlogger).println_v → stdprintln_v
* | fmt.vfprint + io.st_write("\n").
* | println → lprintln(global) →
* | (*logger).println → stdprintln →
* | fmt.fprint + io.write("\n").
* printfln_v_default_stderr | Same chain as row 1 but through the
* | format-string slot (printfln_v
* | lprintfln_v(global_v) → stdprintfln_v
* | → fmt.vfprintf + io.st_write("\n")).
* | format-string slot (printfln →
* | lprintfln(global) → stdprintfln
* | → fmt.fprintf + io.write("\n")).
* | Pins the {n}-placeholder dispatch
* | through vformatfield reaches the
* | default sink.
* lprintln_v_custom_sink | memio.fixed_vstream-backed vstdlogger;
* | log.new_v wires the vtable + sink,
* | log.lprintln_v dispatches "hi" + 7i64
* | through stdprintln_v. Asserts the
* lprintln_v_custom_sink | memio.fixed-backed stdlogger;
* | log.new wires the vtable + sink,
* | log.lprintln dispatches "hi" + 7i64
* | through stdprintln. Asserts the
* | exact bytes ("hi 7\n") land in the
* | caller's buffer (fixed_vstream borrows
* | caller's buffer (fixed borrows
* | the slice, so the bytes are visible
* | back through buf[]).
* branched_lprintln_v | branched callee per #105: two distinct
* | vstdlogger sinks runtime-selected via
* | *vlogger pointer. lprintln_v dispatches
* branched_lprintln | branched callee per #105: two distinct
* | stdlogger sinks runtime-selected via
* | *logger pointer. lprintln dispatches
* | through the picked sink only; the
* | other stays empty. Catches a constant-
* | fold mistake in the fn-ptr dispatch
* | (mirror of 778's branched_bufio_vstream).
* | (mirror of 778's branched_bufio_wrap).
*
* SIBLINGS (filed inline, NOT fixed here — fold-e5 is purely
* additive over fold-e1/e2/e3/e4's frozen io.* + memio.* + fmt.* +
* bufio.* surface plus the minimal `export` bump on fmt.vfprint /
* fmt.vfprintf):
* DEFERRALS / RELATED (NOT addressed by this row):
*
* - eFinal (#50): atomic flip + delete OLD log surface + drop the
* `_v` suffix wholesale.
* - #206 (bare &fn → (*alias|void)): 2 cast sites at ensureinit
* in lib/log/log.ww; the explicit casts are KEPT (ken/#214 —
* cast-drop is a separate deferred payoff gated on #214).
*
* - #206 (bare &fn → (*alias|void)): 2 cast sites at ensureinit_v
* in lib/log/vstream.ww; drop out wholesale on close.
*
* - #173 (TRY-on-tagged-return both-stages broken): stderrwrite_v
* - #173 (TRY-on-tagged-return both-stages broken): stderrwrite
* constructs nomem and widens to io.error explicitly rather than
* using `os.trywrite(...)?`; same shape memio.vstream.ww +
* fmt.vstream.ww + bufio.vstream.ww adopt.
* using `os.trywrite(...)?`; same shape memio.ww + fmt.ww +
* bufio.ww adopt.
*
* - #209 (wwstage formattable match-arm bail): every row is
* STAGE_CS-only; byte-id deferred until #209 lands.
*
* BOOTSTRAP-EMBED CHECK: log is NOT embedded in any selfhost
* combined.ww (grep `package log\|import log` returned empty pre-
* impl). Adding lib/log/vstream.ww + the two `export` bumps on
* lib/fmt/vstream.ww does NOT require a Makefile regen (#110); only
* lib/log/ + lib/fmt/ test paths see the new module surface. 990-997
* byte-id gates stay green by virtue of log being test-only and the
* fmt vstream.ww changes being non-embedded.
* combined.ww (grep `package log\|import log` returns empty), so the
* fold-eFinal log collapse does not require a Makefile regen (#110);
* only lib/log/ + lib/fmt/ test paths see the surface. 990-997
* byte-id gates stay green by virtue of log being test-only.
*
* GATE POLARITY: must stay GREEN. A red here means vstream.ww
* GATE POLARITY: must stay GREEN. A red here means lib/log
* regressed, the module-static stderrsink_ctx_g zero-init or chained
* vt-field assigns regressed, the intrusive vstream→*stderrsink_ctx
* cast miscomputed offsets, ensureinit_v's one-shot guard broke, or
* the fn-ptr dispatch through vlogger.println_v / printfln_v stopped
* vt-field assigns regressed, the intrusive io.stream→*stderrsink_ctx
* cast miscomputed offsets, ensureinit's one-shot guard broke, or
* the fn-ptr dispatch through logger.println / printfln stopped
* resolving.
*/
#include <stdio.h>
@@ -128,7 +118,7 @@ static const struct row rows[] = {
"import os;\n"
"import log;\n"
"export fn main() i32 = {\n"
" log.println_v(\"hello\");\n"
" log.println(\"hello\");\n"
" return 42;\n"
"};\n",
42,
@@ -138,7 +128,7 @@ static const struct row rows[] = {
"import os;\n"
"import log;\n"
"export fn main() i32 = {\n"
" log.printfln_v(\"v={}\", 7i64);\n"
" log.printfln(\"v={}\", 7i64);\n"
" return 43;\n"
"};\n",
43,
@@ -151,10 +141,10 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let buf: [16]u8;\n"
" let st: memio.stream = memio.fixed_vstream(buf[0:16]);\n"
" let vs: io.vstream = &st.vt;\n"
" let sl: log.vstdlogger = log.new_v(vs);\n"
" log.lprintln_v(&sl.logger, \"hi\", 7i64);\n"
" let st: memio.stream = memio.fixed(buf[0:16]);\n"
" let vs: io.stream = &st.vt;\n"
" let sl: log.stdlogger = log.new(vs);\n"
" log.lprintln(&sl.logger, \"hi\", 7i64);\n"
" if (buf[0] != 104u8) { return 91; };\n"
" if (buf[1] != 105u8) { return 92; };\n"
" if (buf[2] != 32u8) { return 93; };\n"
@@ -164,7 +154,7 @@ static const struct row rows[] = {
"};\n",
44,
STAGE_CS, 0 },
{ "branched_lprintln_v",
{ "branched_lprintln",
"package main;\n"
"import os;\n"
"import log;\n"
@@ -173,16 +163,16 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" let bufA: [16]u8;\n"
" let bufB: [16]u8;\n"
" let stA: memio.stream = memio.fixed_vstream(bufA[0:16]);\n"
" let vsA: io.vstream = &stA.vt;\n"
" let stB: memio.stream = memio.fixed_vstream(bufB[0:16]);\n"
" let vsB: io.vstream = &stB.vt;\n"
" let slA: log.vstdlogger = log.new_v(vsA);\n"
" let slB: log.vstdlogger = log.new_v(vsB);\n"
" let stA: memio.stream = memio.fixed(bufA[0:16]);\n"
" let vsA: io.stream = &stA.vt;\n"
" let stB: memio.stream = memio.fixed(bufB[0:16]);\n"
" let vsB: io.stream = &stB.vt;\n"
" let slA: log.stdlogger = log.new(vsA);\n"
" let slB: log.stdlogger = log.new(vsB);\n"
" let sel: i32 = 1;\n"
" let chosen: *log.vlogger = &slA.logger;\n"
" let chosen: *log.logger = &slA.logger;\n"
" if (sel == 0) { chosen = &slB.logger; };\n"
" log.lprintln_v(chosen, \"pick\");\n"
" log.lprintln(chosen, \"pick\");\n"
" if (bufA[0] != 112u8) { return 91; };\n"
" if (bufA[1] != 105u8) { return 92; };\n"
" if (bufA[2] != 99u8) { return 93; };\n"

View File

@@ -1,18 +1,14 @@
/*
* 780_fmt_vstream_mods_run — project #94 fold-e6 sentinel. Pins the
* V-side modifier-formatting machinery (vrawleni64 / vrawlenstr /
* vrawlenf64 / vrawlen / vformatraw / vformatone) in lib/fmt/
* vstream.ww. Before fold-e6, the V printf path parsed mods via
* scanmods but dropped them after parse: vformatfield routed straight
* to vwriteone (no width / alignment / pad / sign / base / prec
* honoured). fold-e6 widens vformatfield to take `*mods` and routes
* through vformatone — same dispatch shape as OLD formatfield at
* fmt.ww:648. Coexists with the OLD modifier path at fmt.ww:443-641
* (fmt.ww UNCHANGED this fold); fold-eFinal (task #50) collapses both
* surfaces.
* 780_fmt_vstream_mods_run — project #94 fold-eFinal sentinel. Pins the
* modifier-formatting machinery (rawleni64 / rawlenstr / rawlenf64 /
* rawlen / formatraw / formatone) in lib/fmt/fmt.ww: formatfield takes
* `*mods` and routes through formatone so the {:mods} placeholder
* honours width / alignment / pad / sign / base / prec. The fold-eFinal
* FLIP collapsed the dual fmt surface into this one (the former `v*`
* modifier helpers merged into the bare names).
*
* Each row imports fmt + os + io, opens a per-process /tmp output
* file, calls fdprintf_v with a {:mods} format string + one arg, and
* file, calls fdprintf with a {:mods} format string + one arg, and
* asserts the exact byte content read back.
*
* Cstage-only per row — pre-existing wwstage bug #209 (sibling of
@@ -48,28 +44,22 @@
* (wwstage checker ordering-sensitivity on os.tryread/trywrite/
* tryopen's bare `return r;` over a tagged return type).
*
* SIBLINGS (filed inline, NOT fixed here — fold-e6 is purely additive
* over fold-e1/e2/e3/e4/e5's frozen io.* + memio.* + fmt.* + bufio.*
* + log.* surface):
* DEFERRALS / RELATED (NOT addressed by these rows):
*
* - #209 (wwstage formattable match-arm bail): blocks STAGE_WW
* here, same as 777_fmt_vstream_run. Cstage-only until close.
* - eFinal (#50): collapses V + OLD surfaces; the `v*` names rename
* off and the OLD rawlen* / formatraw / formatone delete. The v*
* duplication of the rawlen-family today is transient — eFinal
* dedupes.
*
* BOOTSTRAP-EMBED CHECK: fmt is NOT embedded in any selfhost
* combined.ww (grep confirmed pre-impl). Adding modifier formatting
* to lib/fmt/vstream.ww does NOT require a Makefile regen (#110);
* only test paths see the new machinery. 990-997 byte-id gates stay
* green by virtue of fmt being test-only on the bootstrap surface.
* combined.ww (grep confirmed), so the fold-eFinal fmt collapse does
* NOT require a Makefile regen (#110); only test paths see the
* machinery. 990-997 byte-id gates stay green by virtue of fmt being
* test-only on the bootstrap surface.
*
* GATE POLARITY: must stay GREEN. A red here means vformatone /
* vformatraw / vrawlen miscomputed bytes, vformatfield regressed its
* *mods route, scanmods/modsinit (shared from fmt.ww) drifted, or
* the strconv.u64tos base path miscompiled under fdprintf_v's
* intrusive vstream→*fd_ctx dispatch.
* GATE POLARITY: must stay GREEN. A red here means formatone /
* formatraw / rawlen miscomputed bytes, formatfield regressed its
* *mods route, scanmods/modsinit drifted, or the strconv.u64tos base
* path miscompiled under fdprintf's intrusive io.stream→*fd_ctx
* dispatch.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -107,7 +97,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_780_a\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"{:5}\", 42i64);\n"
" let wr = fmt.fdprintf(fd, \"{:5}\", 42i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -135,7 +125,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_780_b\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"{:.3}\", \"hello\");\n"
" let wr = fmt.fdprintf(fd, \"{:.3}\", \"hello\");\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -163,7 +153,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_780_c\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"{:x}\", 255i64);\n"
" let wr = fmt.fdprintf(fd, \"{:x}\", 255i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -191,7 +181,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_780_d\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"{:+}\", 7i64);\n"
" let wr = fmt.fdprintf(fd, \"{:+}\", 7i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -219,7 +209,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_780_e\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintf_v(fd, \"{:_05}\", 42i64);\n"
" let wr = fmt.fdprintf(fd, \"{:_05}\", 42i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"

View File

@@ -1,17 +1,15 @@
/*
* 781_fmt_vstream_compositions_run — project #94 fold-e7 sentinel.
* Pins the V-side composition wrappers in lib/fmt/vstream.ww —
* vfprintln / vfprintfln / vbsprintf / vasprintf — plus the two
* memio enablers fold-e7 bundles alongside (memio.fixed_string /
* memio.dynamic_string in lib/memio/vstream.ww). Coexists with the
* OLD fmt.fprintln / fprintfln / bsprintf / asprintf surface in
* fmt.ww:240,740,839,873 (fmt.ww UNCHANGED this fold; eFinal
* task #50 collapses both surfaces and renames the `v` suffix off).
* 781_fmt_vstream_compositions_run — project #94 fold-eFinal sentinel.
* Pins the composition wrappers in lib/fmt/fmt.ww —
* fprintln / fprintfln / bsprintf / asprintf — plus the memio
* accessor (memio.string in lib/memio/memio.ww) they read back
* through. The fold-eFinal FLIP collapsed the dual fmt + memio
* surfaces into one (the former `v`-suffixed wrappers and the
* fixed_string / dynamic_string accessors merged into the bare names).
*
* The two memio helpers are direct enablers (vbsprintf reads its
* written prefix via fixed_string; vasprintf reads its grown buffer
* via dynamic_string), drew-approved per
* feedback_refactor_routing_same_class_drops (prereqs, not churn).
* memio.string is the direct enabler: bsprintf reads its written
* prefix via memio.string; asprintf reads its grown buffer via the
* same accessor.
*
* Each row imports fmt + os + io, drives one of the four V wrappers,
* and asserts the exact bytes / size emitted. Per-row unique exit
@@ -19,40 +17,39 @@
*
* row | what it pins
* --------------------------+--------------------------------------
* fdprintln_v_run_basic | fdprintln_v wired vstream sink
* | (inline vfprint + vputbytes "\n").
* fdprintln_v_run_basic | fdprintln wired vstream sink
* | (inline fprint + vputbytes "\n").
* | One i64 arg + str arg + bool arg;
* | asserts space-separator plus trailing
* | newline byte content.
* fdprintfln_v_run_fmt | fdprintfln_v wired vstream sink with
* fdprintfln_v_run_fmt | fdprintfln wired vstream sink with
* | a {n}-placeholder format string.
* | Asserts placeholder substitution +
* | trailing newline shape (mirror of
* | fmt.fprintfln, fmt.ww:740).
* vfprintln_basic | fmt.vfprintln dispatched DIRECTLY
* | through memio.fixed_vstream + read
* | back via memio.fixed_string. Pins
* | the new V-side composition symbol
* | itself (fdprintln_v open-codes the
* | same vfprint+vputbytes chain rather
* | than calling vfprintln, so without
* | this row the new symbol ships
* | uncovered).
* vfprintfln_basic | fmt.vfprintfln direct dispatch via
* | memio.fixed_vstream + fixed_string,
* fprintln_basic | fmt.fprintln dispatched DIRECTLY
* | through memio.fixed + read
* | back via memio.string. Pins
* | the composition symbol itself
* | (fdprintln open-codes the same
* | fprint+putbytes chain rather than
* | calling fprintln, so without this
* | row the symbol ships uncovered).
* fprintfln_basic | fmt.fprintfln direct dispatch via
* | memio.fixed + memio.string,
* | same direct-symbol rationale as
* | vfprintln_basic.
* bsprintf_v_basic | vbsprintf into a caller-supplied
* | fprintln_basic.
* bsprintf_v_basic | bsprintf into a caller-supplied
* | [16]u8 buffer through
* | memio.fixed_vstream;
* | memio.fixed_string returns the prefix
* | memio.fixed;
* | memio.string returns the prefix
* | view. Asserts both the bytes in the
* | caller's buffer AND the returned str
* | view (ptr == buf + 0, len == 5).
* asprintf_v_basic | vasprintf into a heap-grown str
* | through memio.dynamic_vstream;
* | memio.dynamic_string + shrink-copy +
* | io.st_close. Asserts the owned str
* asprintf_v_basic | asprintf into a heap-grown str
* | through memio.dynamic;
* | memio.string + shrink-copy +
* | io.close. Asserts the owned str
* | bytes, then frees via os.free.
*
* Cstage-only per row (no STAGE_WW, no byte_id) — pre-existing
@@ -68,32 +65,26 @@
* document (wwstage checker ordering-sensitivity on os.tryread /
* trywrite / tryopen's bare `return r;` over a tagged return type).
*
* SIBLINGS (filed inline, NOT fixed here — fold-e7 is purely
* additive over fold-e1/e2/e3/e4/e5/e6's frozen io.* + memio.* +
* fmt.* + bufio.* + log.* surface):
* DEFERRALS / RELATED (NOT addressed by these rows):
*
* - #209 (wwstage formattable match-arm bail): blocks STAGE_WW
* here, same as 777/780. Cstage-only until close.
* - #173 (TRY-on-tagged-return both-stages broken): vbsprintf
* - #173 (TRY-on-tagged-return both-stages broken): bsprintf
* widens nomem into io.error inline rather than `memio.
* fixed_vstream(buf)?` for the same reason memio.vstream.ww
* does at line 87-99.
* - eFinal (#50): collapses V + OLD surfaces; the `v` names
* rename off and the OLD fprintln / fprintfln / bsprintf /
* asprintf delete.
* fixed(buf)?` for the same reason memio.ww does.
*
* BOOTSTRAP-EMBED CHECK: fmt is NOT embedded in any selfhost
* combined.ww (grep verified pre-impl). memio.vstream.ww IS embedded
* in w6c + wwdump combined.ww — the fold-e7 memio helpers ride along
* via the regen committed in this same commit (per #110 SSoT). 990/
* 994/995 byte-id gates + combined_ww_fresh stay green by virtue of
* the regen.
* combined.ww (grep verified). memio IS embedded in w6c + wwdump
* combined.ww — the fold-eFinal memio collapse rides along via the
* regen committed in this same commit (per #110 SSoT). 990/994/995
* byte-id gates + combined_ww_fresh stay green by virtue of the
* regen.
*
* GATE POLARITY: must stay GREEN. A red here means vfprintln /
* vfprintfln dropped the newline byte, vbsprintf returned a stale
* memio.fixed_string view (intrusive cast broke), vasprintf failed
* to shrink-copy / close cleanly, or the underlying vfprint /
* vfprintf primitives regressed.
* GATE POLARITY: must stay GREEN. A red here means fprintln /
* fprintfln dropped the newline byte, bsprintf returned a stale
* memio.string view (intrusive cast broke), asprintf failed
* to shrink-copy / close cleanly, or the underlying fprint /
* fprintf primitives regressed.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -131,7 +122,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_781_a\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintln_v(fd, 1i64, \"hi\", true);\n"
" let wr = fmt.fdprintln(fd, 1i64, \"hi\", true);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -163,7 +154,7 @@ static const struct row rows[] = {
" let path: str = \"/tmp/wwfmtv_781_b\";\n"
" let fd: i32 = os.open(path, os.flag.RDWR | os.flag.CREATE | os.flag.TRUNC, 0o644: i32);\n"
" if (fd < 0) { return 90; };\n"
" let wr = fmt.fdprintfln_v(fd, \"x={}\", 7i64);\n"
" let wr = fmt.fdprintfln(fd, \"x={}\", 7i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
@@ -182,7 +173,7 @@ static const struct row rows[] = {
"};\n",
61,
STAGE_CS, 0 },
{ "vfprintln_basic",
{ "fprintln_basic",
"package main;\n"
"import os;\n"
"import fmt;\n"
@@ -190,16 +181,16 @@ static const struct row rows[] = {
"import memio;\n"
"export fn main() i32 = {\n"
" let buf: [16]u8;\n"
" let st: memio.stream = memio.fixed_vstream(buf[0:16]);\n"
" let vs: io.vstream = &st.vt;\n"
" let wr = fmt.vfprintln(vs, 1i64, \"hi\", true);\n"
" let st: memio.stream = memio.fixed(buf[0:16]);\n"
" let vs: io.stream = &st.vt;\n"
" let wr = fmt.fprintln(vs, 1i64, \"hi\", true);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
" case io.error => { return 91; };\n"
" };\n"
" if (nw != 10: size) { return 92; };\n"
" let view: str = memio.string_v(&st);\n"
" let view: str = memio.string(&st);\n"
" if (view.len != 10) { return 93; };\n"
" if (view[0] != 49u8) { return 94; };\n"
" if (view[1] != 32u8) { return 95; };\n"
@@ -209,7 +200,7 @@ static const struct row rows[] = {
"};\n",
64,
STAGE_CS, 0 },
{ "vfprintfln_basic",
{ "fprintfln_basic",
"package main;\n"
"import os;\n"
"import fmt;\n"
@@ -217,16 +208,16 @@ static const struct row rows[] = {
"import memio;\n"
"export fn main() i32 = {\n"
" let buf: [16]u8;\n"
" let st: memio.stream = memio.fixed_vstream(buf[0:16]);\n"
" let vs: io.vstream = &st.vt;\n"
" let wr = fmt.vfprintfln(vs, \"x={}\", 7i64);\n"
" let st: memio.stream = memio.fixed(buf[0:16]);\n"
" let vs: io.stream = &st.vt;\n"
" let wr = fmt.fprintfln(vs, \"x={}\", 7i64);\n"
" let nw: size = 0;\n"
" match (wr) {\n"
" case let n: size => { nw = n; };\n"
" case io.error => { return 91; };\n"
" };\n"
" if (nw != 4: size) { return 92; };\n"
" let view: str = memio.string_v(&st);\n"
" let view: str = memio.string(&st);\n"
" if (view.len != 4) { return 93; };\n"
" if (view[0] != 120u8 || view[1] != 61u8) { return 94; };\n"
" if (view[2] != 55u8 || view[3] != 10u8) { return 95; };\n"
@@ -241,7 +232,7 @@ static const struct row rows[] = {
"import io;\n"
"export fn main() i32 = {\n"
" let buf: [16]u8;\n"
" let r = fmt.vbsprintf(buf[0:16], \"v={}\", 42i64);\n"
" let r = fmt.bsprintf(buf[0:16], \"v={}\", 42i64);\n"
" let view: str = \"\";\n"
" match (r) {\n"
" case let s: str => { view = s; };\n"
@@ -261,7 +252,7 @@ static const struct row rows[] = {
"import fmt;\n"
"import io;\n"
"export fn main() i32 = {\n"
" let view: str = fmt.vasprintf(\"hello={}\", 9i64);\n"
" let view: str = fmt.asprintf(\"hello={}\", 9i64);\n"
" if (view.len != 7) { return 90; };\n"
" if (view[0] != 104u8 || view[1] != 101u8 || view[2] != 108u8) { return 91; };\n"
" if (view[3] != 108u8 || view[4] != 111u8) { return 92; };\n"

View File

@@ -34,7 +34,7 @@ static const char *modules[] = {
* lib/os/os.ww, and lib/strings/strings.ww moved off this list:
* each has cross-module type refs that only resolve once the
* driver concatenates `use`d modules. bufio / fmt graduated to
* io.stream-based sinks (*io.stream, io.closed, io.eof); lib/os
* io.stream-based sinks (io.stream = *io.vtable, io.eof, io.error); lib/os
* carries time.instant in filestat post-Commit B;
* lib/strings.iterator + lib/strings.next reference utf8.decoder
* / utf8.done; lib/bytes.tokenize references os.assert +