lib: complete the parallel vstream surface to Hare value-return shape (#94 fold-eFinal prep)
The #94 Option-C vstream surface was left incomplete and structurally divergent from Hare: constructors heap-allocated and returned (X | nomem) or used out-params instead of Hare's by-value stack ownership; memio lacked reset/buffer/borrowedread; bufio's scanner was never ported to the vtable. This is the additive half of the eFinal collapse — OLD surface stays fully live; the destructive FLIP (delete OLD + drop _v + repoint) is the next commit. Reshape all constructors to VALUE-RETURN (field-by-field sret; the heap + nomem was an unnecessary crutch — wide slice-bearing struct return-by-value is byte-id-proven, cf 925_sret_struct_return_run). memio fixed/dynamic/ dynamicfrom, bufio init, log new now return the struct by value; the nomem is gone with the alloc that forced it. memio: unify the per-flavour ctx structs onto one `stream` (vt at offset 0); collapse fixed_string + dynamic_string into a single string() over the common header (bare-str return is the ratified rule-9 frombytes carve-out, cited at the site per ref/hare/memio/stream.ha:81); port reset/buffer/borrowedread as single fns over the header. bufio: collapse the EXISTING scanner subset (newscannerbuf/scanbyte/scanbytes/ scanline/finish + setflush/flush/unread/isbuffered) onto the vtable, with src now io.vstream so reads go through io.st_read. The Hare scanner functions ww never implemented (scanrune/scanstring-arbitrary-delim/readtok/readline/ auto-grow newscanner) are out of scope and deferred to #217 — eFinal is a collapse, not a feature expansion. Keep the explicit (&fn): *io.T casts on vtable-slot stores (cgen-neutral; avoids the #214 (X|void) over-acceptance surface; dropping the casts is a deferred #206 payoff gated on #214). Self-gate: 776 (memio) 18/18 and 778 (bufio) 27/27, every row carrying a cs.s == ww.s byte-id check — bufio/fmt/log are not compiler-embedded, so these rows are their only byte-id coverage. 779/781 stay STAGE_CS-only pending #209. Regen w6c+wwdump combined.ww (io+memio are the embedded modules).
This commit is contained in:
@@ -560,9 +560,10 @@ export fn fdprintfln_v(fd: i32, fmt: str, args: field...) (size | io.error) = {
|
||||
};
|
||||
|
||||
// ---- V-side compositions over the vfprint / vfprintf primitives.
|
||||
// Project #94 fold-e7. drew-approved bundle (memio.fixed_string /
|
||||
// memio.dynamic_string land alongside as direct enablers, not churn —
|
||||
// feedback_refactor_routing_same_class_drops); ken cs==ww mechanical
|
||||
// Project #94 fold-e7. drew-approved bundle (memio.string_v is the
|
||||
// collapsed single accessor over the common `stream` header — direct
|
||||
// enabler, not churn — feedback_refactor_routing_same_class_drops);
|
||||
// ken cs==ww mechanical
|
||||
// (additive only). eFinal (#50) collapses both surfaces and renames
|
||||
// `v` suffix off.
|
||||
//
|
||||
@@ -604,20 +605,18 @@ export fn vfprintfln(vs: io.vstream, fmt: str, args: field...) (size | io.error)
|
||||
|
||||
// vbsprintf — render into `buf` through memio.fixed_vstream; return
|
||||
// the str view of bytes actually written. Mirror fmt.bsprintf
|
||||
// (fmt.ww:839); nomem from fixed_vstream widens into io.error (Hare
|
||||
// wrappers.ha:42 returns `(const str | nomem)` directly — ww collapses
|
||||
// to (str | io.error) so the vfprintf path's io.error arm stays
|
||||
// uniform). Short writes surface as a prefix (memio.fixed contract,
|
||||
// vstream.ww:71 note).
|
||||
// (fmt.ww:839). memio.fixed_vstream now returns the `stream` BY VALUE
|
||||
// (fold-eFinal PREP, ref/hare/memio/stream.ha:46) — no alloc, no
|
||||
// `nomem` arm. The stream lives in this frame; `&st.vt` is the
|
||||
// io.vstream and `&st` the accessor handle. Hare wrappers.ha:42 returns
|
||||
// `(const str | nomem)`; ww collapses to (str | io.error) so the
|
||||
// vfprintf path's io.error arm stays uniform. Short writes surface as a
|
||||
// prefix (memio.fixed contract, vstream.ww fixedwrite note).
|
||||
export fn vbsprintf(buf: []u8, fmt: str, args: field...) (str | io.error) = {
|
||||
let r: (io.vstream | nomem) = memio.fixed_vstream(buf);
|
||||
let vs: io.vstream = nil: *io.vtable;
|
||||
match (r) {
|
||||
case let v: io.vstream => { vs = v; };
|
||||
case let nm: nomem => { let e: io.error = nm; return e; };
|
||||
};
|
||||
let st: memio.stream = memio.fixed_vstream(buf);
|
||||
let vs: io.vstream = &st.vt;
|
||||
match (vfprintf(vs, fmt, args...)) {
|
||||
case let n: size => { return memio.fixed_string(vs); };
|
||||
case let n: size => { return memio.string_v(&st); };
|
||||
case let e: io.error => return e;
|
||||
};
|
||||
};
|
||||
@@ -630,26 +629,26 @@ export fn vbsprintf(buf: []u8, fmt: str, args: field...) (str | io.error) = {
|
||||
// frees with `os.free(r.ptr, r.len: u64)` when r.len > 0; r.len == 0
|
||||
// is a no-op free (same shape strings.dup uses at strings.ww:70).
|
||||
// Shrink-to-fit rationale: memio.dynamic_vstream's cap doubles past
|
||||
// pos during growth (memio/vstream.ww:230); io.st_close frees the
|
||||
// cap-sized mapping. Returning memio.dynamic_string directly would
|
||||
// pos during growth (memio dynamicgrow_v); io.st_close frees the
|
||||
// cap-sized mapping. Returning memio.string_v directly would
|
||||
// leak the cap-vs-len slack (skip close) or dangle the view (close
|
||||
// first); the copy lets the caller free with r.len.
|
||||
export fn vasprintf(fmt: str, args: field...) str = {
|
||||
let out: str;
|
||||
out.ptr = nil;
|
||||
out.len = 0;
|
||||
let r: (io.vstream | nomem) = memio.dynamic_vstream();
|
||||
let vs: io.vstream = nil: *io.vtable;
|
||||
match (r) {
|
||||
case let v: io.vstream => { vs = v; };
|
||||
case nomem => { return out; };
|
||||
};
|
||||
// memio.dynamic_vstream returns the `stream` BY VALUE (fold-eFinal
|
||||
// PREP, ref/hare/memio/stream.ha:58) — no alloc, no `nomem` arm.
|
||||
// The stream lives in this frame across the vfprintf + close; the
|
||||
// heap-grown backing (st.ptr) is freed by io.st_close.
|
||||
let st: memio.stream = memio.dynamic_vstream();
|
||||
let vs: io.vstream = &st.vt;
|
||||
let wres: (size | io.error) = vfprintf(vs, fmt, args...);
|
||||
match (wres) {
|
||||
case let n: size => {};
|
||||
case let e: io.error => {};
|
||||
};
|
||||
let view: str = memio.dynamic_string(vs);
|
||||
let view: str = memio.string_v(&st);
|
||||
if (view.len == 0) {
|
||||
let cres: (void | io.error) = io.st_close(vs);
|
||||
match (cres) { case void => {}; case let e: io.error => {}; };
|
||||
|
||||
Reference in New Issue
Block a user