diff --git a/lib/bufio/bufio.ww b/lib/bufio/bufio.ww index f11ae0b9..a6ae26e4 100644 --- a/lib/bufio/bufio.ww +++ b/lib/bufio/bufio.ww @@ -10,21 +10,13 @@ // ([]u8 | io.eof | io.closed | overflow) // bufio.scanline (s: *scanner) (str | io.eof | io.closed | overflow) // -// bufio.init (b: *bstream, src: *io.stream, rbuf: []u8, wbuf: []u8) void -// bufio.flush (b: *bstream) (void | io.closed) -// bufio.unread (b: *bstream, buf: []u8) void +// bufio.init (b: *stream, src: *io.stream, rbuf: []u8, wbuf: []u8) void +// bufio.flush (b: *stream) (void | io.closed) +// bufio.unread (b: *stream, buf: []u8) void // bufio.isbuffered (s: *io.stream) bool // // Divergence from Hare: // -// • Hare's `bufio::stream` (ref/hare/bufio/stream.ha:27) becomes -// `bufio.bstream` here. Two modules can't both `export type -// stream` under ww's flat-scope module concat — `io.stream` -// is already taken. Filed as a compiler followup -// (cross-module type collision, sibling of the `mod.mod` -// use_alias fix); graduate to `bufio.stream` once that lands. -// Same precedent as `memio.state` (not `stream`). -// // • Hare returns the scanner / stream by value; ww cgen can't // return structs wider than 16B by value yet, so `newscanner` // and `init` are out-parameter shaped. Same workaround @@ -33,21 +25,21 @@ // • The scanner's read buffer is held flat as `(ptr, cap)` rather // than a `[]u8` field; the scanner predates struct-held slice // support and is wired through scanbyte/scantok/scanline. The -// new bstream writer half uses slice-typed `rbuf` / `wbuf` +// new stream writer half uses slice-typed `rbuf` / `wbuf` // fields directly — chained dot through a struct slice field // works after task #6. // // • Hare's `bufio::stream` discriminates r-only / w-only / r+w // via three different vtable singletons (vtable_r, vtable_w, // vtable_rw); ww's [[io.stream]] vtable always carries all -// three callbacks, so bstream always installs `bread` / +// three callbacks, so stream always installs `bread` / // `bwrite` / `bclose`. A zero-length rbuf or wbuf makes the // matching callback degenerate (rbuf=[]: bread short-circuits // to io.eof; wbuf=[]: bwrite passes through to src). // // • Hare's `init` also takes a `flag` argument carrying // MANAGED_HANDLE / MANAGED_RDBUF / MANAGED_WRBUF ownership -// bits; bstream never owns its buffers or src, so the +// bits; stream never owns its buffers or src, so the // `flags` field and the init-time argument are dropped // wholesale. The Hare `flush: []u8` byte-set is preserved — // [[init]] seeds it to `['\n']` (line buffering, matching @@ -64,11 +56,11 @@ // on the call that would have read them. Hare's EOF_GREEDY mode // isn't shipped (no caller needs it yet). // -// Owning model: caller owns the scanner state, the bstream state, +// Owning model: caller owns the scanner state, the stream state, // the byte buffers, and the source stream. `finish` doesn't free // the buffer and doesn't close src; it's a no-op today but stays // on the surface so callers don't churn when bufio grows internal -// allocations. The bstream vtable `close` callback flushes pending +// allocations. The stream vtable `close` callback flushes pending // writes and forwards close to src; it does not free rbuf / wbuf. // // let mem: memio.state; @@ -80,7 +72,7 @@ // match (bufio.scanline(&sc)) { ... }; // bufio.finish(&sc); // -// let b: bufio.bstream; +// let b: bufio.stream; // let rbuf: [256]u8; // let wbuf: [128]u8; // bufio.init(&b, src, rbuf[0:256], wbuf[0:128]); @@ -243,19 +235,19 @@ export fn scanline(s: *scanner) (str | io.eof | io.closed | overflow) = { }; }; -// bstream — buffered read+write over an underlying *io.stream. +// stream — buffered read+write over an underlying *io.stream. // -// `vtable` is the first field so a `*bstream` is castable to an +// `vtable` is the first field so a `*stream` is castable to an // `*io.stream` via address-of-field (`&b.vtable`). Higher layers // (fmt.fprint, scanner, …) only see the io.stream view; bufio -// recovers the outer bstream by casting the dispatch arg back to -// `*bstream` inside the bread/bwrite/bclose callbacks. +// recovers the outer stream by casting the dispatch arg back to +// `*stream` inside the bread/bwrite/bclose callbacks. // // rbuf[rstart..rend] is pending read data; wbuf[0..wend] is pending // write data. rbuf or wbuf may be zero-length: read-empty makes // bread return io.eof immediately, write-empty makes bwrite a // pass-through to src (uses src.write directly, no buffering). -export type bstream = struct { +export type stream = struct { vtable: io.stream, src: *io.stream, rbuf: []u8, @@ -268,9 +260,9 @@ export type bstream = struct { // init — wire `b` over `src` with caller-supplied buffers. Both // rbuf and wbuf may be empty slices; the corresponding direction -// degenerates (see [[bstream]]). The flush byte-set defaults to +// degenerates (see [[stream]]). The flush byte-set defaults to // "\n" (line-buffered writes); [[setflush]] swaps it. -export fn init(b: *bstream, src: *io.stream, rbuf: []u8, wbuf: []u8) void = { +export fn init(b: *stream, src: *io.stream, rbuf: []u8, wbuf: []u8) void = { b.vtable.ctx = b: *void; b.vtable.read = bread; b.vtable.write = bwrite; @@ -290,14 +282,14 @@ export fn init(b: *bstream, src: *io.stream, rbuf: []u8, wbuf: []u8) void = { // appearing in a write payload triggers an automatic flush after // the write copies into wbuf. Mirrors Hare's `setflush` // (ref/hare/bufio/stream.ha:128). -export fn setflush(b: *bstream, bs: []u8) void = { +export fn setflush(b: *stream, bs: []u8) void = { b.flush = bs; }; // flush — drain any pending wbuf data to src. Hare returns // `(void | io::error)`; ww's io.stream write-side error channel // is `io.closed` alone, so the return shape narrows. -export fn flush(b: *bstream) (void | io.closed) = { +export fn flush(b: *stream) (void | io.closed) = { if (b.wend == 0) { return; }; let off: i32 = 0; for (off < b.wend) { @@ -324,7 +316,7 @@ export fn flush(b: *bstream) (void | io.closed) = { // region (rstart >= buf.len); Hare aborts on overflow, ww does the // same via rt_abort. Mirrors Hare's `stream_unread` // (ref/hare/bufio/stream.ha:164). -export fn unread(b: *bstream, buf: []u8) void = { +export fn unread(b: *stream, buf: []u8) void = { if (b.rstart < buf.len) { rtabort("bufio.unread: more data than rbuf has room for"); }; @@ -336,7 +328,7 @@ export fn unread(b: *bstream, buf: []u8) void = { b.rstart -= buf.len; }; -// isbuffered — true when `s` is a [[bufio.bstream]]'s embedded +// isbuffered — true when `s` is a [[bufio.stream]]'s embedded // vtable. Hare's discriminator is callback identity // (ref/hare/bufio/stream.ha:179); we match the shape directly. The // read or write callback being bread / bwrite is sufficient (close @@ -350,7 +342,7 @@ export fn isbuffered(s: *io.stream) bool = { // ---- vtable callbacks ------------------------------------------------ fn bread(s: *io.stream, buf: []u8) (i32 | io.eof | io.closed) = { - let b: *bstream = s.ctx: *bstream; + let b: *stream = s.ctx: *stream; // No read buffer configured: surface eof immediately rather // than punch through to src (callers asked for a write-only // stream, reads against it are a misuse). @@ -380,7 +372,7 @@ fn bread(s: *io.stream, buf: []u8) (i32 | io.eof | io.closed) = { }; fn bwrite(s: *io.stream, buf: []u8) (i32 | io.closed) = { - let b: *bstream = s.ctx: *bstream; + let b: *stream = s.ctx: *stream; // No write buffer configured: pass through to src directly. if (b.wbuf.len == 0) { return io.write(b.src, buf); }; // Scan the write payload for any byte present in b.flush — a @@ -435,7 +427,7 @@ fn bwrite(s: *io.stream, buf: []u8) (i32 | io.closed) = { }; fn bclose(s: *io.stream) (void | io.closed) = { - let b: *bstream = s.ctx: *bstream; + let b: *stream = s.ctx: *stream; let r: (void | io.closed) = flush(b); match (r) { case void => { }; diff --git a/lib/bufio/bufiotest.ww b/lib/bufio/bufiotest.ww index 1fe9efe8..73c0c5b9 100644 --- a/lib/bufio/bufiotest.ww +++ b/lib/bufio/bufiotest.ww @@ -3,7 +3,7 @@ // The scanner @tests enumerate parallel `[N]T` arrays of inputs and // expectations, then iterate one body across them. Parallel arrays // (rather than `[N]struct{...}`) match the same cgen workaround -// memiotest leans on. The bstream @tests are one scenario per fn +// memiotest leans on. The stream @tests are one scenario per fn // (the ww-stdlib idiom): the "table" is the fn list in main, not // a row array. @@ -402,15 +402,15 @@ fn closedstream(s: *io.stream) void = { bufio.finish(&sc); }; -// ---- bstream init + flush round-trip --------------------------------- +// ---- stream init + flush round-trip --------------------------------- -@test fn bstreamsmallwrite() void = { +@test fn streamsmallwrite() void = { let raw: [16]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:16]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [8]u8; let wb: [8]u8; bufio.init(&b, &m, rb[0:8], wb[0:8]); @@ -438,13 +438,13 @@ fn closedstream(s: *io.stream) void = { // ---- write larger than wbuf → auto-flush ----------------------------- -@test fn bstreamautoflush() void = { +@test fn streamautoflush() void = { let raw: [32]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:32]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:4], wb[0:4]); @@ -478,13 +478,13 @@ fn closedstream(s: *io.stream) void = { // the payload contains any byte from b.flush. No setflush call — // this exercises the default. Mirrors Hare's flag::NONE default // (ref/hare/bufio/stream.ha:75 + 100). -@test fn bstreamlineflush() void = { +@test fn streamlineflush() void = { let raw: [32]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:32]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [16]u8; bufio.init(&b, &m, rb[0:4], wb[0:16]); @@ -520,13 +520,13 @@ fn closedstream(s: *io.stream) void = { // to drain after every write is a manual flush call. Setflush to // an empty byte-set first so the default '\n' detector doesn't // shadow what we're testing. -@test fn bstreamflushonwrite() void = { +@test fn streamflushonwrite() void = { let raw: [32]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:32]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [16]u8; bufio.init(&b, &m, rb[0:4], wb[0:16]); @@ -563,15 +563,15 @@ fn closedstream(s: *io.stream) void = { if (raw[2] != 65u8) { fail(); }; }; -// ---- isbuffered: bstream → true, plain memio → false ----------------- +// ---- isbuffered: stream → true, plain memio → false ----------------- -@test fn bstreamisbuffered() void = { +@test fn streamisbuffered() void = { let raw: [8]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:8]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:4], wb[0:4]); @@ -582,7 +582,7 @@ fn closedstream(s: *io.stream) void = { // ---- bread + unread: pushed-back bytes come out first ---------------- -@test fn bstreamunread() void = { +@test fn streamunread() void = { let raw: [8]u8; let n: i32 = putstr("ABCDEFGH", raw[0:8], 0); @@ -590,7 +590,7 @@ fn closedstream(s: *io.stream) void = { let m: io.stream; memio.fixed(&mem, &m, raw[0:n]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [8]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:8], wb[0:4]); @@ -634,14 +634,14 @@ fn closedstream(s: *io.stream) void = { if (out[3] != 71u8) { fail(); }; // 'G' }; -// ---- scanner over a bstream-wrapped src: pre-read unread + scanline -- +// ---- scanner over a stream-wrapped src: pre-read unread + scanline -- -// Push three bytes into a freshly-init'd bstream (rstart=rend=rbuf.len +// Push three bytes into a freshly-init'd stream (rstart=rend=rbuf.len // post-init, per Hare bufio/stream.ha:101 — the unread budget before // the first read is the full rbuf), then scan a line through the -// bstream. The scanner pulls "XYZ" from rbuf first, refills "hello\n" +// stream. The scanner pulls "XYZ" from rbuf first, refills "hello\n" // from src, and scanline returns "XYZhello". -@test fn bstreamscannerunread() void = { +@test fn streamscannerunread() void = { let raw: [16]u8; let n: i32 = putstr("hello\n", raw[0:16], 0); @@ -649,7 +649,7 @@ fn closedstream(s: *io.stream) void = { let m: io.stream; memio.fixed(&mem, &m, raw[0:n]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [16]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:16], wb[0:4]); @@ -679,13 +679,13 @@ fn closedstream(s: *io.stream) void = { // ---- flush() on empty wbuf is a no-op -------------------------------- -@test fn bstreamflushempty() void = { +@test fn streamflushempty() void = { let raw: [8]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:8]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:4], wb[0:4]); @@ -700,16 +700,16 @@ fn closedstream(s: *io.stream) void = { // ---- bclose drains pending wbuf then forwards close to src ---------- -// io.close on the bstream vtable must run the flush path (Hare +// io.close on the stream vtable must run the flush path (Hare // stream.ha:188-202). Buffer two bytes, route io.close through the -// bstream, and confirm both reach src. -@test fn bstreamcloseflushes() void = { +// stream, and confirm both reach src. +@test fn streamcloseflushes() void = { let raw: [8]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:8]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [4]u8; bufio.init(&b, &m, rb[0:4], wb[0:4]); @@ -741,13 +741,13 @@ fn closedstream(s: *io.stream) void = { // setflush installs a fresh byte-set (not just clears it). Use ' ' // (space) as the trigger; "ab cd" must flush at the space, leaving // "cd" pending. -@test fn bstreamsetflushcustom() void = { +@test fn streamsetflushcustom() void = { let raw: [16]u8; let mem: memio.state; let m: io.stream; memio.fixed(&mem, &m, raw[0:16]); - let b: bufio.bstream; + let b: bufio.stream; let rb: [4]u8; let wb: [16]u8; bufio.init(&b, &m, rb[0:4], wb[0:16]); @@ -780,15 +780,15 @@ export fn main() i32 = { signalled = 6; closedsource(); signalled = 7; boundarycases(); signalled = 8; multifill(); - signalled = 9; bstreamsmallwrite(); - signalled = 10; bstreamautoflush(); - signalled = 11; bstreamlineflush(); - signalled = 12; bstreamflushonwrite(); - signalled = 13; bstreamisbuffered(); - signalled = 14; bstreamunread(); - signalled = 15; bstreamscannerunread(); - signalled = 16; bstreamflushempty(); - signalled = 17; bstreamcloseflushes(); - signalled = 18; bstreamsetflushcustom(); + signalled = 9; streamsmallwrite(); + signalled = 10; streamautoflush(); + signalled = 11; streamlineflush(); + signalled = 12; streamflushonwrite(); + signalled = 13; streamisbuffered(); + signalled = 14; streamunread(); + signalled = 15; streamscannerunread(); + signalled = 16; streamflushempty(); + signalled = 17; streamcloseflushes(); + signalled = 18; streamsetflushcustom(); return 0; }; diff --git a/lib/log/log.ww b/lib/log/log.ww index ea1a0f12..1354e095 100644 --- a/lib/log/log.ww +++ b/lib/log/log.ww @@ -107,7 +107,7 @@ export type logger = struct { // stdlogger — concrete logger forwarding to a `*io.stream` sink. // First-field embed: `&sl.logger` yields a `*logger` (same shape as -// bufio.bstream over its embedded io.stream vtable). The vtable +// bufio.stream over its embedded io.stream vtable). The vtable // callback recovers the outer stdlogger by casting the dispatch arg // back to `*stdlogger`. export type stdlogger = struct { diff --git a/test/wcc/696_modtype_leaf_collision.c b/test/wcc/696_modtype_leaf_collision.c index 12b6b84f..2364836a 100644 --- a/test/wcc/696_modtype_leaf_collision.c +++ b/test/wcc/696_modtype_leaf_collision.c @@ -15,8 +15,8 @@ * * Fixtures live in test/wcc/data/modcollision/. mod1/mod1.ww and * mod2/mod2.ww are deliberately *new* source files so the test - * doesn't lean on bufio's `bstream` workaround (still in place - * until #21 lands). + * stays self-contained — independent of lib/bufio (now that + * `bufio.stream` and `io.stream` coexist on the post-#15 surface). */ #include #include