Files
ww/CLAUDE.md

5.4 KiB

  1. This is a project for ww programming language
  2. ww is a programming language aiming for Hare + CSP, no GC
  3. cmd/ is the C bootstrap toolchain (wcc frontend lib, w6c/w6a/w6l per-arch, ww driver); selfhost/ is the ww reimplementation
  4. All C code must strictly align with plan 9 coding style
  5. lib/ is the standard library; follow Hare APIs (signatures, layout, error idioms) — consult ref/hare/ before designing new modules. Package declaration form is Go-style explicit package foo; and imports use import foo; (executables declare package main;) per language design (rob-pike + plan-9 sensibility); lib/ API surface still mirrors Hare.
  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 <mod>_test; + import <mod>;), 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 <mod>;, colocated) are sanctioned alongside the external black-box package <mod>_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.
  13. Authoritative size and layout helpers. Route compiler size and layout computations through resolved type metadata or canonical helpers (tinfo.size / Type.size / ty_*->size / size(T) / primtypesize / tyslicesize). Keep unavoidable external ABI and serialized-format constants localized and explain the contract they encode.
  14. Test targets. make test is the small developer gate: five in-process compiler units plus one compile-only C/WW compiler-fixture smoke case. make test-compiler owns the complete declarative compiler corpus and residual artifact/integration carriers; make test-package, make test-lang, and make test-library own package and in-language behavior. make test-commit composes those ordinary behavior suites but excludes byte identity, fixed-point/bootstrap, and platform gates. Run those explicitly with make test-byteid, make test-bootstrap, and make test-platform; make test-all is the exhaustive composition. Compiler-fixture subprocess coordination defaults to JOBS=1. There is no last-green cache or shell scheduler. A small-target result never proves bootstrap or byte identity.