From 7ab080fe2ad6400a9aa94a188a41b0752e6b7a4c Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 9 Aug 2026 04:40:40 +0900 Subject: [PATCH] docs: rule len and cap as an i32 stability carve-out --- CLAUDE.md | 2 +- lib/CLAUDE.md | 2 +- lib/regex/whitebox_test.ww | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0ad71cbb..9cce77e2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ 6. ref/hare and ref/plan9front are read-only references — consult before inventing data shapes or syntax. Carve-out: the ww compiler frontend is ONE package `lib/ww/syntax/` (tok+lex+ast+sym+typ+parse), a deliberate Go-over-Hare departure modelled on Go's `cmd/compile/internal/syntax` rather than ref/hare/hare's `{ast,lex,parse}` split. Rationale: the split's only payoff is third-party reuse (an IDE wanting `ast` without the parser), which ww has zero of — its frontend is consumed by exactly one client, the `wcc` backend. Consolidating dissolves the cross-package export sprawl (a fn over an unexported sibling type re-triggers sep-build's check_exported_type). Rule 6/12 still bind the internal data shapes (AST kinds, token model, lexer/parser state mirror ref/hare/hare); only the module DECOMPOSITION collapses. The surviving export surface is `syntax`'s public API consumed by `wcc` (a small Hare-faithful set). Ref: USER-approved #74; spec .ai/rob-frontend-reorg.md (rob, drew2 fidelity-confirmed). 7. No workarounds. If a bug forces a workaround, STOP and report with a precise repro. Document any retained divergence at the site with a pointer to the filed task. Never silent. 8. Comments are WHY-only. Never narrate WHAT the code does — names carry the WHAT. Comment only non-obvious WHY: a constraint, a divergence from a reference, a citation to a filed task. -9. Hare-fidelity over convenience. No ad-hoc extensions, renames, or convenience wrappers in lib/. Cite ref/hare// for every signature ported. Carve-out: the Hare `_unsafe` suffix convention is dropped wholesale (ww is C/Plan-9-lineage, an unmanaged systems language — no GC, no "safe" baseline to be unsafe relative to). bytes→str is a pure reinterpret (`strings.frombytes`, renamed from Hare's `fromutf8_unsafe`); validation is opt-in via `utf8.validate(b)?` at the IO source, never wrapped per-construction. Rationale: ref/hare/strings/utf8.ha:10,22 — the suffix flags Hare's managed-bytes-safety axis, which ww doesn't have. The honest name (`frombytes`) reserves `fromutf8` for a future true validating helper. Carve-out: lib/ tests use Go's external-test-package idiom (`package _test;` + `import ;`), a sanctioned Go-over-Hare departure — ww hard-rejects self-import (full Go), and Hare's same-package `@test` colocation now has a ww analogue: in-package white-box `@test` files (`package ;`, colocated) are sanctioned alongside the external black-box `package _test;` split — Go's `foo`/`foo_test` model — now that the non-T `@test` drop landed (#6, harec check.c:3941, 08a76cf; #5 closed). Rule 5/9 binds lib/ *API* surface, not test-authoring style. Ref: Go `foo_test` convention; task #16. +9. Hare-fidelity over convenience. No ad-hoc extensions, renames, or convenience wrappers in lib/. Cite ref/hare// for every signature ported. Carve-out: the Hare `_unsafe` suffix convention is dropped wholesale (ww is C/Plan-9-lineage, an unmanaged systems language — no GC, no "safe" baseline to be unsafe relative to). bytes→str is a pure reinterpret (`strings.frombytes`, renamed from Hare's `fromutf8_unsafe`); validation is opt-in via `utf8.validate(b)?` at the IO source, never wrapped per-construction. Rationale: ref/hare/strings/utf8.ha:10,22 — the suffix flags Hare's managed-bytes-safety axis, which ww doesn't have. The honest name (`frombytes`) reserves `fromutf8` for a future true validating helper. Carve-out: lib/ tests use Go's external-test-package idiom (`package _test;` + `import ;`), a sanctioned Go-over-Hare departure — ww hard-rejects self-import (full Go), and Hare's same-package `@test` colocation now has a ww analogue: in-package white-box `@test` files (`package ;`, colocated) are sanctioned alongside the external black-box `package _test;` split — Go's `foo`/`foo_test` model — now that the non-T `@test` drop landed (#6, harec check.c:3941, 08a76cf; #5 closed). Rule 5/9 binds lib/ *API* surface, not test-authoring style. Ref: Go `foo_test` convention; task #16. Carve-out: `.len`, `.cap`, and `len(x)` remain `i32`, although slice/str header words are 8 bytes and Go returns `int`. This is a deliberate stability exception: ww numeric types do not implicitly interoperate, and the 2026-08-09 strict migration probe found at least 970 new mismatches across 189 paths (575 sites in 57 production lib/internal/selfhost paths). Representation remains word-sized; the checker types `&slice.len`, `&slice.cap`, `&str.len`, and `&str.cap` as `*i64` so indirect writes cover the full header word. Revisit only as a dedicated, independently pinned language migration. 10. Symmetric stages. cstage and wwstage MUST emit byte-identical asm for the same input. When inference power differs, align the richer side DOWN to the leaner side, not the other way. 11. Split commits when they bundle unrelated concerns. Bisect-cleanliness is the default. Multi-fix commits need a body paragraph explaining why they couldn't split. 12. Simple data, simple algorithms. Sea-of-stars style. Mirror Hare's structural choices over clever alternatives. diff --git a/lib/CLAUDE.md b/lib/CLAUDE.md index 44a89bfa..3fd0a999 100644 --- a/lib/CLAUDE.md +++ b/lib/CLAUDE.md @@ -12,7 +12,7 @@ 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: + type (`i32` under root CLAUDE.md rule 9). Example: `strconv.stoi64(s: str, b: strconv.base) (i64 | invalid | overflow)` — same shape as Hare's. The base parameter is the named enum `strconv.base` (Hare uses `enum uint`; we pick `enum i32` to diff --git a/lib/regex/whitebox_test.ww b/lib/regex/whitebox_test.ww index 2a815a6c..5a8a2ca7 100644 --- a/lib/regex/whitebox_test.ww +++ b/lib/regex/whitebox_test.ww @@ -39,7 +39,7 @@ type texp = struct { start_bytesize: size, matched: bool, failed: bool, - // .len reads as i32 (check.c:1239), so the count columns match it + // Root CLAUDE.md rule 9 keeps .len at i32, so these counts use i32. ncaps: i32, nreps: i32, };