Files
ww/lib/CLAUDE.md
Hojun-Cho e16634baec lib: add missing Hare-stdlib functions (ascii/bytes/strings/path/endian)
ascii: valid, validstr, ispunct, isprint, iscntrl, isgraph, isblank,
strcasecmp.

bytes: hasprefix, hassuffix, rindex, rindexbyte, contains, reverse,
zero.

strings: rindex, sub, trimprefix, trimsuffix, ltrimbyte, rtrimbyte,
trimbyte. The byte-set trim is a single-byte subset of Hare's
`trim(input, exclude: rune...)`; no variadic ABI yet.

path: dirname, basename, extension, join. Owned-str returns where the
result isn't a borrowed view of the input (join).

endian: full Hare table — be/le get/put for u16/u32/u64 plus the
network-order htonu/ntohu pair extended to 32/64.

lib/CLAUDE.md rewritten to reflect the post-graduation policy
(tagged-union returns, owned-str returns, plan9 names, documented
deviations for non-graduating modules).

Makefile picks up lib/ascii and lib/fmt as wwdump_ww / w6c_ww deps so
lib-only edits regenerate the affected binaries.
2026-05-13 04:03:55 +09:00

3.0 KiB

lib/ — Hare-shaped standard library.

Scope: every lib/* directory except lib/ww/, which is the compiler frontend port and has its own rules (see lib/ww/CLAUDE.md).

Names mirror Hare. Before adding a function, find its counterpart in ref/hare/<module>/ and copy the name — drop Hare's underscores per plan 9 style (trim_prefixtrimprefix, next_tokennexttoken). Don't invent. Don't shorten further. Don't reorder parameters.

Signatures mirror Hare too, modulo:

  • Tagged-union returns are spelled with the ww ! error tag where Hare uses !void / !T, and indices use the underlying length type (i32 today, since str.len: i32). Example: strconv.stoi64(s: str, b: i32) (i64 | invalid | overflow) — same shape as Hare's; the base parameter is plain i32 rather than a base enum because cross-module mod.enumtype.VALUE chains miscompile in the cstage cgen. strconv exports def DEC: i32 = 10; etc. so callers say strconv.DEC and the Sdef path lowers to an immediate.

  • Owned-str returns. Where Hare returns const str into a thread-local static buffer (strconv.i64tos, strings.dup, strings.concat), ww allocates per call and the caller frees via os.free(r.ptr, r.len: u64). Mutating a module-level *u8 doesn't yet round-trip through the wwstage cgen, so the static- buffer shape isn't expressible today.

  • Variadic ABI doesn't land yet, so callers that Hare writes as fmt::println(42) are spelled fmt.println(strconv.i64tos(42, strconv.DEC)) for now. lib/fmt is intentionally print-string- only — no printf-family.

  • (str | rune)-style sum-typed parameters are split into typed pairs (strings.indexbyte for the byte case, strings.index for the slice case, etc.). The Hare public name byteindex will come back once the sum-typed parameter ABI lands.

Don't ship a richer surface than Hare has. A documented subset is fine; an extension, rename, or convenience-wrapper is not — callers should not bake the current subset shape into themselves.

Modules with intentional divergence:

  • lib/os and lib/net stay below the Hare abstraction — they are syscall wrappers, not the high-level io::handle / net::socket API. Use them as the foundation that lib/io and the buffered layers build on.
  • lib/io keeps the ww-specific stream struct (vtable of fn pointers, no closures, no methods). The Hare io::handle family needs language features we don't have yet.
  • lib/bufio and lib/sort will be redesigned to Hare's scanner / cmpfunc shapes; the present minimal forms are placeholders until then.
  • lib/time and lib/math ship only what callers need today; they're not aiming for parity yet.

When the compiler can express a Hare signature that's still in the ww-specific shape (e.g., once a module-level *u8 is mutable, the strconv *tos family graduates to static-buffer returns), graduate the module in one go — replace the current shape with the Hare shape and fix the callers. Don't keep both around.