lib/io: port mode/whence/error + reader/writer/closer fn-aliases (#94 fold-d)

New lib/io/types.ww mirrors ref/hare/io/types.ha — the surrounding
port that lives alongside the existing lib/io/io.ww (pre-vtable
stream + eof + underread). Hare splits the same way (stream.ha +
types.ha share `module io`); ww does the equivalent via dir-enum.

Each type cites Hare per CLAUDE.md rule 9:
  - mode    (enum u8)  — ref/hare/io/types.ha:29-34. RDWR=3 (not
                         Hare's `READ | WRITE`) because ww enum-value
                         positions don't fold expressions; bitfield
                         value SSoT preserved, divergence inline.
  - whence  (enum i32) — ref/hare/io/types.ha:37-41. Hare leaves the
                         underlying implicit; ww requires one. i32
                         matches the `off` type fold-e wires in.
  - error              — ref/hare/io/types.ha:11. Hare spreads
                         `errors::error`; lib/errors not ported, so
                         the union carries the two tags observable
                         in this fold: underread (from io.ww) and
                         the predeclared `nomem` (#29, type.c:72 /
                         check.ww:78). NOT redefined here.
  - reader/writer/closer — ref/hare/io/types.ha:46/51/55. EOF=eof
                           (not Hare's `done` singleton) per #93
                           and the io.ww:8 rationale. `*stream`
                           forward-refs the existing pre-vtable
                           struct in io.ww; same cross-file pattern
                           Hare uses.

Drew signoff (this fold only): seeker, copier, strerror, and the
EOF=done singleton DEFERRED to fold-e — they need the `handle` sum
and #93's done landing. Hare's `_unsafe` carve-out unaffected.

eof / underread / stream re-used from io.ww (NOT redefined); io.ww
keeps the pre-vtable struct unchanged, ditto its WHY-comments.

Combined.ww regen (#110): selfhost/cmd/{w6c,wwdump}/main.combined.ww
auto-pulled the new types.ww via dir-enum (+52 lines each, same
package io). Makefile dep lines for wwdump_ww + w6c_ww add the new
source so editing it triggers rebuild.

Probe: test/wcc/768_io_types_run.c — 5 rows × 2 stages = 10
invocations. Pins enum value/underlying + the three fn-type aliases
at the param slot. Both siblings filed inline in the probe header:

  - #189 wwstage `let r: io.reader = fn_name;` bails "let: not
    assignable". cstage accepts. Param + struct-field paths work
    in both stages, so io vtable port is unblocked. Probe uses
    the alias only at the param slot.
  - #190 wwstage match-arm on cross-module variant tag bails
    "case: not a variant of scrutinee (io.eof | io.error)". Likely
    same family as #178. cstage accepts. Probe uses `is` instead
    of `match` for the variant gate.

make test: 201/201 (was 200; +1 from 768). 990-997 byte-id +
combined_ww_fresh + sizelint all green.
This commit is contained in:
2026-05-28 21:58:06 +09:00
parent c07f96fc35
commit 635429bef8
5 changed files with 426 additions and 2 deletions

51
lib/io/types.ww Normal file
View File

@@ -0,0 +1,51 @@
// types — error union, mode/whence enums, reader/writer/closer
// fn-type aliases. Project #94 fold-1 step (d) (drew Fold D).
//
// Hare splits the io module across stream.ha + types.ha and ww does
// the same: lib/io/io.ww owns the (pre-vtable) `stream`, `eof`, and
// `underread` shapes; this file owns the surrounding port. Both
// files share `package io;` so forward refs (e.g. reader → stream)
// resolve via the dir-enum concat order.
//
// Deferrals (drew-signed): `handle`, `seeker`, `copier`, `strerror`
// land with fold-e (need the `handle` sum). Hare's `EOF = done`
// stays as `io.eof` until the `done` singleton ships (#93).
package io;
// ref/hare/io/types.ha:29-34. RDWR is spelled `3` rather than Hare's
// `READ | WRITE` because the ww parser doesn't fold expressions in
// enum value positions; the value SSoT stays the same bitfield.
export type mode = enum u8 {
NONE = 0,
READ = 1,
WRITE = 2,
RDWR = 3,
};
// ref/hare/io/types.ha:37-41. Hare leaves the underlying implicit;
// ww requires one. i32 matches the off type that fold-e will plug
// into the seeker signature.
export type whence = enum i32 {
SET = 0,
CUR = 1,
END = 2,
};
// ref/hare/io/types.ha:11 spreads `errors::error` into the union;
// lib/errors isn't ported yet, so the union carries only the tags
// observable in this fold — `underread` (from io.ww) and the
// predeclared `nomem` (#29, type.c:72 / check.ww:78).
export type error = !(underread | nomem);
// ref/hare/io/types.ha:46. `eof` (not Hare's `done`) per the io.ww:8
// rationale; lifts to `done` with #93. `*stream` forward-refs the
// pre-vtable struct in io.ww — same cross-file pattern Hare uses.
export type reader = fn(s: *stream, buf: []u8) (size | eof | error);
// ref/hare/io/types.ha:51. No `const` qualifier — ww has none, and
// lib/io/io.ww:30 + lib/sort/sort.ww:18 drop it the same way.
export type writer = fn(s: *stream, buf: []u8) (size | error);
// ref/hare/io/types.ha:55.
export type closer = fn(s: *stream) (void | error);