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

64 lines
3.0 KiB
Markdown

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_prefix``trimprefix`, `next_token``nexttoken`).
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.