From e5379848de3e0c1f386a637b347d784b087e16ac Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sat, 8 Aug 2026 16:46:48 +0900 Subject: [PATCH] lib: split io empty stream into empty.ww per ref/hare/io/empty.ha Pure file-boundary move of lib/io/stream.ww's single 'empty stream' banner section (_empty_read, _empty_write, _empty_vt, empty) into lib/io/empty.ww, mirroring ref/hare/io/empty.ha. No code, name, signature, or behavior change. Comment-only adjustments: the banner line is deleted (the file name carries it); the moved block's 'Lives in stream.ww' self-reference now says empty.ww; stream.ww's head drops its empty bullet (content duplicated by empty.ww's own comments); io.ww's ownership map gains the empty.ww line; types.ww's 'three files' count becomes four. empty.ww needs no imports (package io types only). Makefile: lib/io/empty.ww added beside every lib/io/stream.ww occurrence (WWFIXTURE_SRC line 75; w6c_ww/wwdump_ww bootstrap prereq lists at lines 184/204). lib/io has no _test.ww, so no LIBRARY_TESTS or byteid-roster change; byteid coverage rides the bootstrap gates. Validation: out/bin/w6c lib/io/io.ww (standalone contract) exit 0; importer tests green: bufio 26, memio 11, log 11, getopt 12 (calls io.empty), fmt 49. --- Makefile | 6 +++--- lib/io/empty.ww | 33 +++++++++++++++++++++++++++++++++ lib/io/io.ww | 7 ++++--- lib/io/stream.ww | 37 ------------------------------------- lib/io/types.ww | 2 +- 5 files changed, 41 insertions(+), 44 deletions(-) create mode 100644 lib/io/empty.ww diff --git a/Makefile b/Makefile index 90fd794f..4f93dba5 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ WWFIXTURE_SRC = cmd/wwfixture/wwfixture.ww \ lib/encoding/hex/hex.ww lib/encoding/utf8/utf8.ww \ lib/endian/endian.ww lib/errors/errors.ww lib/fmt/fmt.ww \ lib/fnmatch/fnmatch.ww lib/hash/hash.ww \ - lib/io/io.ww lib/io/stream.ww lib/io/types.ww \ + lib/io/empty.ww lib/io/io.ww lib/io/stream.ww lib/io/types.ww \ lib/math/floats.ww lib/math/math.ww lib/memio/memio.ww \ lib/os/os.ww lib/rt/malloc.ww \ lib/strconv/decimal.ww lib/strconv/ftos.ww \ @@ -181,7 +181,7 @@ $(BIN)/wwdump_ww: selfhost/cmd/wwdump/main.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgenexpr.ww \ selfhost/cmd/wcc/cgenstmt.ww selfhost/cmd/wcc/cgenutil.ww \ selfhost/cmd/wcc/cgendecl.ww \ - lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww lib/strconv/strconv.ww lib/strconv/stof_data.ww lib/strconv/decimal.ww lib/strconv/stof.ww lib/strconv/ftos_data.ww lib/strconv/ftos.ww lib/strings/strings.ww lib/bytes/bytes.ww lib/encoding/utf8/utf8.ww lib/ascii/ascii.ww lib/errors/errors.ww lib/io/io.ww lib/io/stream.ww lib/io/types.ww lib/math/floats.ww lib/math/math.ww lib/memio/memio.ww lib/types/types.ww \ + lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww lib/strconv/strconv.ww lib/strconv/stof_data.ww lib/strconv/decimal.ww lib/strconv/stof.ww lib/strconv/ftos_data.ww lib/strconv/ftos.ww lib/strings/strings.ww lib/bytes/bytes.ww lib/encoding/utf8/utf8.ww lib/ascii/ascii.ww lib/errors/errors.ww lib/io/empty.ww lib/io/io.ww lib/io/stream.ww lib/io/types.ww lib/math/floats.ww lib/math/math.ww lib/memio/memio.ww lib/types/types.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) @mkdir -p $(WWBUILD)/wwdump_ww @@ -201,7 +201,7 @@ $(BIN)/w6c_ww: selfhost/cmd/w6c/main.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgenexpr.ww \ selfhost/cmd/wcc/cgenstmt.ww selfhost/cmd/wcc/cgenutil.ww \ selfhost/cmd/wcc/cgendecl.ww \ - lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww lib/strconv/strconv.ww lib/strconv/stof_data.ww lib/strconv/decimal.ww lib/strconv/stof.ww lib/strconv/ftos_data.ww lib/strconv/ftos.ww lib/strings/strings.ww lib/bytes/bytes.ww lib/encoding/utf8/utf8.ww lib/ascii/ascii.ww lib/errors/errors.ww lib/io/io.ww lib/io/stream.ww lib/io/types.ww lib/math/floats.ww lib/math/math.ww lib/memio/memio.ww lib/types/types.ww \ + lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww lib/strconv/strconv.ww lib/strconv/stof_data.ww lib/strconv/decimal.ww lib/strconv/stof.ww lib/strconv/ftos_data.ww lib/strconv/ftos.ww lib/strings/strings.ww lib/bytes/bytes.ww lib/encoding/utf8/utf8.ww lib/ascii/ascii.ww lib/errors/errors.ww lib/io/empty.ww lib/io/io.ww lib/io/stream.ww lib/io/types.ww lib/math/floats.ww lib/math/math.ww lib/memio/memio.ww lib/types/types.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) @mkdir -p $(WWBUILD)/w6c_ww diff --git a/lib/io/empty.ww b/lib/io/empty.ww new file mode 100644 index 00000000..f8697f25 --- /dev/null +++ b/lib/io/empty.ww @@ -0,0 +1,33 @@ +// ref/hare/io/empty.ha:4-17. +// +// Hare uses `const _empty_vt: vtable = { ... }` + `const empty: *stream`. +// ww can't const-init a vtable struct with fn-ptr fields (#118), so the +// vtable is a module-level `let` and [[empty]] is a function that wires +// the fn-ptr slots on every call and returns the stream pointer. +// Single-assignment on the same words: idempotent under re-entry. +// Lives in empty.ww (not io.ww) so io.ww stays standalone without +// referencing the cross-file vtable/reader/writer types. + +package io; + +fn _empty_read(s: stream, buf: []u8) (size | eof | error) = { + let e: eof; + return e; +}; + +fn _empty_write(s: stream, buf: []u8) (size | error) = { + return buf.len: size; +}; + +let _empty_vt: vtable; + +// empty — a stream that discards all writes (returning their size) and +// returns EOF on every read. Mirrors ref/hare/io/empty.ha:13. +// #118: const vtable init with fn-ptr fields is unwired (emit_struct_data +// needs a two-pass reloc extension, node_fnptr_sym reusable). Using a +// mutable let + per-call wiring until #118 lands. +export fn empty() stream = { + _empty_vt.reader = (&_empty_read): *reader; + _empty_vt.writer = (&_empty_write): *writer; + return &_empty_vt; +}; diff --git a/lib/io/io.ww b/lib/io/io.ww index 49f633f5..9a9870b3 100644 --- a/lib/io/io.ww +++ b/lib/io/io.ww @@ -6,9 +6,10 @@ // tagged unions instead of errno-style integer sentinels. // // This file owns the eof / underread variant tags; lib/io/stream.ww -// owns the `vtable` + `stream` + read/write/close dispatchers and the -// [[empty]] singleton, and lib/io/types.ww owns the error union, -// mode/whence enums, and the reader/writer/closer fn-type aliases. +// owns the `vtable` + `stream` + read/write/close dispatchers, +// lib/io/empty.ww owns the [[empty]] singleton, and lib/io/types.ww +// owns the error union, mode/whence enums, and the reader/writer/ +// closer fn-type aliases. // #94 fold-eFinal collapsed the pre-vtable `stream` struct + `closed` // tag into the single vtable surface; the dispatchers are read/write/ // close (over `stream`), final over `handle` at io fold-2 (#5). diff --git a/lib/io/stream.ww b/lib/io/stream.ww index c4922b9c..496866ef 100644 --- a/lib/io/stream.ww +++ b/lib/io/stream.ww @@ -21,9 +21,6 @@ // public `read`/`write`/`close`; ww has no `handle` yet // (io fold-2, #5), so the dispatchers ARE the public // surface and grow the `handle` match when #5 lands. -// empty the discard+EOF stream (ref/hare/io/empty.ha:13). Lives -// here rather than io.ww so io.ww remains a standalone -// frontend input with no cross-file type references. // // Deferrals (drew-signed): `seeker` lands with io fold-2 (#5) once `off` // + `whence` plug into the signature. Hare's `?`-propagating `close` @@ -186,37 +183,3 @@ export fn seek(h: handle, off: off, w: whence) (off | error) = { export fn tell(h: handle) (off | error) = { return seek(h, 0, whence.CUR); }; - -// ---- empty stream ------------------------------------------------------- -// -// ref/hare/io/empty.ha:4-17. -// -// Hare uses `const _empty_vt: vtable = { ... }` + `const empty: *stream`. -// ww can't const-init a vtable struct with fn-ptr fields (#118), so the -// vtable is a module-level `let` and [[empty]] is a function that wires -// the fn-ptr slots on every call and returns the stream pointer. -// Single-assignment on the same words: idempotent under re-entry. -// Lives in stream.ww (not io.ww) so io.ww stays standalone without -// referencing the cross-file vtable/reader/writer types. - -fn _empty_read(s: stream, buf: []u8) (size | eof | error) = { - let e: eof; - return e; -}; - -fn _empty_write(s: stream, buf: []u8) (size | error) = { - return buf.len: size; -}; - -let _empty_vt: vtable; - -// empty — a stream that discards all writes (returning their size) and -// returns EOF on every read. Mirrors ref/hare/io/empty.ha:13. -// #118: const vtable init with fn-ptr fields is unwired (emit_struct_data -// needs a two-pass reloc extension, node_fnptr_sym reusable). Using a -// mutable let + per-call wiring until #118 lands. -export fn empty() stream = { - _empty_vt.reader = (&_empty_read): *reader; - _empty_vt.writer = (&_empty_write): *writer; - return &_empty_vt; -}; diff --git a/lib/io/types.ww b/lib/io/types.ww index 1c365dc2..90bd33e5 100644 --- a/lib/io/types.ww +++ b/lib/io/types.ww @@ -6,7 +6,7 @@ // the same: lib/io/io.ww owns the `eof` and `underread` tags; // lib/io/stream.ww owns the vtable surface (`vtable`, `stream`, // `read`/`write`/`close` dispatch); this file owns the surrounding -// port. The three files share `package io;` so cross-file refs +// port. The four files share `package io;` so cross-file refs // resolve via the dir-enum concat order (io.ww < stream.ww < types.ww // — `stream` lands before the reader/writer/closer aliases below). //