1.7 KiB
selfhost — ww reimplementation of the toolchain (wcc, w6c, w6a, w6l, ww, wwdump). Compiled by the C bootstrap (../cmd/); the goal is to eventually compile itself.
Identifiers: Plan 9 style. lowercase, words run together (newbuf, tcpsock, parsefile). No snake_case.
Syntax and idioms: Hare-shaped. Trailing ;, = after fn/type signatures, export for visibility, match/?/! for tagged-union errors. Consult ref/hare/ for canonical signatures and error-handling patterns before inventing your own.
The C bootstrap's cgen ("wwstage") has four known silent-miscompilation traps. They produce wrong runtime behavior, not compile errors. When porting C → ww here, default to the workarounds:
-
Two-level field write through pointer field doesn't stick.
r.sym.isdyn = 1wherer.sym: *Tdrops the write. Bind the inner pointer to a local first:let sym: *lsym = r.sym; sym.isdyn = 1; -
Tuple return
(scalar, str)corrupts the str half. Both ptr and len come back garbage. Split into two functions — one returns the scalar, another returns the str. Plainstrreturns are fine. -
def NAME: str = "...";is broken. The.lenpicks up an unrelated accumulator. Wrap the literal in a nullary fn instead:fn namestr() str = { return "..."; }; -
amalloc(n)with n < struct size silently corrupts neighbours. No error — the bump arena hands out n bytes and field writes overflow into the next record. When introducing or growing a struct, audit everyamalloc(_, n)call site and over-size (we routinely pass 48 for a 40-byte struct). Symptom: linked-list prepends lose all but the most recent entry.
If a port "should work" but the binary is wrong, suspect these first.