diff --git a/lib/ascii/ascii_test.ww b/lib/ascii/ascii_test.ww index 94f60fc1..20dbabaa 100644 --- a/lib/ascii/ascii_test.ww +++ b/lib/ascii/ascii_test.ww @@ -1,6 +1,5 @@ -// asciitest — exercises lib/ascii case folding. Run with -// `ww run lib/ascii/asciitest.ww`. A failing row aborts via the -// assert/abort builtin (task #5 @test conversion). +// A failing row aborts via the assert/abort builtin (task #5 @test +// conversion). // // Vectors mirror Hare's @test fn strcasecmp in ref/hare/ascii/string.ha. diff --git a/lib/bufio/scanner_test.ww b/lib/bufio/scanner_test.ww index 8c4ee388..7bd0de3b 100644 --- a/lib/bufio/scanner_test.ww +++ b/lib/bufio/scanner_test.ww @@ -1,9 +1,6 @@ -// scannertest — exercises the lib/bufio scanner surface. The @tests -// enumerate parallel `[N]T` arrays of inputs and expectations, then -// iterate one body across them. #94 fold-eFinal: the unified -// value-return surface — `let st = memio.fixed(buf); &st.vt` into the -// scanner init, io.read/write/close return size/io.error. Row -// ownership mirrors ref/hare/bufio/scanner_test+test.ha. +// Row ownership mirrors ref/hare/bufio/scanner_test+test.ha. +// Streams are built as `let st = memio.fixed(buf); &st.vt` — the #94 +// unified value-return io surface (read/write/close return size/io.error). package bufio_test; @@ -12,8 +9,6 @@ import encoding.utf8; import io; import memio; -// putstr — copy the bytes of `s` into `into` starting at `off`, -// returning the new offset. fn putstr(s: str, into: []u8, off: i32) i32 = { let i: i32 = 0; for (i < s.len) { @@ -23,8 +18,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { return off + s.len; }; -// Replaces the OLD io.closed source. errvt is module-static; its -// reader/writer return a nomem-widened io.error. let errvt: io.vtable; fn errread(s: io.stream, buf: []u8) (size | io.eof | io.error) = { @@ -244,7 +237,6 @@ fn errsource() io.stream = { }; @test fn boundarycases() void = { - // ---- empty line via scanline ----------------------------------- let s1: [16]u8; let n1: i32 = putstr("\nfoo\n", s1[0:16], 0); let m1mem: memio.stream = memio.fixed(s1[0:n1]); @@ -271,7 +263,6 @@ fn errsource() io.stream = { }; bufio.finish(&sc1); - // ---- scanbytes idempotent EOF --------------------------------- let s2: [8]u8; let n2: i32 = putstr("ab", s2[0:8], 0); let m2mem: memio.stream = memio.fixed(s2[0:n2]); diff --git a/lib/bufio/stream.ww b/lib/bufio/stream.ww index b6edb302..0ec6e01c 100644 --- a/lib/bufio/stream.ww +++ b/lib/bufio/stream.ww @@ -2,24 +2,6 @@ // Hare's bufio:: surface (ref/hare/bufio/{scanner,stream}.ha). Project // #94 fold-eFinal. // -// Surface: -// -// bufio.newscanner (src: io.stream, maxread: i32) scanner -// bufio.newscannerbuf(src: io.stream, buf: []u8) scanner -// bufio.finish (s: *scanner) void -// bufio.scanbyte (s: *scanner) (u8 | io.eof | io.error | overflow) -// bufio.scanbytes (s: *scanner, delim: u8) -// ([]u8 | io.eof | io.error | overflow) -// bufio.scanrune (s: *scanner) -// (rune | io.eof | io.error | utf8.invalid | overflow) -// bufio.scanline (s: *scanner) (str | io.eof | io.error | overflow) -// -// bufio.init (src: io.stream, rbuf: []u8, wbuf: []u8) stream -// bufio.flush (b: *stream) (void | io.error) -// bufio.setflush (b: *stream, bs: []u8) void -// bufio.unread (b: *stream, buf: []u8) void -// bufio.isbuffered (s: io.stream) bool -// // VALUE-RETURN (Hare ref/hare/bufio/stream.ha:69 init, scanner.ha:92 // newscanner_buf): each constructor builds in a local `let r: T;`, // field-assigns every slot, and `return r;`. The caller owns the diff --git a/lib/bufio/stream_test.ww b/lib/bufio/stream_test.ww index 779730d8..f96596e3 100644 --- a/lib/bufio/stream_test.ww +++ b/lib/bufio/stream_test.ww @@ -1,8 +1,6 @@ -// streamtest — exercises the lib/bufio buffered stream surface. The -// stream @tests are one scenario per fn. #94 fold-eFinal: the unified -// value-return surface — `let st = memio.fixed(buf); &st.vt` into the -// stream init, io.read/write/close return size/io.error. Row -// ownership mirrors ref/hare/bufio/stream_test+test.ha. +// Row ownership mirrors ref/hare/bufio/stream_test+test.ha. +// Streams are built as `let st = memio.fixed(buf); &st.vt` — the #94 +// unified value-return io surface (read/write/close return size/io.error). package bufio_test; @@ -10,8 +8,6 @@ import bufio; import io; import memio; -// sputstr — copy the bytes of `s` into `into` starting at `off`, -// returning the new offset. fn sputstr(s: str, into: []u8, off: i32) i32 = { let i: i32 = 0; for (i < s.len) { diff --git a/lib/bytes/bytes.ww b/lib/bytes/bytes.ww index a9029d5b..061a6ae2 100644 --- a/lib/bytes/bytes.ww +++ b/lib/bytes/bytes.ww @@ -1,6 +1,4 @@ -// bytes — slice operations over []u8. Mirrors Hare's bytes module -// (ref/hare/bytes/) for the in-tree subset: search/equality/prefix -// helpers used by lib/encoding, lib/bufio, lib/memio. +// Hare port of the in-tree subset; see ref/hare/bytes/. // // Documented divergences from Hare: // - index_slice / rindex_slice use naive O(n·m); Hare specialises @@ -29,17 +27,16 @@ import types; // (utf8.ww:36). Plain `void` (not `!void`): continuation signal. export type done = void; -// tokenizer — cursor over an input slice. Layout mirrors -// ref/hare/bytes/tokenize.ha:6-10. `p` is the cached peek-position; -// I64_MAX (forward) / I64_MIN (reverse) are the unprimed sentinels. -// p < 0 also identifies a reverse-direction iterator. +// Layout mirrors ref/hare/bytes/tokenize.ha:6-10. `p` is the cached +// peek-position; I64_MAX (forward) / I64_MIN (reverse) are the +// unprimed sentinels. p < 0 also identifies a reverse-direction +// iterator. export type tokenizer = struct { in: []u8, delim: []u8, p: i64, }; -// equal — true iff `a` and `b` have the same length and contents. // ref/hare/bytes/equal.ha:9. export fn equal(a: []u8, b: []u8) bool = { if (a.len != b.len) { return false; }; @@ -51,8 +48,6 @@ export fn equal(a: []u8, b: []u8) bool = { return true; }; -// index — first offset of `needle` in `s`. u8 needle scans for the -// byte; []u8 needle scans for the substring. void if absent. // ref/hare/bytes/index.ha:6. export fn index(s: []u8, needle: (u8 | []u8)) (i32 | void) = { match (needle) { @@ -85,9 +80,8 @@ export fn index(s: []u8, needle: (u8 | []u8)) (i32 | void) = { return; }; -// rindex — last offset of `needle` in `s`. Empty []u8 needle returns -// s.len (ref/hare/bytes/index.ha:103 — Hare's loop yields r-0 at i=0). -// ref/hare/bytes/index.ha:86. +// Empty []u8 needle returns s.len (ref/hare/bytes/index.ha:103 — +// Hare's loop yields r-0 at i=0). ref/hare/bytes/index.ha:86. export fn rindex(s: []u8, needle: (u8 | []u8)) (i32 | void) = { match (needle) { case let c: u8 => { @@ -118,7 +112,6 @@ export fn rindex(s: []u8, needle: (u8 | []u8)) (i32 | void) = { return; }; -// contains — true iff any of `needles` (byte or sub-slice) appears in `s`. // ref/hare/bytes/contains.ha:6. export fn contains(s: []u8, needles: (u8 | []u8)...) bool = { let i: i32 = 0; @@ -142,8 +135,7 @@ export fn contains(s: []u8, needles: (u8 | []u8)...) bool = { return false; }; -// ltrim — borrowed view of `in` with leading bytes in `trim` stripped. -// `trim` must be non-empty. ref/hare/bytes/trim.ha:7. +// ref/hare/bytes/trim.ha:7. Borrowed view of `in` — caller must not free. export fn ltrim(in: []u8, trim: u8...) []u8 = { assert(trim.len > 0, "bytes.ltrim called with empty trim set"); let i: i32 = 0; @@ -155,8 +147,7 @@ export fn ltrim(in: []u8, trim: u8...) []u8 = { return r; }; -// rtrim — borrowed view of `in` with trailing bytes in `trim` stripped. -// `trim` must be non-empty. ref/hare/bytes/trim.ha:17. Hare's loop uses +// ref/hare/bytes/trim.ha:17. Borrowed view of `in`. Hare's loop uses // `size` underflow at i==0 to terminate; ww indices are signed i32, so // the equivalent termination is spelled `i >= 0` explicitly. export fn rtrim(in: []u8, trim: u8...) []u8 = { @@ -170,13 +161,11 @@ export fn rtrim(in: []u8, trim: u8...) []u8 = { return r; }; -// trim — borrowed view of `in` with both ends in `trim` stripped. -// ref/hare/bytes/trim.ha:27. +// ref/hare/bytes/trim.ha:27. Borrowed view of `in`. export fn trim(in: []u8, trim: u8...) []u8 = { return ltrim(rtrim(in, trim...), trim...); }; -// hasprefix — true iff `s` starts with `pre`. // ref/hare/bytes/contains.ha:21. export fn hasprefix(s: []u8, pre: []u8) bool = { if (pre.len > s.len) { return false; }; @@ -188,7 +177,6 @@ export fn hasprefix(s: []u8, pre: []u8) bool = { return true; }; -// hassuffix — true iff `s` ends with `suf`. // ref/hare/bytes/contains.ha:35. export fn hassuffix(s: []u8, suf: []u8) bool = { if (suf.len > s.len) { return false; }; @@ -201,7 +189,7 @@ export fn hassuffix(s: []u8, suf: []u8) bool = { return true; }; -// reverse — in-place reverse of `s`. ref/hare/bytes/reverse.ha:5. +// ref/hare/bytes/reverse.ha:5. export fn reverse(s: []u8) void = { let i: i32 = 0; let j: i32 = s.len - 1; @@ -214,7 +202,7 @@ export fn reverse(s: []u8) void = { }; }; -// zero — set every byte of `s` to 0. ref/hare/bytes/zero.ha:5. +// ref/hare/bytes/zero.ha:5. export fn zero(s: []u8) void = { let i: i32 = 0; for (i < s.len) { @@ -223,8 +211,6 @@ export fn zero(s: []u8) void = { }; }; -// tokenize — iterator yielding tokens from `in` separated by any byte -// in `delim`. Leading / trailing / adjacent delims yield empty tokens. // `delim` is borrowed; caller keeps it valid for the tokenizer's // lifetime. ref/hare/bytes/tokenize.ha:22. export fn tokenize(in: []u8, delim: u8...) tokenizer = { @@ -242,8 +228,7 @@ export fn tokenize(in: []u8, delim: u8...) tokenizer = { return t; }; -// rtokenize — reverse-direction tokenize. First nexttoken yields the -// last token, last nexttoken yields the first. ref/hare/bytes/tokenize.ha:40. +// ref/hare/bytes/tokenize.ha:40. export fn rtokenize(in: []u8, delim: u8...) tokenizer = { assert(delim.len > 0, "bytes.rtokenize called with empty slice"); assert((in.len: i64) < types.I64_MAX, @@ -259,9 +244,8 @@ export fn rtokenize(in: []u8, delim: u8...) tokenizer = { return t; }; -// peektoken — next token without advancing the cursor. Returns done -// once `s.delim` has been zeroed by a prior past-end nexttoken. -// ref/hare/bytes/tokenize.ha:91. +// Returns done once `s.delim` has been zeroed by a prior past-end +// nexttoken. ref/hare/bytes/tokenize.ha:91. export fn peektoken(s: *tokenizer) ([]u8 | done) = { if (s.delim.len == 0) { let d: done; return d; @@ -338,7 +322,6 @@ export fn peektoken(s: *tokenizer) ([]u8 | done) = { return r; }; -// nexttoken — current token, then advance past it and the delim. // Once the input is exhausted, returns done and zeros `s.delim` so // subsequent peeks short-circuit. ref/hare/bytes/tokenize.ha:59. export fn nexttoken(s: *tokenizer) ([]u8 | done) = { @@ -380,15 +363,13 @@ export fn nexttoken(s: *tokenizer) ([]u8 | done) = { return b; }; -// remainingtokens — the unconsumed portion of `s.in`. Read-only view. -// ref/hare/bytes/tokenize.ha:145. +// ref/hare/bytes/tokenize.ha:145. Read-only borrowed view. export fn remainingtokens(s: *tokenizer) []u8 = { return s.in; }; -// splitn — split `in` on any byte in `delim`, returning up to `n` -// tokens via forward iteration. The trailing slot (when more than -// `n - 1` tokens exist) holds the unconsumed remainder. +// The trailing slot (when more than `n - 1` tokens exist) holds the +// unconsumed remainder. // // The caller frees the returned slice via // `os.free(r.ptr: *void, (r.cap: u64) * 24u64)`. Element bytes are @@ -425,9 +406,8 @@ export fn splitn(in: []u8, delim: []u8, n: i32) [][]u8 = { return toks; }; -// rsplitn — reverse-direction counterpart to [[splitn]]: tokens are -// collected from the end of `in`. The trailing slot holds the -// unconsumed prefix (everything before the n-th-from-last delim hit). +// The trailing slot holds the unconsumed prefix (everything before +// the n-th-from-last delim hit). // // When the input has fewer than n tokens, the `done` short-circuit // returns toks UN-reversed (in last-token-first order). Mirrors Hare @@ -486,8 +466,7 @@ export fn rsplitn(in: []u8, delim: []u8, n: i32) [][]u8 = { return toks; }; -// split — full split of `in` on `delim` (no token cap). Mirrors -// `splitn(in, delim, types::SIZE_MAX)`. ww uses `types.I32_MAX` +// Mirrors `splitn(in, delim, types::SIZE_MAX)`. ww uses `types.I32_MAX` // because the index type is i32 (lib/CLAUDE.md). // // ref/hare/bytes/tokenize.ha:225. @@ -495,10 +474,9 @@ export fn split(in: []u8, delim: []u8) [][]u8 = { return splitn(in, delim, types.I32_MAX); }; -// cut — split `in` along the first instance of `delim`, returning the -// portion before and the portion after the delimiter as a borrowed -// tuple. When `delim` is absent, the whole input is the first half and -// the second is empty. ref/hare/bytes/tokenize.ha:392. +// When `delim` is absent, the whole input is the first half and the +// second is empty. Both halves are borrowed views — caller must not +// free them. ref/hare/bytes/tokenize.ha:392. // // Delim is spelled (u8 | []u8) to match index/rindex (bytes.ww:57/91); // the tagged union is an unordered set, so this is the same type as @@ -525,7 +503,6 @@ export fn cut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = { }; }; -// rcut — like [[cut]] but splits along the last instance of `delim`. // ref/hare/bytes/tokenize.ha:413. export fn rcut(in: []u8, delim: (u8 | []u8)) ([]u8, []u8) = { let ln: i32 = match (delim) { diff --git a/lib/bytes/contains_test.ww b/lib/bytes/contains_test.ww index 66d40e2b..aaed2ff2 100644 --- a/lib/bytes/contains_test.ww +++ b/lib/bytes/contains_test.ww @@ -1,6 +1,4 @@ -// containstest — exercises bytes.contains/hasprefix/hassuffix. A -// failing row aborts via the assert/abort builtin (task #5 @test -// conversion). Vectors mirror ref/hare/bytes/contains.ha. +// Vectors mirror ref/hare/bytes/contains.ha (task #5 @test conversion). package bytes_test; diff --git a/lib/bytes/equal_test.ww b/lib/bytes/equal_test.ww index 13591a5e..6bede581 100644 --- a/lib/bytes/equal_test.ww +++ b/lib/bytes/equal_test.ww @@ -1,6 +1,4 @@ -// equaltest — exercises bytes.equal. A failing row aborts via the -// assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/bytes/equal.ha. +// Vectors mirror ref/hare/bytes/equal.ha (task #5 @test conversion). package bytes_test; diff --git a/lib/bytes/index_test.ww b/lib/bytes/index_test.ww index a8992863..d313f6a9 100644 --- a/lib/bytes/index_test.ww +++ b/lib/bytes/index_test.ww @@ -1,6 +1,4 @@ -// indextest — exercises bytes.index/rindex, u8 and []u8 arms. A -// failing row aborts via the assert/abort builtin (task #5 @test -// conversion). Vectors mirror ref/hare/bytes/index.ha. +// Vectors mirror ref/hare/bytes/index.ha (task #5 @test conversion). package bytes_test; diff --git a/lib/bytes/tokenize_test.ww b/lib/bytes/tokenize_test.ww index 4c289725..a074d0cd 100644 --- a/lib/bytes/tokenize_test.ww +++ b/lib/bytes/tokenize_test.ww @@ -1,6 +1,4 @@ -// tokenizetest — exercises the bytes tokenize/splitn/cut families. -// A failing row aborts via the assert/abort builtin (task #5 @test -// conversion). Vectors mirror ref/hare/bytes/tokenize.ha. +// Vectors mirror ref/hare/bytes/tokenize.ha (task #5 @test conversion). package bytes_test; @@ -11,8 +9,6 @@ import os; // drives the iterator through an expected-token sequence and asserts // `equal(p, n)` (peek == next), `equal(n, want)` (next == expected). -// expect_token — table row driver. Advances `t` once, asserts the -// returned token matches `want`. peek invariant: peek must equal next. fn expect_token(t: *bytes.tokenizer, want: []u8) void = { match (bytes.peektoken(t)) { case let p: []u8 => { @@ -28,7 +24,6 @@ fn expect_token(t: *bytes.tokenizer, want: []u8) void = { }; }; -// expect_done — table-row driver. peek and next must both be done. fn expect_done(t: *bytes.tokenizer) void = { match (bytes.peektoken(t)) { case let p: []u8 => abort(); diff --git a/lib/bytes/trim_test.ww b/lib/bytes/trim_test.ww index 7e1a25cc..9068e442 100644 --- a/lib/bytes/trim_test.ww +++ b/lib/bytes/trim_test.ww @@ -1,6 +1,4 @@ -// trimtest — exercises bytes.ltrim/rtrim/trim. A failing row aborts -// via the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/bytes/trim.ha. +// Vectors mirror ref/hare/bytes/trim.ha (task #5 @test conversion). package bytes_test; diff --git a/lib/c/libc/libc.ww b/lib/c/libc/libc.ww index 7fb84700..b3d0b88f 100644 --- a/lib/c/libc/libc.ww +++ b/lib/c/libc/libc.ww @@ -1,10 +1,8 @@ -// lib/c/libc — minimal libc bindings. Each declaration is body-less, -// imported from the C side at link time. The @symbol attribute pins -// the linker name; without it, the binding name itself is used. -// // These declarations cover the small surface the bootstrap wants: // process exit, three io syscalls, and the malloc/free pair. Higher -// ergonomics live in sibling pure-ww packages. +// ergonomics live in sibling pure-ww packages. Each declaration is +// body-less, resolved from the C side at link time; @symbol pins the +// linker name (without it the binding name itself is used). package libc; diff --git a/lib/crypto/sha256/sha256_test.ww b/lib/crypto/sha256/sha256_test.ww index b3c07633..70453720 100644 --- a/lib/crypto/sha256/sha256_test.ww +++ b/lib/crypto/sha256/sha256_test.ww @@ -1,13 +1,11 @@ -// sha256_test — exercises lib/crypto/sha256 against the standard NIST -// SHA-256 vectors (FIPS 180-4 examples + the classic "one million a's"). -// Run with `out/bin/ww run lib/crypto/sha256/sha256_test.ww`. +// Vectors: the standard NIST SHA-256 set (FIPS 180-4 examples + the +// classic "one million a's"). // // The digest is the cgen-correctness oracle for u32 wrapping arithmetic // + the hash-vtable dispatch: any u32-overflow / rotate miscompile shows // up as a byte mismatch. A failing row aborts via the assert/abort // builtin (task #5 @test conversion). Expected digests come through the -// (separately tested) -// hex.decodestr so the vectors stay readable. +// (separately tested) hex.decodestr so the vectors stay readable. package sha256_test; import bytes; diff --git a/lib/dirs/dirs.ww b/lib/dirs/dirs.ww index 3f7f8c20..6fe1a957 100644 --- a/lib/dirs/dirs.ww +++ b/lib/dirs/dirs.ww @@ -1,14 +1,7 @@ // dirs — XDG base directory paths. Port of Hare's lib/dirs // (ref/hare/dirs/xdg.ha) using the lib/temp-style static `[256]u8` // pathbuf in place of Hare's `path::buffer` (lib/path doesn't ship -// a buffer type yet). -// -// Surface today (1:1 with Hare's xdg.ha minus runtime()): -// -// dirs.config(prog: str) str — XDG_CONFIG_HOME/, fallback $HOME/.config/ -// dirs.cache(prog: str) str — XDG_CACHE_HOME/, fallback $HOME/.cache/ -// dirs.data(prog: str) str — XDG_DATA_HOME/, fallback $HOME/.local/share/ -// dirs.state(prog: str) str — XDG_STATE_HOME/, fallback $HOME/.local/state/ +// a buffer type yet). Surface is 1:1 with Hare's xdg.ha minus runtime(). // // Returns are static-buffer views — borrowed for the lifetime of // the next dirs call (any of the four above). Callers needing the @@ -71,9 +64,8 @@ def SEP: u8 = 47u8; // octal literals, so we name the constant once. def MODE_0755: i32 = 493i32; -// puts — append `s` to pathbuf at offset `off`, capping against the -// buffer's capacity to leave room for the trailing NUL. Returns the -// new offset. Same shape as lib/temp.puts. +// Caps at 255 to leave room for the trailing NUL. Same shape as +// lib/temp.puts. fn puts(off: i32, s: str) i32 = { let i: i32 = 0; for (i < s.len) { @@ -84,9 +76,6 @@ fn puts(off: i32, s: str) i32 = { return off + i; }; -// build — assemble "//" into pathbuf, NUL-terminate, -// and store the length in [[pathlen]]. If `sub` is empty, the -// "/" segment is skipped and the result is "/". // Embedded '/' in `sub` (e.g. ".local/share") is fine — [[os.mkdirs]] // handles intermediate dirs. fn build(base: str, sub: str, prog: str) void = { @@ -112,8 +101,7 @@ fn build(base: str, sub: str, prog: str) void = { pathlen = off; }; -// view — return a `str` view into pathbuf[0..pathlen]. Borrowed -// for the lifetime of the next dirs call. +// Borrowed for the lifetime of the next dirs call. fn view() str = { let r: str; r.ptr = &pathbuf[0]; diff --git a/lib/dirs/dirs_test.ww b/lib/dirs/dirs_test.ww index 02255362..004e3cd7 100644 --- a/lib/dirs/dirs_test.ww +++ b/lib/dirs/dirs_test.ww @@ -92,8 +92,6 @@ fn gettmpdir() str = { }; }; -// ---- 1: XDG_CONFIG_HOME=/cfg → /cfg/myapp -------------- - @test fn test_config_xdg_set() void = { let tmpl = gettmpdir(); let exp = expected(tmpl, "cfg", "myapp"); @@ -101,8 +99,6 @@ fn gettmpdir() str = { assert(!(!streq(got, exp))); }; -// ---- 2: XDG_CACHE_HOME="relative/path" → fallback to $HOME/.cache -- -// // Exercises Hare's `if (!path::abs(path)) yield;` branch — a // non-absolute XDG_*_HOME silently falls through to the HOME path. @@ -113,8 +109,6 @@ fn gettmpdir() str = { assert(!(!streq(got, exp))); }; -// ---- 3: XDG_DATA_HOME unset → fallback to $HOME/.local/share ------- - @test fn test_data_unset_fallback() void = { let tmpl = gettmpdir(); let exp = expected(tmpl, ".local/share", "myapp"); @@ -122,8 +116,6 @@ fn gettmpdir() str = { assert(!(!streq(got, exp))); }; -// ---- 4: XDG_STATE_HOME unset → fallback to $HOME/.local/state ------ - @test fn test_state_unset_fallback() void = { let tmpl = gettmpdir(); let exp = expected(tmpl, ".local/state", "myapp"); diff --git a/lib/encoding/base32/base32.ww b/lib/encoding/base32/base32.ww index 4e796565..0b540270 100644 --- a/lib/encoding/base32/base32.ww +++ b/lib/encoding/base32/base32.ww @@ -1,5 +1,3 @@ -// encoding/base32 — RFC 4648 base32 encode/decode, buffer-based. -// // Mirrors Hare's encoding::base32 surface, modulo Hare's stream-based // encoder/decoder. ww ships the in-memory subset only: `encode(dst, // src)` writes the encoded bytes into `dst`, returning the count; diff --git a/lib/encoding/base32/base32_test.ww b/lib/encoding/base32/base32_test.ww index 305969a5..18878f2a 100644 --- a/lib/encoding/base32/base32_test.ww +++ b/lib/encoding/base32/base32_test.ww @@ -86,7 +86,6 @@ fn enchexvec(input: str, expect: str) void = { }; @test fn roundtrip_all_quintets() void = { - // Encode then decode every 5-byte combination of a small set. let raw: [5]u8; raw[0] = 0x00u8; raw[1] = 0x55u8; diff --git a/lib/encoding/base64/base64_test.ww b/lib/encoding/base64/base64_test.ww index fd94f8d5..ca8c332f 100644 --- a/lib/encoding/base64/base64_test.ww +++ b/lib/encoding/base64/base64_test.ww @@ -1,9 +1,7 @@ -// base64_test — exercises lib/encoding/base64's io-streaming surface. -// Run with `out/bin/ww run lib/encoding/base64/base64_test.ww`. Mirrors -// Hare's base64 @test fns (ref/hare/encoding/base64/base64.ha:315,514, -// 601) over the RFC 4648 §10 vectors, table-driven (parallel arrays; -// tuple-row arrays are blocked by #111). A failing row aborts via the -// assert/abort builtin (task #5 @test conversion). +// Mirrors Hare's base64 @test fns (ref/hare/encoding/base64/base64.ha: +// 315,514,601) over the RFC 4648 §10 vectors, table-driven (parallel +// arrays; tuple-row arrays are blocked by #111). A failing row aborts +// via the assert/abort builtin (task #5 @test conversion). // // The streaming decoder (newdecoder) is deferred (#247-sibling), so the // decode side is exercised through decodestr only. @@ -60,8 +58,6 @@ fn inval_check(enc: *base64.encoding, encoded: str) void = { }; }; -// ---- RFC 4648 §10 vectors, encode + decodestr round-trip ---- -// // Inputs are the prefixes of "foobar". The §10 expected encodings // contain no '+' / '/', so std and base64url agree on these vectors — // both alphabets are driven over the same table here; the std-vs-url @@ -91,8 +87,6 @@ fn inval_check(enc: *base64.encoding, encoded: str) void = { }; }; -// ---- std vs base64url alphabet distinctness ---- -// // [0xFB, 0xFF, 0xBF] hits the 62/63 alphabet slots: std emits '+'/'/', // url emits '-'/'_'. The two encodings must differ, each round-trips // under its own alphabet, and each is INVALID under the other (std @@ -112,8 +106,6 @@ fn inval_check(enc: *base64.encoding, encoded: str) void = { inval_check(&base64.url_encoding, s_std); }; -// ---- decodestr error cases ---- ref/hare/encoding/base64/base64.ha:525 -// // Table-driven (parallel-array idiom; tuple rows blocked by #111). Each // row exercises one malformed class the hand-written validation in // decodestr must reject. Cross-alphabet chars are covered separately by @@ -142,8 +134,6 @@ fn inval_check(enc: *base64.encoding, encoded: str) void = { }; }; -// ---- size calc ---- ref/hare/encoding/base64/base64.ha:601 - @test fn sizes() void = { assert(!(base64.encodedsize(0) != 0)); assert(!(base64.encodedsize(1) != 4)); @@ -172,8 +162,6 @@ fn inval_check(enc: *base64.encoding, encoded: str) void = { base64.decodedsize(5i32); }; -// ---- round-trip every byte value 0..255 (std + url) ---- - @test fn roundtrip_all_bytes() void = { let src: [256]u8; let i: i32 = 0; diff --git a/lib/encoding/hex/hex_test.ww b/lib/encoding/hex/hex_test.ww index b9c9f416..efc4c3bd 100644 --- a/lib/encoding/hex/hex_test.ww +++ b/lib/encoding/hex/hex_test.ww @@ -1,8 +1,6 @@ -// hextest — exercises lib/encoding/hex's io-streaming surface. Run with -// `out/bin/ww run lib/encoding/hex/hextest.ww`. Mirrors Hare's hex -// @test fns (ref/hare/encoding/hex/hex.ha:82,96,194) plus a full-byte -// round-trip. A failing row aborts via the assert/abort builtin (task #5 -// @test conversion). +// Mirrors Hare's hex @test fns (ref/hare/encoding/hex/hex.ha:82,96,194) +// plus a full-byte round-trip. A failing row aborts via the assert/abort +// builtin (task #5 @test conversion). // // The streaming decoder (newdecoder) is deferred (#247), so the decode // side is exercised through decodestr only. @@ -33,8 +31,6 @@ fn cafebabe() [8]u8 = { return r; }; -// ---- encodestr ---- ref/hare/encoding/hex/hex.ha:82 - @test fn encodestr_basic() void = { let in: [8]u8 = cafebabe(); assert(!(!streq(hex.encodestr(in[0:8]), "cafebabedeadf00d"))); @@ -57,8 +53,6 @@ fn cafebabe() [8]u8 = { assert(!(hex.encodestr(in[0:0]).len != 0)); }; -// ---- encode (io.handle sink) ---- ref/hare/encoding/hex/hex.ha:96 - @test fn encode_stream() void = { let in: [8]u8 = cafebabe(); let out: memio.stream = memio.dynamic(); @@ -69,8 +63,6 @@ fn cafebabe() [8]u8 = { assert(!(!streq(memio.string(&out), "cafebabedeadf00d"))); }; -// ---- decodestr round-trip ---- ref/hare/encoding/hex/hex.ha:194 - @test fn decodestr_lower() void = { match (hex.decodestr("cafebabedeadf00d")) { case let b: []u8 => { @@ -110,9 +102,8 @@ fn cafebabe() [8]u8 = { }; }; -// ---- decodestr error cases ---- ref/hare/encoding/hex/hex.ha:154,199 -// -// Odd length and non-hex chars both return errors.invalid. +// Odd length and non-hex chars both return errors.invalid +// (ref/hare/encoding/hex/hex.ha:154,199). @test fn decodestr_odd() void = { match (hex.decodestr("abc")) { @@ -135,8 +126,6 @@ fn cafebabe() [8]u8 = { }; }; -// ---- round-trip every byte value 0..255 -------------------------------- - @test fn roundtrip_all_bytes() void = { let src: [256]u8; let i: i32 = 0; diff --git a/lib/encoding/utf8/decode_test.ww b/lib/encoding/utf8/decode_test.ww index 9205bb10..386413da 100644 --- a/lib/encoding/utf8/decode_test.ww +++ b/lib/encoding/utf8/decode_test.ww @@ -1,7 +1,5 @@ -// decodetest — exercises the utf8 decoder: next/prev/validate/ -// remaining/slice/position, plus the encode→decode round-trip. A -// failing row aborts via the assert/abort builtin (task #5 @test -// conversion). Vectors mirror ref/hare/encoding/utf8/decode.ha. +// Vectors mirror ref/hare/encoding/utf8/decode.ha. A failing row aborts +// via the assert/abort builtin (task #5 @test conversion). package utf8_test; diff --git a/lib/encoding/utf8/encode_test.ww b/lib/encoding/utf8/encode_test.ww index dd56fd53..c28a0c2b 100644 --- a/lib/encoding/utf8/encode_test.ww +++ b/lib/encoding/utf8/encode_test.ww @@ -1,6 +1,5 @@ -// encodetest — exercises utf8.encoderune. A failing row aborts via -// the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/encoding/utf8/encode.ha. +// Vectors mirror ref/hare/encoding/utf8/encode.ha. A failing row aborts +// via the assert/abort builtin (task #5 @test conversion). package utf8_test; diff --git a/lib/encoding/utf8/rune_test.ww b/lib/encoding/utf8/rune_test.ww index 263a3c08..6733d707 100644 --- a/lib/encoding/utf8/rune_test.ww +++ b/lib/encoding/utf8/rune_test.ww @@ -1,6 +1,5 @@ -// runetest — exercises utf8.runesz/utf8sz. A failing row aborts via -// the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/encoding/utf8/rune.ha. +// Vectors mirror ref/hare/encoding/utf8/rune.ha. A failing row aborts +// via the assert/abort builtin (task #5 @test conversion). package utf8_test; diff --git a/lib/encoding/utf8/types_test.ww b/lib/encoding/utf8/types_test.ww index 40f7d65f..f5f7a3b2 100644 --- a/lib/encoding/utf8/types_test.ww +++ b/lib/encoding/utf8/types_test.ww @@ -1,6 +1,5 @@ -// typestest — exercises utf8.strerror. A failing row aborts via the +// Mirrors ref/hare/encoding/utf8/types.ha. A failing row aborts via the // assert/abort builtin (task #5 @test conversion). -// Mirrors ref/hare/encoding/utf8/types.ha. package utf8_test; diff --git a/lib/encoding/utf8/utf8.ww b/lib/encoding/utf8/utf8.ww index 6248e3dd..d38ef090 100644 --- a/lib/encoding/utf8/utf8.ww +++ b/lib/encoding/utf8/utf8.ww @@ -1,4 +1,4 @@ -// encoding/utf8 — UTF-8 encode/decode. Hare port; see +// Hare port; see // ref/hare/encoding/utf8/{types,rune,encode,decode,decodetable}.ha. // // The decoder is Hoehrmann's branchless DFA, originally published @@ -453,4 +453,3 @@ export fn slice(begin: *decoder, end: *decoder) []u8 = { export fn position(d: *decoder) i32 = { return d.offs: i32; }; - diff --git a/lib/endian/network.ww b/lib/endian/network.ww index c49ece6b..53a5771c 100644 --- a/lib/endian/network.ww +++ b/lib/endian/network.ww @@ -1,7 +1,7 @@ -// endian — byte-order conversions. Mirrors Hare's endian:: surface: -// big-endian (be*), little-endian (le*), and network-order (hton/ntoh) -// helpers. Host order on amd64 is little-endian, so hton/ntoh are -// byte swaps and the le* family is identity. +// Mirrors Hare's endian:: surface: big-endian (be*), little-endian +// (le*), and network-order (hton/ntoh) helpers. Host order on amd64 is +// little-endian, so hton/ntoh are byte swaps and the le* family is +// identity. package endian; diff --git a/lib/errors/errno_test.ww b/lib/errors/errno_test.ww index 4d351143..7eb95758 100644 --- a/lib/errors/errno_test.ww +++ b/lib/errors/errno_test.ww @@ -1,6 +1,3 @@ -// errnotest — exercises [[errors.errno]] and the [[errors.opaque_]] -// tail. Run with `out/bin/ww run lib/errors/errnotest.ww`. -// // Parallel `[N]T` arrays of (errno, expected-tag) rather than a // `[N]struct{...}` table — the cstage cgen's chained `arr[i].field` // store gap (task #6). [[errtag]] collapses each named-void variant to @@ -42,7 +39,6 @@ fn errtag(e: errors.error) int = { }; }; -// ---- errno → named condition -------------------------------------- @test fn mapping() void = { let ins: [12]os.errno; ins[0] = os.ECONNREFUSED; @@ -85,7 +81,6 @@ fn errtag(e: errors.error) int = { }; }; -// ---- unmapped errno → opaque_ tail -------------------------------- @test fn opaquetail() void = { // EIO (5) is outside the mapped set, so it wraps opaque_. let e: errors.error = errors.errno(5); @@ -98,7 +93,6 @@ fn errtag(e: errors.error) int = { }; }; -// ---- os.strerror mapped path -------------------------------------- @test fn strerrortext() void = { assert(!(!streq(os.strerror(os.ENOENT), "No such file or directory"))); assert(!(!streq(os.strerror(os.EINVAL), "Invalid argument"))); diff --git a/lib/fmt/fmt.ww b/lib/fmt/fmt.ww index e2228eb0..d2864255 100644 --- a/lib/fmt/fmt.ww +++ b/lib/fmt/fmt.ww @@ -1,23 +1,6 @@ -// fmt — formatting writers. Mirrors Hare's lib/fmt subset. Project #94 -// fold-eFinal; io fold-2 (#5) graduated the sink to [[io.handle]]. -// -// fprint / fprintln / fprintf / fprintfln -// write to an [[io.handle]] (= `(io.file | -// io.stream)`) — Hare's primary surface -// (ref/hare/fmt/print.ha:13). Errors via -// [[io.error]]. A file handle (raw fd) and a stream -// (`*io.vtable`) both flow in; [[io.write]] -// dispatches per arm. -// -// The process-stdio wrappers (print/println/errorln/printf/printfln/ -// errorfln/fatal/fatalf) route through the fprint family over a file -// handle built from os.STD{OUT,ERR}_FILENO. The #5 handle convergence -// retired the prior `fd_ctx` shim — the fake-stream vtable around -// os.write that stood in before io.write took a handle. -// -// Call sites take Hare's variadic shape: `fmt.println(42, "hi", true)` -// gathers the args into a `[]formattable` slice; wrappers forward via -// `args...`. +// fmt — formatting writers. Mirrors Hare's lib/fmt subset (primary +// surface ref/hare/fmt/print.ha:13). Project #94 fold-eFinal; io +// fold-2 (#5) graduated the sink to [[io.handle]]. package fmt; @@ -90,11 +73,6 @@ fn i64dec(v: i64) str = { // construction — both stages now accept bare int by MEMBERSHIP. export type formattable = (i64 | str | bool | rune | f64 | int | uint); -// ---- internal stream formatters -------------------------------------- - -// putbytes — io.write(s, [ptr..ptr+n)). Internal helper; the inline -// `let v` slice synthesis composes the (ptr, len) triple each -// formattable arm carries. fn putbytes(s: io.handle, p: *u8, n: i32) (size | io.error) = { let v: []u8; v.ptr = p; @@ -102,7 +80,6 @@ fn putbytes(s: io.handle, p: *u8, n: i32) (size | io.error) = { return io.write(s, v); }; -// writeone — emit one formattable through io.write. fn writeone(s: io.handle, a: formattable) (size | io.error) = { match (a) { case let n: i64 => { @@ -145,8 +122,6 @@ fn writeone(s: io.handle, a: formattable) (size | io.error) = { return 0: size; }; -// ---- {n}-placeholder parser ----------------------------------------- -// // Mirrors ref/hare/fmt/{iter,print,wrappers}.ha. Format sequences: // // {} implicit-positional next arg @@ -636,8 +611,6 @@ fn formatfield(s: io.handle, f: field, m: *mods) (size | io.error) = { }; }; -// ---- stream sinks ---------------------------------------------------- - // fprint — write the formatted form of each `args` element to `s`, // separated by spaces. Returns total bytes written or the first // io.error. Mirrors ref/hare/fmt/print.ha (fprint) + wrappers.ha. @@ -818,9 +791,7 @@ export fn asprintf(fmt: str, args: field...) str = { return strings.frombytes(tight); }; -// ---- process-stdio wrappers ----------------------------------------- -// -// Mirror ref/hare/fmt/wrappers.ha. Hare routes these through +// Mirror ref/hare/fmt/wrappers.ha. Hare routes the stdio wrappers through // os::stdout / os::stderr (io::handle); ww's os plays the sys role and // can't import io (import floor), so it exports the std fd NUMBERS // (os.STD{OUT,ERR}_FILENO) and the io.file binding is cast at the call diff --git a/lib/fmt/fmt_test.ww b/lib/fmt/fmt_test.ww index 03f895ea..e4621333 100644 --- a/lib/fmt/fmt_test.ww +++ b/lib/fmt/fmt_test.ww @@ -1,6 +1,3 @@ -// fmttest — exercises lib/fmt's stream sinks (fprint / fprintln). -// Run with `out/bin/ww run lib/fmt/fmttest.ww`. -// // Each @test writes through a memio.stream and compares the resulting // bytes against an inline `want` literal. Bodies are short enough that // the parallel-array idiom used by memiotest doesn't apply — every row @@ -24,10 +21,6 @@ fn streq(a: str, b: str) bool = { return true; }; -// ---- an error-returning stream for the io.error surfacing test -------- -// -// Replaces the OLD io.closed source. errvt is module-static; its -// reader/writer return a nomem-widened io.error. let errvt: io.vtable; fn errread(s: io.stream, buf: []u8) (size | io.eof | io.error) = { @@ -42,8 +35,6 @@ fn errsource() io.stream = { return &errvt; }; -// ---- fprint: bare str -------------------------------------------------- - @test fn fprintbarestr() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -59,8 +50,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint: int + str mix, space-separated ---------------------------- - @test fn fprintintstr() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -76,8 +65,7 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint: i64::MIN / int MIN whole-magnitude (#67) ------------------ -// i64dec used `n = -n` within i64, which wraps at i64::MIN (-MIN == MIN), +// #67: i64dec used `n = -n` within i64, which wraps at i64::MIN (-MIN == MIN), // so the digit loop never ran and only the bare '-' was emitted. The fix // takes the magnitude through math.absi64 into u64. These rows pin the // boundary value plus a normal negative, zero, and int MIN. @@ -114,8 +102,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint: bool + rune renders as "true A" -------------------------- - @test fn fprintboolrune() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -131,8 +117,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint: zero args returns 0, no bytes written -------------------- - @test fn fprintempty() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -148,8 +132,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprintln: multi-arg, trailing '\n' -------------------------------- - @test fn fprintlnmulti() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -165,8 +147,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprintln: zero args writes just the newline ---------------------- - @test fn fprintlnempty() void = { let mem: memio.stream = memio.dynamic(); let s: io.stream = &mem.vt; @@ -182,7 +162,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint over a fixed stream: short writes return partial count ---- // memio.fixedwrite caps each call at the remaining buffer space and // never closes the stream, so fprint sees a short i32 result, not // io.error. Verifies the inner-loop arithmetic adds the actual byte @@ -204,7 +183,6 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint over a closed stream surfaces io.error ------------------- // Exercises the early-return arm in fprint's inner match — distinct from // the short-write path above, which keeps returning i32 from a partial // accept. Single arm is enough: every formattable case routes errors @@ -220,10 +198,7 @@ fn errsource() io.stream = { }; }; -// ---- fprintf scenarios ------------------------------------------------- -// Each scenario writes through memio.dynamic and compares bytes against -// an inline `want`. Variadic call-site shape forces one body per shape; -// see the file header. +// Variadic call-site shape forces one body per shape; see the file header. @test fn fprintf_implicit() void = { let mem: memio.stream = memio.dynamic(); @@ -303,8 +278,7 @@ fn errsource() io.stream = { match (c) { case void => {}; case let eioe: io.error => abort(); }; }; -// ---- fprint: rune args emit full UTF-8, not a truncated byte (#66) ----- -// writeone/formatraw's rune arm did `buf[0] = r: u8; putbytes(...,1)`, +// #66: writeone/formatraw's rune arm did `buf[0] = r: u8; putbytes(...,1)`, // emitting only the low byte (invalid UTF-8 for r > 0x7F). The fix routes // through utf8.encoderune (ref/hare/fmt/print.ha:84). Edge runes: é (2B), // € (3B), 😀 (4B), A (1B). @@ -558,8 +532,6 @@ fn errsource() io.stream = { os.free(r.ptr: *void, r.len: u64); }; -// ---- f64 dispatch arm ------------------------------------------------- -// // Pins the f64 formattable arm landed under task #17 (unblocked by #30 // — the variant-widen-from-X0 fix). strconv.f64tos drives the render; // see lib/strconv/strconv.ww for the documented subset (fixed-point, diff --git a/lib/fnmatch/fnmatch.ww b/lib/fnmatch/fnmatch.ww index f5fd9a33..06627a79 100644 --- a/lib/fnmatch/fnmatch.ww +++ b/lib/fnmatch/fnmatch.ww @@ -2,12 +2,6 @@ // fnmatch:: (ref/hare/fnmatch/fnmatch.ha) using ww byte-indexed // cursors in place of Hare's strings::iterator. // -// Surface today: -// -// fnmatch.flag — enum i32 bitmask (NONE / PATHNAME / -// NOESCAPE / PERIOD) -// fnmatch.fnmatch(pattern: str, string: str, flags: flag) bool -// // Matching rules (Hare-spec): // // - '?' matches any single byte @@ -328,7 +322,6 @@ fn fnmatch_internal(pattern: str, string: str, fl: flag) (bool | invalid) = { let pp: i32 = 0; let sp: i32 = 0; - // ---- prefix: match up to the first '*' ---------------------- let sawstar: bool = false; for (!sawstar) { let scur: i32 = sp; @@ -361,7 +354,6 @@ fn fnmatch_internal(pattern: str, string: str, fl: flag) (bool | invalid) = { if (advance) { sp = scur; }; }; - // ---- find the tail (token count after the last '*') --------- let pp_copy: i32 = pp; let pp_last: i32 = pp; let pp_last_cnt: i32 = 0; @@ -398,7 +390,6 @@ fn fnmatch_internal(pattern: str, string: str, fl: flag) (bool | invalid) = { let tail_pos: i32 = string.len - tail_cnt; if (tail_pos < sp_copy) { return false; }; - // ---- tail: match (from pp) against string[tail_pos..] ------- let ts: i32 = tail_pos; let tdone: bool = false; for (!tdone) { @@ -439,7 +430,6 @@ fn fnmatch_internal(pattern: str, string: str, fl: flag) (bool | invalid) = { }; }; - // ---- middle: greedy match of each star-delimited subpattern -- let mid_pat: str; mid_pat.ptr = pattern.ptr + (pp_copy: u64); mid_pat.len = pp_last - pp_copy; @@ -525,7 +515,6 @@ fn fnmatch_pathname(pattern: str, string: str, fl: flag) (bool | invalid) = { let final: bool = false; for (!final) { segstart_pat = pp; - // Walk pattern until the next '/' (segment break) or end. let inner: bool = true; let kind: i32 = 0; // 0 = saw '/', 1 = saw end for (inner) { diff --git a/lib/fnmatch/fnmatch_test.ww b/lib/fnmatch/fnmatch_test.ww index b3894ebe..831c94e7 100644 --- a/lib/fnmatch/fnmatch_test.ww +++ b/lib/fnmatch/fnmatch_test.ww @@ -1,6 +1,3 @@ -// fnmatchtest — exercises lib/fnmatch. Run with -// `out/bin/ww run lib/fnmatch/fnmatchtest.ww`. -// // Table-driven via the [[check]] helper: every row is the uniform // 4-tuple `(pattern, string, expected, flags)`. Cases follow Hare's // ref/hare/fnmatch/+test.ha (the de-facto spec for this port); @@ -23,8 +20,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { assert(!(fnmatch.fnmatch(pat, s, f) != expected)); }; -// ---- basic literal / wildcard cases --------------------------------- - @test fn basic() void = { check("a", "a", true, 0); check("b", "b", true, 0); @@ -59,8 +54,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check("*?*?*?*?", "abc", false, 0); }; -// ---- bracket expressions: literal / range / negation ---------------- - @test fn brackets() void = { check("[b]", "b", true, 0); check("a[b]c", "abc", true, 0); @@ -110,8 +103,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check("[!-ac]", "b", true, 0); }; -// ---- POSIX character classes: [[:alnum:]] / [[:alpha:]] / ... ------- - @test fn ctype() void = { check("[[:alnum:]]", "7", true, 0); check("[[:alpha:]]", "[", false, 0); @@ -140,8 +131,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check("[![:alnum:][:digit:]]", "a", false, 0); }; -// ---- flag.PERIOD: leading '.' must be literal in the pattern -------- - @test fn period() void = { let fp: i32 = 4; // flag.PERIOD check(".", ".", true, fp); @@ -152,16 +141,12 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check(".*", "asdf", false, fp); }; -// ---- flag.NOESCAPE: '\\' loses its escape meaning ------------------- - @test fn noescape() void = { let nesc: i32 = 2; // flag.NOESCAPE check("\\", "\\", true, nesc); check("\\*", "\\asdf", true, nesc); }; -// ---- musl-adapted cases (no flags) --------------------------------- - @test fn musl_basic() void = { check("*.c", "foo.c", true, 0); check("*.c", ".c", true, 0); @@ -201,8 +186,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check("[![:d-d]", "[", false, 0); }; -// ---- flag.PATHNAME: '/' must be matched by literal '/' -------------- - @test fn pathname() void = { let fp: i32 = 1; // flag.PATHNAME check("[a-z]/[a-z]", "a/b", true, fp); @@ -217,8 +200,6 @@ fn check(pat: str, s: str, expected: bool, flags: i32) void = { check("???b", "aa/b", false, fp); }; -// ---- flag.PERIOD + flag.PATHNAME combined --------------------------- - @test fn combined() void = { let pp: i32 = 1; // PATHNAME let fp: i32 = 4; // PERIOD diff --git a/lib/getopt/getopt.ww b/lib/getopt/getopt.ww index 24d61f5d..19a8ed55 100644 --- a/lib/getopt/getopt.ww +++ b/lib/getopt/getopt.ww @@ -403,8 +403,6 @@ export fn strerror(err: *error) str = { return r; }; -// ---- help output -------------------------------------------------------- -// // ref/hare/getopt/getopts.ha:202-335. // // Divergences from Hare (all forced): @@ -447,13 +445,11 @@ fn _printusage( ) (size | io.error) = { let z: size = 0; - // "Usage: " match (fmt.fprint(out, "Usage:", name)) { case let n: size => z += n; case let e: io.error => return e; }; - // Optional auto-[-h] + flag cluster [-Xabc]. let startedflags: bool = false; if (!hascmdh) { match (fmt.fprint(out, " [-h")) { @@ -485,7 +481,6 @@ fn _printusage( }; }; - // Parameter slots [-X ]. i = 0; for (i < help.len) { let p: *help = &help[i]; @@ -571,7 +566,6 @@ export fn printhelp( return void; }; - // Print "name: summary\n\n" if help[0] is a CMD entry. let p0: *help = &help[0]; if (p0.kind == helpkind.CMD) { match (fmt.fprintfln(out, "{}: {}\n", name, p0.text)) { @@ -593,13 +587,11 @@ export fn printhelp( case let e: io.error => return e; }; - // Blank line between usage and option list. match (fmt.fprint(out, "\n")) { case let n: size => {}; case let e: io.error => return e; }; - // Auto -h line if not declared. if (!hascmdh) { match (fmt.fprintln(out, "-h: print this help text")) { case let n: size => {}; @@ -607,7 +599,6 @@ export fn printhelp( }; }; - // Per-option lines. let i: i32 = 0; for (i < help.len) { let p: *help = &help[i]; diff --git a/lib/getopt/getopt_test.ww b/lib/getopt/getopt_test.ww index 49a9f0e9..13c4cef1 100644 --- a/lib/getopt/getopt_test.ww +++ b/lib/getopt/getopt_test.ww @@ -1,6 +1,3 @@ -// getopttest — exercises lib/getopt. Run with -// `out/bin/ww run lib/getopt/getopttest.ww`. -// // Every @test enumerates parallel `[N]T` arrays of inputs and // expectations, then iterates one body across them. Parallel arrays // (rather than `[N]struct{...}`) sidestep the cstage cgen's chained @@ -36,8 +33,6 @@ fn streq(a: str, b: str) bool = { return true; }; -// ---- flagcluster: -Fahs files.txt → 4 flags + 1 arg -------------------- - @test fn flagcluster() void = { let helps: [5]getopt.help; getopt.cmdhelp(&helps[0], "list files"); @@ -82,8 +77,6 @@ fn streq(a: str, b: str) bool = { getopt.finish(&cmd); }; -// ---- paramflag: glued + separated arguments ---------------------------- - @test fn paramflag() void = { let helps: [3]getopt.help; getopt.cmdhelp(&helps[0], "edit"); @@ -125,8 +118,6 @@ fn streq(a: str, b: str) bool = { getopt.finish(&cmd); }; -// ---- separator: -- ends option processing ------------------------------ -// // `--` in three positions: after a flag, immediately after argv[0], // and at the tail with nothing trailing. Flat-packed argv per // errortable's pattern; rows expect distinct (optslen, argslen, @@ -176,8 +167,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- repeatedflag: -vvv → 3 v opts ------------------------------------- - @test fn repeatedflag() void = { let helps: [2]getopt.help; getopt.cmdhelp(&helps[0], "verbose count"); @@ -207,8 +196,6 @@ fn streq(a: str, b: str) bool = { getopt.finish(&cmd); }; -// ---- baredash: "-" alone is a positional -------------------------------- -// // Bare `-` in three positions: trailing after a flag, leading (which // halts option scanning), and followed by what looks like a flag // (also halts — first non-flag wins). @@ -257,8 +244,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- errortable: unknownopt + requiresarg variants --------------------- -// // Parallel arrays per row: argv flat-packed into `srcs`, with `argo` // the offset and `argn` the count for each row. @test fn errortable() void = { @@ -306,8 +291,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- strerrortext: render both error kinds ----------------------------- -// // Parallel rows over (kind, flag, name) → expected message. `kind` // rides as i32 because the errorkind enum doesn't yet index an // array element directly. @@ -332,8 +315,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- nooptionsbare: argv with only program name + positionals ---------- -// // Positional-only argv at three lengths: two positionals, one // positional, and the program-name-only edge. @test fn nooptionsbare() void = { @@ -380,8 +361,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- printusage_cases: table of width-measure paths -------------------- -// // ref/hare/getopt/getopts.ha:202-265. // Row 0: short line (≤72) — auto-[-h] + FLAG cluster, no wrap. // Row 1: long line (>72) — PARAM slots each prefixed with \n\t. @@ -434,8 +413,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- optionsizepin: option is 32B, not 24B ----------------------------- -// // tryparse/finish free the parsed-option array at `cap * size(option)`. // option = rune (4) + pad (4) + str (24, #1/Phase 3) = 32B. A hardcoded // `24u64` here was an 8-byte-per-element under-free; pinning the size @@ -445,8 +422,6 @@ fn streq(a: str, b: str) bool = { assert(!(size(getopt.option) != 32)); }; -// ---- freeroundtrip: parse → finish over {0, 1, several} options -------- -// // Exercises the free path at three distinct cap values so the // `cap * size(option)` free in [[finish]] runs for an empty, single, // and multi-element option array. The under-free is not directly @@ -493,8 +468,6 @@ fn streq(a: str, b: str) bool = { }; }; -// ---- printhelp_cases: table of help-output paths ---------------------- -// // ref/hare/getopt/getopts.ha:281-314. // Row 0: empty help slice → early return, no output. // Row 1: full help (CMD+FLAG+PARAM+CMD) → summary + usage + option list. diff --git a/lib/hash/adler32/adler32.ww b/lib/hash/adler32/adler32.ww index 267887f9..d19ac0a9 100644 --- a/lib/hash/adler32/adler32.ww +++ b/lib/hash/adler32/adler32.ww @@ -1,4 +1,4 @@ -// hash/adler32 — Adler-32 checksum (RFC 1950). Pure ww. +// Adler-32 checksum (RFC 1950). // // Hare ships a hash::hash-shaped streaming type backed by io::stream; // we ship the pure-buffer subset here, same shape as lib/hash/fnv. diff --git a/lib/hash/crc16/crc16.ww b/lib/hash/crc16/crc16.ww index 2e7673e9..e7e317fd 100644 --- a/lib/hash/crc16/crc16.ww +++ b/lib/hash/crc16/crc16.ww @@ -1,5 +1,3 @@ -// hash/crc16 — CRC-16 checksum. Pure ww. -// // Inline polynomial-shift per byte (no precomputed tables). Slower // than a table-driven CRC by ~8x per byte but matches the // table-driven answer bit-for-bit. @@ -15,9 +13,7 @@ def ANSI: u16 = 0xA001u16; // Modbus, USB, ANSI X3.28 // sum16 — fold `buf` under `poly` and return ~cval. Initial value is // ~0u16, matching the streaming CRC-16 contract for a single -// write-then-sum. Per byte: XOR low byte of cval with msg byte to form -// an 8-bit index, run 8 polynomial shifts on that index, XOR the -// result with the high byte of cval shifted down. +// write-then-sum. export fn sum16(buf: []u8, poly: u16) u16 = { let c: u16 = 0xFFFFu16; let i: i32 = 0; diff --git a/lib/hash/crc32/crc32.ww b/lib/hash/crc32/crc32.ww index 23f1cfd3..0ebfaf5d 100644 --- a/lib/hash/crc32/crc32.ww +++ b/lib/hash/crc32/crc32.ww @@ -1,5 +1,3 @@ -// hash/crc32 — CRC-32 checksum. Pure ww. -// // Same shape as lib/hash/crc16: per-byte inline polynomial shift, // no precomputed table. Slower than Hare's table-driven path by ~8x // per byte but produces identical answers. @@ -10,9 +8,7 @@ def IEEE: u32 = 0xEDB88320u32; // gzip, PNG, zip, Ethernet def CASTAGNOLI: u32 = 0x82F63B78u32; // iSCSI, SCTP, SSE4.2 def KOOPMAN: u32 = 0xEB31D82Eu32; // small datasets -// sum32 — fold `buf` under `poly` (reversed form). Initial cval is -// ~0u32; per byte we mix in the low byte via 8 polynomial shifts and -// XOR with the high three bytes shifted down. +// sum32 — fold `buf` under `poly` (reversed form). Initial cval is ~0u32. export fn sum32(buf: []u8, poly: u32) u32 = { let c: u32 = 0xFFFFFFFFu32; let i: i32 = 0; diff --git a/lib/hash/crc64/crc64.ww b/lib/hash/crc64/crc64.ww index 8ae69d29..b8329b1f 100644 --- a/lib/hash/crc64/crc64.ww +++ b/lib/hash/crc64/crc64.ww @@ -1,5 +1,3 @@ -// hash/crc64 — CRC-64 checksum. Pure ww. -// // Same shape as lib/hash/crc32: per-byte inline polynomial shift, no // precomputed table. Slower than Hare's table-driven path by ~8x per // byte but produces identical answers for the documented polynomials. @@ -11,9 +9,7 @@ package crc64; def ECMA: u64 = 0xC96C5795D7870F42u64; // ECMA-182, xz-utils def ISO: u64 = 0xD800000000000000u64; // ISO 3309 HDLC -// sum64 — fold `buf` under `poly` (reversed form). Initial cval is -// ~0u64; per byte we mix in the low byte via 8 polynomial shifts and -// XOR with the high seven bytes shifted down. +// sum64 — fold `buf` under `poly` (reversed form). Initial cval is ~0u64. export fn sum64(buf: []u8, poly: u64) u64 = { let c: u64 = 0xFFFFFFFFFFFFFFFFu64; let i: i32 = 0; diff --git a/lib/hash/fnv/fnv.ww b/lib/hash/fnv/fnv.ww index fea37485..12c3773e 100644 --- a/lib/hash/fnv/fnv.ww +++ b/lib/hash/fnv/fnv.ww @@ -1,5 +1,3 @@ -// hash/fnv — FNV-1a 64-bit. Pure ww. No dependencies. - package fnv; def OFFSET: u64 = 14695981039346656037; diff --git a/lib/hash/siphash/siphash.ww b/lib/hash/siphash/siphash.ww index 3a7bd623..8334cd15 100644 --- a/lib/hash/siphash/siphash.ww +++ b/lib/hash/siphash/siphash.ww @@ -1,5 +1,3 @@ -// hash/siphash — SipHash-2-4 keyed hash, buffer-based. -// // Mirrors Hare's hash::siphash for the one-shot path: take a 16-byte // key and a buffer, return the 64-bit hash. Hare ships a streaming // io::stream-backed type; ww's subset doesn't, matching the rest of diff --git a/lib/io/io.ww b/lib/io/io.ww index 9a9870b3..e6725dca 100644 --- a/lib/io/io.ww +++ b/lib/io/io.ww @@ -5,19 +5,13 @@ // through it. The error channel is the return value — Hare-shaped // tagged unions instead of errno-style integer sentinels. // -// This file owns the eof / underread variant tags; lib/io/stream.ww -// owns the `vtable` + `stream` + read/write/close dispatchers, -// lib/io/empty.ww owns the [[empty]] singleton, and lib/io/types.ww -// owns the error union, mode/whence enums, and the reader/writer/ -// closer fn-type aliases. // #94 fold-eFinal collapsed the pre-vtable `stream` struct + `closed` // tag into the single vtable surface; the dispatchers are read/write/ // close (over `stream`), final over `handle` at io fold-2 (#5). package io; -// eof — read past the end of the stream. Hare uses the `done` -// singleton for EOF; ww doesn't have `done` yet so we ship a -// named-void variant tag. Lifts to `done` with #93. +// Hare uses the `done` singleton for EOF; ww doesn't have `done` yet +// so we ship a named-void variant tag. Lifts to `done` with #93. export type eof = void; // underread — an I/O handle hit eof partway through a fixed-size diff --git a/lib/io/stream.ww b/lib/io/stream.ww index 496866ef..998a010b 100644 --- a/lib/io/stream.ww +++ b/lib/io/stream.ww @@ -89,8 +89,7 @@ fn st_close(s: stream) (void | error) = { }; }; -// ref/hare/io/stream.ha:70-77. Clone of st_read's slot-dispatch shape -// over the new `seeker` vtable slot. +// ref/hare/io/stream.ha:70-77. fn st_seek(s: stream, off: off, w: whence) (off | error) = { match (s.seeker) { case void => { @@ -102,9 +101,8 @@ fn st_seek(s: stream, off: off, w: whence) (off | error) = { }; }; -// ref/hare/io/handle.ha:16-23. The handle-typed public read: the -// file-arm routes to os.read (Q2 layering), the stream-arm delegates to -// the unchanged st_read vtable dispatch above. +// ref/hare/io/handle.ha:16-23. The file arm routes to os.read +// directly (the Q2 layering ruling: os stays below io). export fn read(h: handle, buf: []u8) (size | eof | error) = { match (h) { case let fd: file => { diff --git a/lib/io/types.ww b/lib/io/types.ww index 90bd33e5..76fae0a6 100644 --- a/lib/io/types.ww +++ b/lib/io/types.ww @@ -1,14 +1,8 @@ -// types — error union, mode/whence enums, reader/writer/closer -// fn-type aliases. Project #94 fold-eFinal; the fn-aliases target -// `stream` (= `*vtable`, the single io surface). -// // Hare splits the io module across stream.ha + types.ha and ww does -// the same: lib/io/io.ww owns the `eof` and `underread` tags; -// lib/io/stream.ww owns the vtable surface (`vtable`, `stream`, -// `read`/`write`/`close` dispatch); this file owns the surrounding -// port. The four files share `package io;` so cross-file refs -// resolve via the dir-enum concat order (io.ww < stream.ww < types.ww -// — `stream` lands before the reader/writer/closer aliases below). +// the same (#94 fold-eFinal). The four files share `package io;` so +// cross-file refs resolve via the dir-enum concat order (io.ww < +// stream.ww < types.ww — `stream` lands before the reader/writer/ +// closer aliases below). // // Deferrals (drew-signed): `copier`, `strerror` (the #5 list's // `handle` + `seeker` landed with the #5 arc and the memio-seeker diff --git a/lib/log/log.ww b/lib/log/log.ww index 6cbb4ef2..b9639835 100644 --- a/lib/log/log.ww +++ b/lib/log/log.ww @@ -2,24 +2,6 @@ // Subset of Hare's lib/log (ref/hare/log/{logger,funcs,global,silent}.ha). // Project #94 fold-eFinal. // -// Surface: -// -// log.logger — vtable with `println` + `printfln` slots -// log.stdlogger — first-field embed of logger + an io.stream sink -// log.new (sink: io.stream) stdlogger -// log.silent *logger — a logger that discards every record -// log.default *logger — a stdlogger writing to stderr -// log.global *logger — the dispatch target for [[println]] / [[fatal]] -// log.println (args: fmt.formattable...) void -// log.lprintln (log: *logger, args: fmt.formattable...) void -// log.printfln (format: str, fields: fmt.field...) void -// log.lprintfln (log: *logger, format: str, fields: fmt.field...) void -// log.fatal (args: fmt.formattable...) never -// log.lfatal (log: *logger, args: fmt.formattable...) never -// log.fatalf (format: str, fields: fmt.field...) never -// log.lfatalf (log: *logger, format: str, fields: fmt.field...) never -// log.setlogger (log: *logger) void -// // VALUE-RETURN (Hare ref/hare/log/logger.ha:20): [[new]] builds a // stdlogger in a local and `return r;` (proven field-by-field sret). // stdlogger is 24B (two fn-ptrs + sink), returned via the SysV memory @@ -111,7 +93,6 @@ export let silent: *logger; export let default: *logger; export let global: *logger; -// initdone — guards [[ensureinit]] so the one-shot wiring runs once. let initdone: i32 = 0; fn ensureinit() void = { @@ -183,8 +164,6 @@ fn stdprintfln(l: *logger, format: str, fields: fmt.field...) void = { fn silentprintln(l: *logger, args: fmt.formattable...) void = { }; fn silentprintfln(l: *logger, format: str, fields: fmt.field...) void = { }; -// ---- public API ---------------------------------------------------------- - // new — build a stdlogger over `sink`, returned BY VALUE. Mirrors // ref/hare/log/logger.ha:20. export fn new(sink: io.stream) stdlogger = { diff --git a/lib/log/silent_test.ww b/lib/log/silent_test.ww index 06476b3a..c3d799d6 100644 --- a/lib/log/silent_test.ww +++ b/lib/log/silent_test.ww @@ -23,9 +23,7 @@ import memio; assert(!(mem.pos != 0)); }; -// The silent logger's printfln callback discards args without touching -// fmt or any sink. Same pattern as [[silentwritesnothing]] for the -// bare-args path. +// Same pattern as [[silentwritesnothing]] for the bare-args path. @test fn silentignoresprintfln() void = { let buf: [16]u8; let mem = memio.fixed(buf[0:16]); diff --git a/lib/math/checked/checked.ww b/lib/math/checked/checked.ww index 5ab9e2bd..2d3eeda7 100644 --- a/lib/math/checked/checked.ww +++ b/lib/math/checked/checked.ww @@ -1,8 +1,7 @@ -// math/checked — overflow-checked integer arithmetic. Ported from -// Hare's math::checked (ref/hare/math/checked/checked.ha). add*/sub*/ -// mul* return (result, overflow) with wrapping semantics. The saturating -// (clamp-on-overflow) siblings live in saturating.ww — same `checked` -// module. +// Ported from Hare's math::checked (ref/hare/math/checked/checked.ha). +// add*/sub*/mul* return (result, overflow) with wrapping semantics. The +// saturating (clamp-on-overflow) siblings live in saturating.ww — same +// `checked` module. // // Subset of Hare's surface (Hare splits per type, so these are clean // omissions, not divergences): diff --git a/lib/math/checked/saturating.ww b/lib/math/checked/saturating.ww index f42ef50c..3cf428db 100644 --- a/lib/math/checked/saturating.ww +++ b/lib/math/checked/saturating.ww @@ -1,5 +1,4 @@ -// math/checked (saturating) — clamp-on-overflow arithmetic. Ported from -// Hare's math::checked saturating siblings +// Ported from Hare's math::checked saturating siblings // (ref/hare/math/checked/saturating.ha). Part of the same `checked` // module as checked.ww. Each sat_* clamps to the type's range on // overflow instead of wrapping. diff --git a/lib/math/floats.ww b/lib/math/floats.ww index 38100f9c..574b255b 100644 --- a/lib/math/floats.ww +++ b/lib/math/floats.ww @@ -1,6 +1,4 @@ -// floats — f64 classification, sign, bit-reinterpret core, and the f64 -// decompose half (subnormal-normalize + frexp). Ported from -// ref/hare/math/floats.ha (fold-1: classify/sign/bits; fold-2a: +// Ported from ref/hare/math/floats.ha (fold-1: classify/sign/bits; fold-2a: // issubnormalf64/normalizef64/frexpf64; strconv-foundation fold-1a: // F32 bit-layout + f32bits/f32frombits + floatinfo struct type; // fold-1b: NAN_BITS/INF_BITS sentinels; γ-cleanup: f64info/f32info @@ -12,7 +10,6 @@ package math; -// Returns the binary representation of the given f64. // ref/hare/math/floats.ha:5. Parens around &n are load-bearing: ww's `:` // cast binds tighter than unary `&`, so Hare's `*(&n: *u64)` would parse // as `*(&(n: *u64))`; `(&n): *u64` reinterprets the address as intended. @@ -20,19 +17,16 @@ export fn f64bits(n: f64) u64 = { return *((&n): *u64); }; -// Returns the binary representation of the given f32. // ref/hare/math/floats.ha:8 export fn f32bits(n: f32) u32 = { return *((&n): *u32); }; -// Returns f64 with the given binary representation. // ref/hare/math/floats.ha:11 export fn f64frombits(n: u64) f64 = { return *((&n): *f64); }; -// Returns f32 with the given binary representation. // ref/hare/math/floats.ha:14 export fn f32frombits(n: u32) f32 = { return *((&n): *f32); @@ -45,25 +39,20 @@ export fn f32frombits(n: u32) f32 = { // amounts and mask widths, so they are typed u64 here — the closest // stand-in for Hare's untyped-int adapt at those use sites. -// The number of bits in the significand of the binary representation of f64. export def F64_MANTISSA_BITS: u64 = 52; -// The number of bits in the exponent of the binary representation of f64. export def F64_EXPONENT_BITS: u64 = 11; // The bias of the exponent of the binary representation of f64. Subtract this // from the exponent in the binary representation to get the actual exponent. export def F64_EXPONENT_BIAS: u64 = 1023; -// Mask with each bit of an f64's mantissa set. // ref/hare/math/floats.ha:37 export def F64_MANTISSA_MASK: u64 = (1 << F64_MANTISSA_BITS) - 1; -// Mask with each bit of an f64's exponent set. // ref/hare/math/floats.ha:40 export def F64_EXPONENT_MASK: u64 = (1 << F64_EXPONENT_BITS) - 1; -// The mask that gets an f64's sign. // ref/hare/math/floats.ha:75 def F64_SIGN_MASK: u64 = 1u64 << 63; @@ -84,11 +73,9 @@ def F64_EXP_ZERO: u64 = (F64_EXPONENT_BIAS - 1) << F64_MANTISSA_BITS; // the u32 bit container, the same way the F64 family rides u64 — see // the note above F64_MANTISSA_BITS). -// The number of bits in the significand of the binary representation of f32. // ref/hare/math/floats.ha:27 export def F32_MANTISSA_BITS: u32 = 23u32; -// The number of bits in the exponent of the binary representation of f32. // ref/hare/math/floats.ha:30 export def F32_EXPONENT_BITS: u32 = 8u32; @@ -97,15 +84,12 @@ export def F32_EXPONENT_BITS: u32 = 8u32; // ref/hare/math/floats.ha:33 export def F32_EXPONENT_BIAS: u32 = 127u32; -// Mask with each bit of an f32's mantissa set. // ref/hare/math/floats.ha:43 export def F32_MANTISSA_MASK: u32 = (1u32 << F32_MANTISSA_BITS) - 1u32; -// Mask with each bit of an f32's exponent set. // ref/hare/math/floats.ha:46 export def F32_EXPONENT_MASK: u32 = (1u32 << F32_EXPONENT_BITS) - 1u32; -// The mask that gets an f32's sign. // ref/hare/math/floats.ha:87 def F32_SIGN_MASK: u32 = 1u32 << 31; @@ -127,15 +111,10 @@ def F32_EXP_ZERO: u32 = (F32_EXPONENT_BIAS - 1u32) << F32_MANTISSA_BITS; // against ref/hare/strconv/stof.ha:248,288 (`let e: int = 0` arithmetic // against `f.expbias` of the same type, no cast at use site). export type floatinfo = struct { - // Bits in significand. mantbits: u64, - // Bits in exponent. expbits: u64, - // Bias of exponent. expbias: int, - // Mask for mantissa. mantmask: u64, - // Mask for exponent. expmask: u64, }; @@ -177,14 +156,12 @@ export def f32info: floatinfo = floatinfo { export def NAN_BITS: u64 = 0x7FF8000000000000u64; export def INF_BITS: u64 = 0x7FF0000000000000u64; -// Returns true if the given floating-point number is NaN. // ref/hare/math/floats.ha:144 (Hare's expression body inlined into a // block: ww has no expression-bodied fn form, only brace blocks). export fn isnan(n: f64) bool = { return n != n; }; -// Returns true if the given floating-point number is infinite. // ref/hare/math/floats.ha:147 export fn isinf(n: f64) bool = { const bits = f64bits(n); @@ -193,7 +170,6 @@ export fn isinf(n: f64) bool = { return exp == F64_EXPONENT_MASK && mant == 0; }; -// Returns true if the given f64 is subnormal. // ref/hare/math/floats.ha:179 export fn issubnormalf64(n: f64) bool = { const bits = f64bits(n); @@ -202,7 +178,6 @@ export fn issubnormalf64(n: f64) bool = { return exp == 0 && mant != 0; }; -// Returns the absolute value of f64 n. // ref/hare/math/floats.ha:195 export fn absf64(n: f64) f64 = { if (isnan(n)) { @@ -222,19 +197,16 @@ export fn signf64(x: f64) i64 = { }; }; -// Returns whether or not x is positive. // ref/hare/math/floats.ha:231 export fn ispositivef64(x: f64) bool = { return signf64(x) == 1i64; }; -// Returns whether or not x is negative. // ref/hare/math/floats.ha:237 export fn isnegativef64(x: f64) bool = { return signf64(x) == -1i64; }; -// Returns x, but with the sign of y. // ref/hare/math/floats.ha:243 export fn copysignf64(x: f64, y: f64) f64 = { return f64frombits((f64bits(x) & ~F64_SIGN_MASK) | diff --git a/lib/math/math.ww b/lib/math/math.ww index 3ed99ead..d593c9a7 100644 --- a/lib/math/math.ww +++ b/lib/math/math.ww @@ -1,6 +1,6 @@ -// math — numeric helpers. Subset of Hare's math::; only the absolute- -// value pair for the signed integer types we currently care about. The -// return type is unsigned so that abs(I32_MIN) doesn't overflow. +// Subset of Hare's math::; only the absolute-value pair for the signed +// integer types we currently care about. The return type is unsigned +// so that abs(I32_MIN) doesn't overflow. package math; diff --git a/lib/math/random/random.ww b/lib/math/random/random.ww index dd315f06..0991cd58 100644 --- a/lib/math/random/random.ww +++ b/lib/math/random/random.ww @@ -9,11 +9,9 @@ package random; export type random = u64; -// init — initialize a generator with `seed`. Same seed reproduces the -// same sequence on every run. Mirrors Hare's random::init. +// Mirrors Hare's random::init. export fn init(seed: u64) random = { return seed: random; }; -// next — return a pseudo-random 64-bit value and advance the state. // SplitMix64, per Hare's random::next. export fn next(r: *random) u64 = { let s: u64 = (*r): u64 + 0x9E3779B97F4A7C15u64; diff --git a/lib/memio/memio.ww b/lib/memio/memio.ww index 6431fe5a..919037d1 100644 --- a/lib/memio/memio.ww +++ b/lib/memio/memio.ww @@ -122,8 +122,6 @@ export fn dynamicfrom(buf: []u8) stream = { return r; }; -// ---- vtable callbacks ---------------------------------------------------- - // readfn — recover the stream from the io.stream's `*vtable` via the // intrusive offset-0 cast. Single fn over the common header (Hare's // single `read` at ref/hare/memio/stream.ha:103); fixed and dynamic @@ -247,11 +245,6 @@ fn dynamicgrow(d: *stream, need: i32) void = { d.cap = newcap; }; -// ---- accessors over the common `stream` header ----------------------- -// -// Single fn each: Hare's string/reset/buffer/borrowedread all take -// `*stream` and read the flat header. - // string — bytes written so far, as a str view (buf[0..pos]). // // Mirrors ref/hare/memio/stream.ha:81 string(in: *stream). Hare returns diff --git a/lib/memio/memio_test.ww b/lib/memio/memio_test.ww index 90298110..81ec0ece 100644 --- a/lib/memio/memio_test.ww +++ b/lib/memio/memio_test.ww @@ -1,5 +1,3 @@ -// memiotest — exercises lib/memio. Run with `out/bin/ww run lib/memio/memiotest.ww`. -// // Every @test enumerates parallel `[N]T` arrays of inputs and // expectations, then iterates one body across them. Parallel arrays // (rather than `[N]struct{...}`) sidestep the cstage cgen's chained @@ -23,8 +21,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { return off + s.len; }; -// ---- fixedread: read sizes drive partial / full / eof outcomes ---------- - @test fn fixedread() void = { let arr: [8]u8; arr[0] = 1u8; arr[1] = 2u8; arr[2] = 3u8; arr[3] = 4u8; @@ -73,8 +69,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- fixedwritecases: full-fit / exact-fill / partial / overflow ------------- - @test fn fixedwritecases() void = { let dst: [16]u8; let st: memio.stream = memio.fixed(dst[0:16]); @@ -130,7 +124,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- fixedwritefull: the full-sink nomem contract (memio.ww:190) ------- // A write that exactly fills the sink succeeds; any further non-empty // write into the full sink returns nomem, not a 0-byte success // (ref/hare/memio/stream.ha:161). A zero-length sink is full from the @@ -165,8 +158,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { }; }; -// ---- dynamicgrowcases: every cap doubling exercised --------------------- - // Drive grow 0 → 8 → 16 → 32 by writing sized chunks. Verify // accumulated `pos` after each step. @test fn dynamicgrowcases() void = { @@ -207,8 +198,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- dynamicreset: write / reset / write cycles ------------------------- - // op=0 writes `ln` bytes from a rolling source; op=1 resets and ignores // ln. After each row the accumulated len must equal `want`. @test fn dynamicreset() void = { @@ -255,8 +244,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- borrowedread: under / exact / over / 0-byte ------------------------ - @test fn borrowedreadcases() void = { let arr: [6]u8; arr[0]=0u8; arr[1]=1u8; arr[2]=2u8; arr[3]=3u8; arr[4]=4u8; arr[5]=5u8; @@ -289,8 +276,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { }; }; -// ---- stringview: len + endpoints track pos across appends --------------- - @test fn stringview() void = { let st: memio.stream = memio.dynamic(); let s: io.stream = &st.vt; @@ -327,8 +312,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- dynamicfromseed: ownership-transferred seed, read then write ------- - @test fn dynamicfromseed() void = { // Build a heap-allocated seed via append (rt_ensure path), then // hand ownership to memio. dynamicclose then frees `seed.cap` @@ -381,8 +364,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { match (c) { case void => {}; case let e: io.error => abort(); }; }; -// ---- seekcases: SET/CUR/END × in-bounds/OOB over one fixed stream -------- - // Sequential rows over one 8-byte fixed stream; CUR rows depend on the // cursor left by earlier rows. want = resulting pos for valid rows, // -1 = errors.invalid expected. After EVERY row an io.tell readback @@ -467,8 +448,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { }; }; -// ---- emptyseek: every whence over a 0-length buffer ---------------------- - @test fn emptyseek() void = { let arr: [1]u8; arr[0] = 0u8; @@ -505,8 +484,6 @@ fn putstr(s: str, into: []u8, off: i32) i32 = { }; }; -// ---- dynamicseek: rewind-and-reread over written data -------------------- - // The dynamic vtable wires the same seekfn; bounds run against the // LOGICAL length (m.len), not capacity (Hare: len(s.buf), // ref/hare/memio/stream.ha:131,136). diff --git a/lib/net/net.ww b/lib/net/net.ww index 449684ac..488a34a2 100644 --- a/lib/net/net.ww +++ b/lib/net/net.ww @@ -1,7 +1,5 @@ -// net — minimal TCP. Sketched against the Linux syscall numbers -// 41 (socket), 42 (connect), 43 (accept), 49 (bind), 50 (listen). -// Real applications will want addrinfo + DNS; we leave that to -// higher layers. +// net — minimal TCP. Real applications will want addrinfo + DNS; we +// leave that to higher layers. package net; diff --git a/lib/os/os.ww b/lib/os/os.ww index 4bdcf383..73e9feda 100644 --- a/lib/os/os.ww +++ b/lib/os/os.ww @@ -1,6 +1,5 @@ -// os — process and filesystem facade. The body of each call lands -// either in libwwrt.a (rt_syscall trampoline) or libc bindings, -// depending on how the program was linked. +// The body of each call lands either in libwwrt.a (rt_syscall +// trampoline) or libc bindings, depending on how the program was linked. package os; @@ -155,10 +154,8 @@ export fn close(fd: i32) i32 = { return syscall1(nr.CLOSE, fd: i64): i32; }; -// dup2(2): make `newfd` refer to the same description as `oldfd`, -// closing `newfd` first if open. Returns `newfd` on success or a -// negative errno. Used by w6c_ww to redirect stdout into an output -// file without changing the cgen emit path. +// Used by w6c_ww to redirect stdout into an output file without +// changing the cgen emit path. export fn dup2(oldfd: i32, newfd: i32) i32 = { return syscall2(nr.DUP2, oldfd: i64, newfd: i64): i32; }; @@ -208,9 +205,8 @@ export fn tryopen(path: str, flags: flag, mode: i32) (i32 | oserror) = { return fd; }; -// lseek — set/inspect the fd's position. Returns the new offset or -// a negative errno. We use this for fstat-free file-size discovery -// (open ⇒ lseek to end ⇒ lseek back). +// Used for fstat-free file-size discovery (open ⇒ lseek to end ⇒ +// lseek back). export fn lseek(fd: i32, off: i64, w: whence) i64 = { return syscall3(nr.LSEEK, fd: i64, off, (w as i32): i64); }; @@ -273,7 +269,6 @@ export fn strerror(err: errno) str = { return "Unknown error"; }; -// filesize — byte length of an open fd via lseek-to-end-and-back. export fn filesize(fd: i32) (i64 | oserror) = { let end: i64 = lseek(fd, 0i64, whence.END); if (end < 0) { return end: oserror; }; @@ -282,9 +277,8 @@ export fn filesize(fd: i32) (i64 | oserror) = { return end; }; -// readall — keep reading until `n` bytes have arrived or the fd -// closes early. Hare name (io::readall); the buffer is caller- -// supplied, matching the Plan 9 subset convention. +// Hare name (io::readall); the buffer is caller-supplied, matching +// the Plan 9 subset convention. export fn readall(fd: i32, buf: *u8, n: u64) (i64 | oserror) = { let got: u64 = 0u64; for (got < n) { @@ -296,8 +290,7 @@ export fn readall(fd: i32, buf: *u8, n: u64) (i64 | oserror) = { return got: i64; }; -// writeall — keep writing until `n` bytes have been accepted or the -// fd refuses progress. Hare name (io::writeall). +// Hare name (io::writeall). export fn writeall(fd: i32, buf: *u8, n: u64) (i64 | oserror) = { let sent: u64 = 0u64; for (sent < n) { @@ -309,8 +302,6 @@ export fn writeall(fd: i32, buf: *u8, n: u64) (i64 | oserror) = { return sent: i64; }; -// ---- process and filesystem helpers used by the `ww` driver ---------- - // access(2): returns 0 if the file is reachable, negative errno // otherwise. mode is the bitset described in (F_OK=0). // Mirrors Hare's os::access (ref/hare/os/+linux/fs.ha:access). @@ -531,8 +522,6 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { return syscall3(nr.GETDENTS64, fd: i64, buf: i64, n: i64); }; -// ---- environment ------------------------------------------------------ - // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer // into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT @@ -688,8 +677,6 @@ export fn args() []str = { return r; }; -// ---- stat / lstat / fstat / exists ----------------------------------- -// // Ports of Hare's stat family (ref/hare/fs/fs.ha:172,196 + // ref/hare/sys/+linux/stat.ha:24-58). The Hare surface returns // `filestat` by value; ww's cgreturn ABI tops out at 24B today (see @@ -830,8 +817,7 @@ type kstat = struct { let emptypath: [1]u8 = [0u8]; // fillfilestat — copy a 144B kstat into the 80B Hare-shaped -// filestat. Internal helper used by all three public entry points. -// Mirrors Hare's st_to_filestat (ref/hare/os/+linux/dirfdfs.ha:259): +// filestat. Mirrors Hare's st_to_filestat (ref/hare/os/+linux/dirfdfs.ha:259): // newfstatat populates every field, so the mask is the OR-fold of // all seven Hare stat_mask bits. fn fillfilestat(out: *filestat, k: *kstat) void = { diff --git a/lib/os/os_test.ww b/lib/os/os_test.ww index 62b2a897..74e22f30 100644 --- a/lib/os/os_test.ww +++ b/lib/os/os_test.ww @@ -1,8 +1,6 @@ -// ostest — exercises lib/os surface that doesn't have a dedicated -// test elsewhere. Covers [[os.getenv]] and a direct -// [[os.alloc]] / [[os.free]] roundtrip. memio's tests indirectly -// cover alloc/free; the direct row here pins the FFI shape under -// lib/os itself so future bindings refactors can't quietly drift. +// memio's tests indirectly cover alloc/free; the direct row here pins +// the FFI shape under lib/os itself so future bindings refactors can't +// quietly drift. // // getenv env contract (ww ships no setenv primitive, deliberately): // @@ -45,8 +43,6 @@ fn ostestwait(pid: i32, status: *i32) i32 = { return -1; }; -// ---- getenv: set var → matching value ------------------------------- - @test fn test_getenv_set() void = { let r = os.getenv("WW_TEST_GETENV"); match (r) { @@ -57,11 +53,9 @@ fn ostestwait(pid: i32, status: *i32) i32 = { }; }; -// ---- getenv: empty value (set but zero-length) ---------------------- -// // POSIX permits an env var with an empty value (`name=` in environ). // getenv must return the empty str, NOT void — void is reserved for -// "name not present at all". This row exercises the boundary. +// "name not present at all". @test fn test_getenv_empty() void = { let r = os.getenv("WW_TEST_EMPTY"); @@ -73,8 +67,6 @@ fn ostestwait(pid: i32, status: *i32) i32 = { }; }; -// ---- getenv: unset var → void --------------------------------------- - @test fn test_getenv_unset() void = { let r = os.getenv("WW_TEST_NOT_SET"); match (r) { @@ -83,8 +75,6 @@ fn ostestwait(pid: i32, status: *i32) i32 = { }; }; -// ---- getenv: prefix-collision guard --------------------------------- -// // Probes that "WW_TEST_GETEN" (a prefix of WW_TEST_GETENV) doesn't // match. Without the explicit `entry[name.len] == '='` check in // getenv, a naive prefix matcher would return the value of any @@ -103,8 +93,6 @@ fn ostestwait(pid: i32, status: *i32) i32 = { }; }; -// ---- getenvs: direct non-vacuous coverage of the []str shape -------- -// // getenvs() is public API (task #28) and the single env walker getenv // routes through. getenv's cases exercise the walk transitively, but // none asserts the []str RETURN shape — its count or "NAME=VALUE" entry @@ -139,8 +127,6 @@ fn ostestwait(pid: i32, status: *i32) i32 = { }; }; -// ---- alloc/free: mmap-backed runtime allocator ---------------------- -// // Direct round-trip. Write-then-read-back proves the returned page is // dereferenceable. A miscompiled binding (wrong arg order, wrong ABI, // etc.) would either fault or return zero here. diff --git a/lib/os/stat_test.ww b/lib/os/stat_test.ww index bfbde8a5..469af6f2 100644 --- a/lib/os/stat_test.ww +++ b/lib/os/stat_test.ww @@ -1,7 +1,6 @@ -// stattest — exercises [[os.stat]] / [[os.lstat]] / [[os.fstat]] / -// [[os.exists]] against a scratch tree each row arranges itself -// under [[temp.dir]] (Hare's own idiom: os tests self-arrange in a -// temp dir), so the suite passes bare with no external driver: +// Each row arranges its own scratch tree under [[temp.dir]] (Hare's +// own idiom: os tests self-arrange in a temp dir), so the suite +// passes bare with no external driver: // // /regfile regular file, 11 bytes "hello world", 0644 // /symlink → ./regfile (relative symlink) @@ -66,14 +65,6 @@ fn istype(m: os.mode, t: os.mode) bool = { return ((m as u32) & 61440u32) == (t as u32); }; -// ---- stat: regular file -------------------------------------------- -// -// Pinned bytes are "hello world" (11 bytes). We verify: -// - mask is fully set (newfstatat fills everything) -// - mode's type bits == REG -// - sz == 11 -// - inode is non-zero (real fs entry, not synthetic) - @test fn test_stat_regfile() void = { let t: tree; mktree(&t); @@ -112,8 +103,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- stat: directory ------------------------------------------------ - @test fn test_stat_subdir() void = { let t: tree; mktree(&t); @@ -127,8 +116,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- stat: missing path → oserror ENOENT --------------------------- - @test fn test_stat_noent() void = { let t: tree; mktree(&t); @@ -143,11 +130,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- stat (follow) vs lstat (no-follow) on a symlink ---------------- -// -// stat follows the link → reports the regfile (REG, 11 bytes). -// lstat does NOT follow → reports the link itself (LINK). - @test fn test_stat_symlink_follow() void = { let t: tree; mktree(&t); @@ -175,8 +157,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- fstat: open a file and stat by fd ------------------------------ - @test fn test_fstat_regfile() void = { let t: tree; mktree(&t); @@ -194,8 +174,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- exists: true on regfile/dir/symlink, false on noent ------------ - @test fn test_exists_regfile() void = { let t: tree; mktree(&t); @@ -217,8 +195,6 @@ fn istype(m: os.mode, t: os.mode) bool = { rmtree(&t); }; -// ---- ENAMETOOLONG: kpath rejects paths >= PATH_MAX ------------------- -// // kpath copies into a single [PATH_MAX]u8 buffer and reserves one byte // for the NUL terminator (`p.len + 1 >= PATH_MAX` → reject). The // rejection surfaces as `oserror = -36` (ENAMETOOLONG) on (... | diff --git a/lib/path/path.ww b/lib/path/path.ww index d6cf306c..443dd1c5 100644 --- a/lib/path/path.ww +++ b/lib/path/path.ww @@ -152,8 +152,6 @@ export fn set(buf: *buffer, items: str...) (str | error) = { return push(buf, items...); }; -// ---- c3 buffer-ops (ref/hare/path/buffer.ha, stack.ha) ---------------- - // lifts Hare's fn-`static let buf` (buffer.ha:53-56): statically allocated, // overwritten on the next local() call. strconv *tos-buf precedent. let localbuf: [MAX]u8 = [0...]; @@ -225,7 +223,6 @@ export fn parent(buf: *buffer) (str | error) = { return strings.frombytes(buf.buf[0:newend]); }; -// ---- POSIX jail (ref/hare/path/posix.ha) ------------------------------ // POSIX-compliant dirname/basename. They do NOT normalize the input and // operate on plain str (no buffer), so they sit apart from the stack // paradigm above — same POSIX-complaint as posix.ha:7-11. diff --git a/lib/regex/regex_test.ww b/lib/regex/regex_test.ww index 47a19fa7..243e4d20 100644 --- a/lib/regex/regex_test.ww +++ b/lib/regex/regex_test.ww @@ -564,8 +564,6 @@ type fdexp = struct { }; -// ---- fold 3: anchors / escape / postfix / alternation ---------------- - // instsig — flatten an inst for the table-driven program pins below: // kind base + payload. Takes the 56B inst by value (the #19-landed // is_consuming_inst shape). @@ -821,8 +819,6 @@ type cerow = struct { }; }; -// ---- fold 4: bracket expressions -------------------------------------- - // Emitted-program pins for the `[..]` arm: the charset inst lands where // a literal would (and composes with fold-3's postfix/anchors), the // charsets table grows one entry per bracket, negation rides @@ -1173,8 +1169,6 @@ type cscase = struct { }; }; -// ---- fold 5a: capture groups ------------------------------------------ - // The fold-5a compile-error surface, exact texts. ")" and "(" are // Hare's own ERROR fixtures (+test.ha:276/606); "a("/"a)" graduate // here from the metachar-loud table with their real texts. The @@ -1464,8 +1458,6 @@ type smcase = struct { }; }; -// ---- fold 5b: repetition ---------------------------------------------- - // 5b compile-error rows end-to-end through compile() — the two // parse_repetition texts surface verbatim (+test.ha:461-463 ERROR // rows). "a{" is the GRADUATED metachar-loud row: with `{` ported the @@ -1693,8 +1685,6 @@ type smcase = struct { }; }; -// ---- fold 6: POSIX character classes --------------------------------- - // compile error: `[[:` with no valid class name // ref/hare/regex/+test.ha — no direct cite; error string from // regex.ha:203 "No character class after '[:'". diff --git a/lib/shlex/shlex.ww b/lib/shlex/shlex.ww index 12f63df2..9b2b4373 100644 --- a/lib/shlex/shlex.ww +++ b/lib/shlex/shlex.ww @@ -2,14 +2,6 @@ // (ref/hare/shlex/{split.ha,escape.ha}) using ww byte-indexed cursors // in place of Hare's strings::iterator. // -// Surface today: -// -// shlex.syntaxerr — !void; bad shell syntax -// shlex.strerror(syntaxerr) — "Invalid shell syntax" -// shlex.split(in: str) — tokenize; returns ([]str | syntaxerr) -// shlex.quote(io.stream, s) — write `s` shell-quoted to a sink -// shlex.quotestr(s: str) str — quote into a fresh str -// // Owning model: split() returns a fresh `[]str` of strings.dup'd // elements; release with [[strings.freeall]] (Hare's natural disposer // shape). quotestr() returns an os.alloc'd str; release via @@ -227,7 +219,6 @@ export fn split(in: str) ([]str | syntaxerr) = { dirty = true; if (r == ' ' || r == '\t' || r == '\n') { - // Collapse a run of whitespace. let inner: bool = true; for (inner) { if (pos >= in.len) { inner = false; } diff --git a/lib/shlex/shlex_test.ww b/lib/shlex/shlex_test.ww index 48f21213..2222601a 100644 --- a/lib/shlex/shlex_test.ww +++ b/lib/shlex/shlex_test.ww @@ -1,6 +1,3 @@ -// shlextest — exercises lib/shlex. Run with -// `out/bin/ww run lib/shlex/shlextest.ww`. -// // Two cohorts, grouped Hare-style — one @test fn per cohort, table- // driven inside via per-arity helpers: // @@ -110,8 +107,6 @@ fn checkquote(in: str, expected: str) void = { let _c: (void | io.error) = io.close(snk); }; -// ---- split: Hare's @test fn split() table -------------------------- -// // 9 success rows + 3 syntaxerr rows ported VERBATIM from // ref/hare/shlex/+test.ha; plus one ww-specific edge (empty input → // empty []str) confirmed by drew. @@ -146,8 +141,6 @@ fn checkquote(in: str, expected: str) void = { checkempty(""); }; -// ---- quote: Hare's testquote rows + the empty-input edge ---------- -// // 4 rows from ref/hare/shlex/+test.ha @test fn quote(). The empty- // input row (→ `''`) is implementation-specific (Hare's testquote // doesn't cover it) but is documented behaviour per shlex.ww's @@ -163,16 +156,12 @@ fn checkquote(in: str, expected: str) void = { checkquote("@%+=:,./-", "@%+=:,./-"); }; -// ---- quotestr ------------------------------------------------------ - @test fn test_quotestr() void = { let r: str = shlex.quotestr("hello world"); assert(!(!streq(r, "'hello world'"))); // leak r — short-lived test process, same precedent as fnmatchtest. }; -// ---- strerror ------------------------------------------------------ - @test fn test_strerror() void = { let e: shlex.syntaxerr; let s: str = shlex.strerror(e); diff --git a/lib/strconv/decimal.ww b/lib/strconv/decimal.ww index 106f1ba0..38c947ef 100644 --- a/lib/strconv/decimal.ww +++ b/lib/strconv/decimal.ww @@ -1,6 +1,5 @@ -// strconv — arbitrary-precision decimal engine for float↔string -// conversion. Mirrors ref/hare/strconv/decimal.ha (Hare in turn ports -// Go's lib/strconv/decimal.go). Pure integer arithmetic; no f32/f64 +// Mirrors ref/hare/strconv/decimal.ha (Hare in turn ports Go's +// lib/strconv/decimal.go). Pure integer arithmetic; no f32/f64 // references (#121 residual-guard SAFE). // // Spelling divergences from Hare (mechanical, ww-side parser shape): diff --git a/lib/strconv/ftos.ww b/lib/strconv/ftos.ww index e3c36bec..26a64404 100644 --- a/lib/strconv/ftos.ww +++ b/lib/strconv/ftos.ww @@ -1,4 +1,3 @@ -// strconv — float→string via Ryū (shortest round-trippable decimal). // Mirrors ref/hare/strconv/ftos_ryu.ha (the algorithm core) + // ref/hare/strconv/ftos.ha:432 (the f64tos driver). Ryū: Ulf Adams, // https://doi.org/10.1145/3192366.3192369 — Hare translated it from the @@ -339,12 +338,12 @@ fn f64todecf64(mantissa: u64, exponent: u32) decf64 = { return decf64 { exponent = (exp: i64), mantissa = output }; }; -// ==== f32 Ryū sub-path (ftos_ryu.ha). The *32 helpers below mirror their +// f32 Ryū sub-path (ftos_ryu.ha). The *32 helpers below mirror their // u64 siblings at 32-bit width; they reuse the SHARED f64computeinvpow5/ // f64computepow5 (and thus the f64 SPLIT2 tables) per ftos_ryu.ha — there // is no separate f32 table. Same scalar-PARAM-mutation → copy-to-local, // comma-split, expr-yield → block divergences as the f64 path -// above. ==== +// above. // ref/hare/strconv/ftos_ryu.ha:52. Largest p with 5^p | value (32-bit). fn pow5fac32(v: u32) u32 = { @@ -523,13 +522,13 @@ fn f32todecf32(mantissa: u32, exponent: u32) decf32 = { return decf32 { mantissa = output, exponent = (exp: i64) }; }; -// ==== G-format encode layer (ftos.ha) — only the ffmt::G / prec=void / +// G-format encode layer (ftos.ha) — only the ffmt::G / prec=void / // fflags::NONE-REACHABLE logic. The SHOW_POINT/precision/E-vs-uppercase // arms (ftos.ha:88-105, 127-145, 170-213's zeros/caps) are UNREACHABLE // for G/void/NONE (ffpoint(NONE)=false, prec is never uint, f is always // G) and are NOT ported — porting them stubbed would be untested dead // code. The parametric ftosf/ffmt/fflags surface is deferred (task #64; -// needs a parametric consumer + io::handle + #158). ==== +// needs a parametric consumer + io::handle + #158). // ref/hare/strconv/ftos.ha:49. Decimal digit-count of n (n <= 1e17). fn declen(n: u64) uint = { diff --git a/lib/strconv/ftos_data.ww b/lib/strconv/ftos_data.ww index c989f0b2..26907491 100644 --- a/lib/strconv/ftos_data.ww +++ b/lib/strconv/ftos_data.ww @@ -1,4 +1,3 @@ -// strconv — Ryū float→string lookup tables + bit-count constants. // Mirrors ref/hare/strconv/ftos_ryu.ha:159-222 byte-exact. Pure data // fold (strconv #106 fold-5): no logic, consumed by ftos.ww's // f64computeinvpow5 / f64computepow5 (the Ryū power-of-five cores). diff --git a/lib/strconv/ftos_test.ww b/lib/strconv/ftos_test.ww index 105e5d9f..ae85bf8e 100644 --- a/lib/strconv/ftos_test.ww +++ b/lib/strconv/ftos_test.ww @@ -1,6 +1,3 @@ -// ftostest — exercises lib/strconv/ftos.ww (Hare ftos.ha / ftos_ryu.ha -// Ryū port). -// // Ports ref/hare/strconv/+test/ftos_test.ha's ffmt::G / prec=void / // fflags::NONE rows (the f64tos cases) verbatim — these are exactly // strconv.f64tos's output. encode_f_dec is covered by 13.37/1100/0.011/… diff --git a/lib/strconv/int_test.ww b/lib/strconv/int_test.ww index 76027e5a..f0766843 100644 --- a/lib/strconv/int_test.ww +++ b/lib/strconv/int_test.ww @@ -1,6 +1,3 @@ -// inttest — exercises lib/strconv integer parse: parseint / stoi64 / -// stou64 / the iN/uN width wrappers. -// // Verbatim port of ref/hare/strconv/stoi.ha:56-86 (stoi/stoi_bases) and // stou.ha:116-138 (stou/stou_bases). Hare's strconv integer tests are // flat assert SEQUENCES, not row-array tables — mirrored here as inline @@ -210,7 +207,6 @@ fn ck_uint_ovf(id: i32, s: str, b: base) void = { ck_uint(62, "110101", base.BIN, 53u64: uint); // 0b110101 }; -// ---- format side: u64tos / i64tos / machine-word wrappers ------------ // Verbatim ports of ref/hare/strconv/utos.ha:74-103 (utos/utos_bases) and // itos.ha:54-87 (itos/itos_bases) — Hare's format tests are flat assert // sequences too. Radix-literal inputs are written in DECIMAL (ww value diff --git a/lib/strconv/stof.ww b/lib/strconv/stof.ww index bfce9c63..c8c2d50b 100644 --- a/lib/strconv/stof.ww +++ b/lib/strconv/stof.ww @@ -1,6 +1,6 @@ -// strconv — string-to-float. Mirrors ref/hare/strconv/stof.ha -// (Hare in turn adapts Go): Eisel-Lemire fast path [1] with the -// Simple-Decimal-Conversion slow path [2] (decimal.ww) as fallback. +// Mirrors ref/hare/strconv/stof.ha (Hare in turn adapts Go): +// Eisel-Lemire fast path [1] with the Simple-Decimal-Conversion slow +// path [2] (decimal.ww) as fallback. // [1]: https://nigeltao.github.io/blog/2020/eisel-lemire.html // [2]: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html // diff --git a/lib/strconv/stof_data.ww b/lib/strconv/stof_data.ww index 1ce03e15..2bf995b3 100644 --- a/lib/strconv/stof_data.ww +++ b/lib/strconv/stof_data.ww @@ -1,5 +1,4 @@ -// strconv — stof/ftos lookup tables. Mirrors ref/hare/strconv/stof_data.ha -// byte-exact. Pure-data fold (strconv #106 fold-2, was fold-3 before drew +// Mirrors ref/hare/strconv/stof_data.ha byte-exact. Pure-data fold (strconv #106 fold-2, was fold-3 before drew // re-sequenced 2026-05-26): no logic, exercised transitively when fold-3's // `leftshift_newdigits` lands (ref/hare/strconv/decimal.ha:35). // diff --git a/lib/strconv/stof_test.ww b/lib/strconv/stof_test.ww index e7efbc69..6fcdc326 100644 --- a/lib/strconv/stof_test.ww +++ b/lib/strconv/stof_test.ww @@ -1,5 +1,3 @@ -// stoftest — exercises lib/strconv/stof.ww (Hare stof.ha port). -// // Ports ref/hare/strconv/stof.ha's @test vectors (stof64 / stof32 / // stofhex). Comparisons are BIT-level (math.f64bits / f32bits) so a // sign flip (-0.0 vs 0.0) or a 1-ulp miss fails the row rather than @@ -14,8 +12,6 @@ import strconv; import math; -// ---- unwrap helpers (bit-exact value checks) ------------------------- - fn chk64(s: str, b: base, want: f64) bool = { match (stof64(s, b)) { case let v: f64 => { return math.f64bits(v) == math.f64bits(want); }; @@ -89,7 +85,6 @@ fn nan32(s: str) bool = { return false; }; -// ---- stof64 ---------------------------------------------------------- // ref/hare/strconv/stof.ha:530. @test fn stof64_dec() void = { @@ -141,7 +136,6 @@ fn nan32(s: str) bool = { assert(!(!nan64("naN"))); }; -// ---- stof32 ---------------------------------------------------------- // ref/hare/strconv/stof.ha:560. @test fn stof32_dec() void = { @@ -180,7 +174,6 @@ fn nan32(s: str) bool = { assert(!(!chk32("9.19100241453305036800e+20", base.DEC, 9.19100241453305036800e+20f32))); }; -// ---- stofhex --------------------------------------------------------- // ref/hare/strconv/stof.ha:590. Hex-float surface-form literals (0x1.fp-2, // math::F64_MAX_NORMAL, …) are spelled as IEEE-754 bit patterns since ww // has no hex-float literal lexer / no F*_MAX_NORMAL math consts. diff --git a/lib/strconv/strconv.ww b/lib/strconv/strconv.ww index 04c346b7..b981b147 100644 --- a/lib/strconv/strconv.ww +++ b/lib/strconv/strconv.ww @@ -1,5 +1,3 @@ -// strconv — number↔string conversions. -// // Mirrors Hare's strconv:: surface. The *tos functions return a // `const str` view into a module-level buffer that is overwritten on // the next call to the same function; callers must copy the bytes if @@ -71,7 +69,7 @@ let lut_lower: [16]rune = [ // fidelity; the initial value is irrelevant (only the freshly-written // prefix is ever read) but the fill form is exercised (probed: emits // byte-identically cross-stage). -let u64tos_buf: [64]u8 = [0...]; // 64 binary digits +let u64tos_buf: [64]u8 = [0...]; // u64tos — convert u to a base-b numeric string. Returns a view into // `u64tos_buf`, overwritten on the next call; copy via strings.dup to @@ -114,7 +112,7 @@ export fn u64tos(u: u64, b: base) str = { // i64tos_buf — independent from u64tos_buf so i64tos's own u64tos call // (the magnitude) doesn't clobber the in-flight result. 65 = 64 digits // plus the leading '-'. Hare's `static let buf: [65]u8` (itos.ha:18). -let i64tos_buf: [65]u8 = [0...]; // 64 binary digits plus '-' +let i64tos_buf: [65]u8 = [0...]; // i64tos — convert i to a base-b numeric string. Returns a view into // `i64tos_buf`. Verbatim port of ref/hare/strconv/itos.ha:10-32. diff --git a/lib/strings/compare_test.ww b/lib/strings/compare_test.ww index bd635d56..1430fbcc 100644 --- a/lib/strings/compare_test.ww +++ b/lib/strings/compare_test.ww @@ -1,6 +1,4 @@ -// comparetest — exercises strings.compare. A failing row aborts -// via the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/strings/compare.ha. +// Vectors mirror ref/hare/strings/compare.ha (task #5 @test conversion). package strings_test; diff --git a/lib/strings/concat_test.ww b/lib/strings/concat_test.ww index a7d77c12..c7505c09 100644 --- a/lib/strings/concat_test.ww +++ b/lib/strings/concat_test.ww @@ -58,7 +58,6 @@ import os; }; }; -// ---- join ------------------------------------------------------------- // ref/hare/strings/concat.ha:64. Rows mirror Hare's @test fn join // (0-arg, 1-arg, empty-sep, 3-arg.) plus 2-arg, all-empties, long sep, // multibyte, empty-mid (delim still inserted around the empty slot). @@ -111,4 +110,3 @@ import os; i += 1; }; }; - diff --git a/lib/strings/contains_test.ww b/lib/strings/contains_test.ww index 0e257d8a..f89eafc0 100644 --- a/lib/strings/contains_test.ww +++ b/lib/strings/contains_test.ww @@ -1,6 +1,4 @@ -// containstest — exercises strings.contains. A failing row aborts -// via the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/strings/contains.ha. +// Vectors mirror ref/hare/strings/contains.ha (task #5 @test conversion). package strings_test; diff --git a/lib/strings/dup_test.ww b/lib/strings/dup_test.ww index 7be07ea6..f1d76891 100644 --- a/lib/strings/dup_test.ww +++ b/lib/strings/dup_test.ww @@ -27,7 +27,6 @@ import os; defer os.free(m.ptr: *void, m.len: u64); }; -// ---- dupall ----------------------------------------------------------- // ref/hare/strings/dup.ha:55 (#6). Element reads go through // `&toks.ptr[i]: *str` // per the splitn cases (16B element copy gap, cgen.c:6515). @@ -109,4 +108,3 @@ import os; case nomem => { abort(); }; }; }; - diff --git a/lib/strings/iter_test.ww b/lib/strings/iter_test.ww index 1de072bb..801c969e 100644 --- a/lib/strings/iter_test.ww +++ b/lib/strings/iter_test.ww @@ -131,7 +131,6 @@ import encoding.utf8; }; }; -// ---- prev / riter / iterstr / slice / position ----------------------- // ref/hare/strings/iter.ha:84-127. The Hare @test fn iter body uses // `s = riter(...)` mid-test to swap the iterator's direction; ww's // sret-into-existing-slot path handles that fine (probed pre-port). @@ -302,4 +301,3 @@ import encoding.utf8; match (strings.next(&rit)) { case let r: rune => void; case utf8.done => { abort(); }; }; assert(!(!streq(strings.iterstr(&rit), "he"))); }; - diff --git a/lib/strings/strings.ww b/lib/strings/strings.ww index 7977f8c0..95af719b 100644 --- a/lib/strings/strings.ww +++ b/lib/strings/strings.ww @@ -1,5 +1,4 @@ -// strings — operations over str ({ptr,len}). Hare port; see -// ref/hare/strings/. +// Hare port; see ref/hare/strings/. // // Documented divergences from Hare: // @@ -30,8 +29,8 @@ import os; import rt; import types; -// toutf8 — borrowed []u8 view of `s`. ref/hare/strings/utf8.ha:29. -// `cap` equals `len`; the slice does not own a separate allocation. +// ref/hare/strings/utf8.ha:29. `cap` equals `len`; the slice does +// not own a separate allocation. export fn toutf8(s: str) []u8 = { let r: []u8; r.ptr = s.ptr; @@ -40,8 +39,8 @@ export fn toutf8(s: str) []u8 = { return r; }; -// frombytes — borrowed str view of `in`. Pure reinterpret per -// CLAUDE.md rule 9 carve-out; ref/hare/strings/utf8.ha:10. +// Pure reinterpret per CLAUDE.md rule 9 carve-out; +// ref/hare/strings/utf8.ha:10. export fn frombytes(in: []u8) str = { let r: str; r.ptr = in.ptr; @@ -49,9 +48,8 @@ export fn frombytes(in: []u8) str = { return r; }; -// compare — three-way bytewise codepoint-order comparison. Return is -// a sign (neg/zero/pos), not an index, so it tracks Hare's `int` -// rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12. +// Return is a sign (neg/zero/pos), not an index, so it tracks Hare's +// `int` rather than the str-index i32 (#8). ref/hare/strings/compare.ha:12. export fn compare(a: str, b: str) int = { let n: i32 = a.len; if (b.len < n) { n = b.len; }; @@ -63,8 +61,8 @@ export fn compare(a: str, b: str) int = { return (a.len: int) - (b.len: int); }; -// dup — allocate a fresh copy of `s`. Caller releases with -// `os.free(r.ptr, r.len: u64)`. ref/hare/strings/dup.ha:7. +// Caller releases with `os.free(r.ptr, r.len: u64)`. +// ref/hare/strings/dup.ha:7. export fn dup(s: str) str = { let r: str; r.ptr = nil; @@ -77,9 +75,7 @@ export fn dup(s: str) str = { return frombytes(buf); }; -// dupall — fresh `[]str` whose elements are independent copies of -// `s`'s elements. Caller releases via [[freeall]]. -// ref/hare/strings/dup.ha:26 (#6). +// Caller releases via [[freeall]]. ref/hare/strings/dup.ha:26 (#6). // // Hare gates the per-element dup behind `?` and rolls back via // `defer if (!ok) freeall(newsl)`. ww has no `defer if`; more @@ -113,8 +109,6 @@ export fn dupall(s: []str) ([]str | nomem) = { return newsl; }; -// freeall — release each element + the slice header. The natural -// disposer for any `[]str` of dup'd elements (e.g. shlex.split). // ref/hare/strings/dup.ha:38. // // Empty elements (`{nil, 0}` from a zero-length dup) are skipped: @@ -135,8 +129,7 @@ export fn freeall(s: []str) void = { }; }; -// concat — fresh allocation containing each element of `strs` in -// order. Caller releases with `os.free(r.ptr, r.len: u64)`. +// Caller releases with `os.free(r.ptr, r.len: u64)`. // ref/hare/strings/concat.ha:5. Hare's `nomem` return is dropped: // `os.alloc` aborts on OOM. export fn concat(strs: str...) str = { @@ -163,8 +156,7 @@ export fn concat(strs: str...) str = { return frombytes(buf); }; -// join — fresh allocation with `delim` placed between each element of -// `strs`. Caller releases with `os.free(r.ptr, r.len: u64)`. +// Caller releases with `os.free(r.ptr, r.len: u64)`. // ref/hare/strings/concat.ha:46. Hare's `nomem` return is dropped: // `os.alloc` aborts on OOM. export fn join(delim: str, strs: str...) str = { @@ -203,9 +195,8 @@ export fn join(delim: str, strs: str...) str = { return frombytes(buf); }; -// utf8bytelenbounded — walk `it` forward `end` runes and return the -// resulting byte offset. ref/hare/strings/sub.ha:10. Aborts on -// short input per Hare's contract for the rune-wise [[sub]]. +// ref/hare/strings/sub.ha:10. Aborts on short input per Hare's +// contract for the rune-wise [[sub]]. fn utf8bytelenbounded(it: *iterator, end: i32) i32 = { let i: i32 = 0; for (i < end) { @@ -218,10 +209,11 @@ fn utf8bytelenbounded(it: *iterator, end: i32) i32 = { return it.offs; }; -// sub — borrowed substring [start, end) where start/end are rune -// indices. ref/hare/strings/sub.ha:30. Hare's 2-arg `sub(s, start)` +// Borrowed substring; start/end are rune indices; byte-indexed +// counterpart [[bytesub]]. +// ref/hare/strings/sub.ha:30. Hare's 2-arg `sub(s, start)` // defaulting end=END is omitted: ww has no default-parameter syntax -// (filed as #37). Byte-indexed counterpart: [[bytesub]]. +// (filed as #37). export fn sub(s: str, start: i32, end: i32) str = { assert(start <= end, "strings.sub: start is higher than end"); let it: iterator = iter(s); @@ -233,8 +225,9 @@ export fn sub(s: str, start: i32, end: i32) str = { return r; }; -// bytesub — borrowed substring [start, end) where start/end are byte -// offsets. ref/hare/strings/sub.ha:59 (#7). Returns `utf8.invalid` if +// Borrowed substring; start/end are byte offsets, unlike the +// rune-wise [[sub]]. +// ref/hare/strings/sub.ha:59 (#7). Returns `utf8.invalid` if // either endpoint lands on a continuation byte (would split a // codepoint); the equivalent Hare predicate is `s[i] & 0xc0 == 0x80` // at ref/hare/strings/sub.ha:72-73. @@ -253,9 +246,8 @@ export fn bytesub(s: str, start: i32, end: i32) (str | utf8.invalid) = { return r; }; -// runebytes — encode `r` into caller's `scratch` (must hold 4 bytes) -// and return the borrowed slice trimmed to the encoded length. Hare -// inlines the same shape at ref/hare/strings/index.ha:132. +// `scratch` must hold 4 bytes; the return borrows it. Hare inlines +// the same shape at ref/hare/strings/index.ha:132. fn runebytes(scratch: []u8, r: rune) []u8 = { let n: i32 = utf8.encoderune(scratch, r); let s: []u8; @@ -265,7 +257,6 @@ fn runebytes(scratch: []u8, r: rune) []u8 = { return s; }; -// hasprefix — true iff `in` begins with `prefix`. // ref/hare/strings/suffix.ha:8. export fn hasprefix(in: str, prefix: (str | rune)) bool = { let scratch: [4]u8; @@ -276,7 +267,6 @@ export fn hasprefix(in: str, prefix: (str | rune)) bool = { return bytes.hasprefix(toutf8(in), p); }; -// hassuffix — true iff `in` ends with `suff`. // ref/hare/strings/suffix.ha:26. export fn hassuffix(in: str, suff: (str | rune)) bool = { let scratch: [4]u8; @@ -287,8 +277,7 @@ export fn hassuffix(in: str, suff: (str | rune)) bool = { return bytes.hassuffix(toutf8(in), s); }; -// byteindex — byte-wise offset of `needle` in `haystack`, or void if -// absent. ref/hare/strings/index.ha:127. Rune arm encodes via +// ref/hare/strings/index.ha:127. Rune arm encodes via // utf8.encoderune (Hare passes the encoded slice straight to // bytes::index). export fn byteindex(haystack: str, needle: (str | rune)) (i32 | void) = { @@ -300,7 +289,6 @@ export fn byteindex(haystack: str, needle: (str | rune)) (i32 | void) = { return bytes.index(toutf8(haystack), n); }; -// rbyteindex — byte-wise offset of the last `needle` in `haystack`. // ref/hare/strings/index.ha:138. export fn rbyteindex(haystack: str, needle: (str | rune)) (i32 | void) = { let scratch: [4]u8; @@ -311,15 +299,12 @@ export fn rbyteindex(haystack: str, needle: (str | rune)) (i32 | void) = { return bytes.rindex(toutf8(haystack), n); }; -// indexstring — str-arm of [[index]]. Dual-rune-iterator walk: at each -// candidate rune index `i`, compare `haystack` from that position -// against `needle` rune-by-rune until needle is exhausted (match) or -// a mismatch / haystack-exhaustion breaks the inner loop. Mirrors -// ref/hare/strings/index.ha:59 (#10). Hare copies `rest_iter = s_iter` -// directly via struct assignment; ww re-seats `rest_iter` field-wise -// because the let-init struct-copy form diverges between cstage and -// wwstage on this iterator type (993_ww_ww + 995_self_rebuild fail, -// filed as #41) and rule #10 (CLAUDE.md) forbids stage asymmetry. +// Mirrors ref/hare/strings/index.ha:59 (#10). Hare copies +// `rest_iter = s_iter` directly via struct assignment; ww re-seats +// `rest_iter` field-wise because the let-init struct-copy form +// diverges between cstage and wwstage on this iterator type +// (993_ww_ww + 995_self_rebuild fail, filed as #41) and rule #10 +// (CLAUDE.md) forbids stage asymmetry. fn indexstring(haystack: str, needle: str) (i32 | void) = { let s_iter: iterator = iter(haystack); let i: i32 = 0; @@ -356,11 +341,10 @@ fn indexstring(haystack: str, needle: str) (i32 | void) = { return; }; -// index — rune-wise offset of `needle`'s first occurrence in -// `haystack`, or void if absent. ref/hare/strings/index.ha:10. The -// str-arm delegates to [[indexstring]] (dual-iterator rune-by-rune -// walk per Hare's `index_string`, #10); the rune-arm mirrors Hare's -// `index_rune` (ref/hare/strings/index.ha:31). +// Rune-wise offset, not byte-wise ([[byteindex]]). +// ref/hare/strings/index.ha:10. The str-arm delegates to +// [[indexstring]] (per Hare's `index_string`, #10); the rune-arm +// mirrors Hare's `index_rune` (ref/hare/strings/index.ha:31). export fn index(haystack: str, needle: (str | rune)) (i32 | void) = { match (needle) { case let s: str => return indexstring(haystack, s); @@ -381,8 +365,7 @@ export fn index(haystack: str, needle: (str | rune)) (i32 | void) = { return; }; -// rindex — rune-wise offset of `needle`'s last occurrence in -// `haystack`, or void if absent. ref/hare/strings/index.ha:22. The +// Rune-wise offset. ref/hare/strings/index.ha:22. The // str-arm reuses `rbyteindex`; the rune-arm walks forward tracking // the most recent matching rune index (Hare's `rindex_rune` with // `riter` returns a byte-offset value for multibyte strings, which @@ -426,7 +409,6 @@ export fn rindex(haystack: str, needle: (str | rune)) (i32 | void) = { return; }; -// contains — true iff any of `needles` occurs in `haystack`. // ref/hare/strings/contains.ha:9. export fn contains(haystack: str, needles: (str | rune)...) bool = { let i: i32 = 0; @@ -450,9 +432,7 @@ export fn contains(haystack: str, needles: (str | rune)...) bool = { return false; }; -// trimprefix — `s` with `prefix` stripped from the front, or `s` -// unchanged if it doesn't start with `prefix`. Borrowed view. -// ref/hare/strings/trim.ha:60. +// ref/hare/strings/trim.ha:60. Borrowed view. export fn trimprefix(input: str, prefix: str) str = { if (!hasprefix(input, prefix)) { return input; }; let r: str; @@ -461,7 +441,7 @@ export fn trimprefix(input: str, prefix: str) str = { return r; }; -// trimsuffix — symmetric. ref/hare/strings/trim.ha:69. +// ref/hare/strings/trim.ha:69. export fn trimsuffix(input: str, suffix: str) str = { if (!hassuffix(input, suffix)) { return input; }; let r: str; @@ -470,12 +450,11 @@ export fn trimsuffix(input: str, suffix: str) str = { return r; }; -// whitespace — ASCII whitespace set used by the 0-arg ltrim/rtrim/trim -// branches (#9). ref/hare/strings/trim.ha:6. +// ASCII set for the 0-arg ltrim/rtrim/trim branches (#9). +// ref/hare/strings/trim.ha:6. let whitespace: [4]u8 = [0x20u8, 0x0Au8, 0x09u8, 0x0Du8]; -// ltrim — strip leading runes that occur in `trim`. Borrowed view. -// 0-arg strips ASCII whitespace via [[bytes.ltrim]] (#9). +// Borrowed view. 0-arg strips ASCII whitespace via [[bytes.ltrim]] (#9). // ref/hare/strings/trim.ha:11. The spread expression is inlined // because `let ws: []u8 = whitespace[0:4]` produces a slice whose // ptr doesn't track the module-level array storage (filed as #40); @@ -509,9 +488,8 @@ export fn ltrim(input: str, trim: rune...) str = { return iterstr(&it); }; -// rtrim — strip trailing runes that occur in `trim`. Borrowed view. // 0-arg strips ASCII whitespace via [[bytes.rtrim]] (#9). Spread is -// inlined to dodge #40 — see [[ltrim]]. +// Borrowed view; inlined to dodge #40 — see [[ltrim]]. // ref/hare/strings/trim.ha:32. export fn rtrim(input: str, trim: rune...) str = { if (trim.len == 0) { @@ -541,23 +519,22 @@ export fn rtrim(input: str, trim: rune...) str = { return iterstr(&it); }; -// trim — strip from both ends. ref/hare/strings/trim.ha:54. +// ref/hare/strings/trim.ha:54. export fn trim(input: str, trim: rune...) str = { return ltrim(rtrim(input, trim...), trim...); }; -// iterator — UTF-8 rune cursor over a `str`. Layout flattens Hare's -// anonymous-embedded `utf8::decoder` (ref/hare/strings/iter.ha:6-9) to -// explicit fields. `reverse` selects walk direction: forward iterators -// (`iter`) advance through utf8.next; reverse iterators (`riter`) advance -// through utf8.prev. May be copied to save state. +// Layout flattens Hare's anonymous-embedded `utf8::decoder` +// (ref/hare/strings/iter.ha:6-9) to explicit fields. `reverse` selects +// walk direction: forward iterators (`iter`) advance through utf8.next; +// reverse iterators (`riter`) advance through utf8.prev. May be copied +// to save state. export type iterator = struct { offs: i32, src: []u8, reverse: bool, }; -// iter — initialize a forward iterator at the start of `src`. // ref/hare/strings/iter.ha:24. export fn iter(src: str) iterator = { let r: iterator; @@ -567,8 +544,6 @@ export fn iter(src: str) iterator = { return r; }; -// riter — initialize a reverse iterator at the end of `src`. `next` -// on a reverse iterator walks back through the string. // ref/hare/strings/iter.ha:32. export fn riter(src: str) iterator = { let r: iterator; @@ -578,8 +553,7 @@ export fn riter(src: str) iterator = { return r; }; -// move — private dispatch shared by next/prev. `forward` selects -// utf8.next vs utf8.prev. Aborts on more/invalid per Hare's +// Aborts on more/invalid per Hare's // ref/hare/strings/iter.ha:51-58 ("Invalid UTF-8 string (this should // not happen)"). Hare picks the utf8 function via a fn-pointer; ww // branches on `forward` at each call site instead. @@ -607,22 +581,17 @@ fn move(forward: bool, it: *iterator) (rune | utf8.done) = { }; }; -// next — advance the iterator one rune. Forward iterators step -// through utf8.next; reverse iterators (riter) step backward through -// utf8.prev. Returns utf8.done at end-of-walk. ref/hare/strings/iter.ha:45. +// ref/hare/strings/iter.ha:45. export fn next(it: *iterator) (rune | utf8.done) = { return move(!it.reverse, it); }; -// prev — step back one rune. Dual to next: on a forward iterator -// this walks utf8.prev; on a reverse iterator (riter) it walks -// utf8.next. ref/hare/strings/iter.ha:49. +// ref/hare/strings/iter.ha:49. export fn prev(it: *iterator) (rune | utf8.done) = { return move(it.reverse, it); }; -// iterstr — borrowed view of the bytes remaining in the iterator's -// walk direction. Forward iter: bytes from offs to end; reverse iter: +// Borrowed view. Forward iter: bytes from offs to end; reverse iter: // bytes from start to offs. ref/hare/strings/iter.ha:63. export fn iterstr(it: *iterator) str = { let r: []u8; @@ -634,7 +603,6 @@ export fn iterstr(it: *iterator) str = { return frombytes(r); }; -// slice — borrowed substring between two iterator positions. // ref/hare/strings/iter.ha:75. Hare passes `*iterator` directly where // `*utf8::decoder` is expected via anonymous-embed coercion; ww has // no anonymous embed, so we reconstruct a local utf8.decoder for each @@ -649,22 +617,19 @@ export fn slice(begin: *iterator, end: *iterator) str = { return frombytes(utf8.slice(&b, &e)); }; -// position — byte-wise offset of the iterator in its source. // ref/hare/strings/iter.ha:82. export fn position(it: *iterator) i32 = { return it.offs; }; -// tokenizer — re-export of bytes.tokenizer. ref/hare/strings/tokenize.ha:7. +// ref/hare/strings/tokenize.ha:7. // First cross-module type alias in tree; needs #22's transitive // alias-chain unwrap (cstage type_chase_named + wwstage // structlookupchain) to walk struct fields through the chain. export type tokenizer = bytes.tokenizer; -// tokenize — yield substrings of `s` split on any byte in `delim`. -// Leading / trailing / adjacent delims yield empty tokens. `s` and -// `delim` are borrowed; caller keeps them live for the tokenizer's -// lifetime. ref/hare/strings/tokenize.ha:32. ASCII-only delim +// `s` and `delim` are borrowed; caller keeps them live for the +// tokenizer's lifetime. ref/hare/strings/tokenize.ha:32. ASCII-only delim // asserted per Hare lines 35-37: a multibyte rune in delim would // split on a single continuation byte and yield invalid UTF-8. export fn tokenize(s: str, delim: str) tokenizer = { @@ -678,8 +643,6 @@ export fn tokenize(s: str, delim: str) tokenizer = { return bytes.tokenize(toutf8(s), d...); }; -// rtokenize — reverse-direction counterpart to [[tokenize]]. First -// nexttoken yields the last token, last yields the first. // ref/hare/strings/tokenize.ha:44. export fn rtokenize(s: str, delim: str) tokenizer = { let d: []u8 = toutf8(delim); @@ -692,7 +655,6 @@ export fn rtokenize(s: str, delim: str) tokenizer = { return bytes.rtokenize(toutf8(s), d...); }; -// nexttoken — current token, advancing the cursor. // ref/hare/strings/tokenize.ha:62. export fn nexttoken(s: *tokenizer) (str | bytes.done) = { let b: *bytes.tokenizer = s: *bytes.tokenizer; @@ -702,7 +664,6 @@ export fn nexttoken(s: *tokenizer) (str | bytes.done) = { }; }; -// peektoken — current token without advancing. // ref/hare/strings/tokenize.ha:71. export fn peektoken(s: *tokenizer) (str | bytes.done) = { let b: *bytes.tokenizer = s: *bytes.tokenizer; @@ -712,34 +673,29 @@ export fn peektoken(s: *tokenizer) (str | bytes.done) = { }; }; -// remainingtokens — unconsumed portion of the input ahead of the -// cursor. ref/hare/strings/tokenize.ha:79. +// ref/hare/strings/tokenize.ha:79. export fn remainingtokens(s: *tokenizer) str = { let b: *bytes.tokenizer = s: *bytes.tokenizer; return frombytes(bytes.remainingtokens(b)); }; -// cut — split `in` along the first instance of `delim`, returning the -// portions before and after it. When `delim` is absent the whole input -// is the first half and the second is empty. Both halves are borrowed -// from `in`; caller ensures `delim` is non-empty. -// ref/hare/strings/tokenize.ha:288. +// When `delim` is absent the whole input is the first half and the +// second is empty. Both halves are borrowed from `in`; caller +// ensures `delim` is non-empty. ref/hare/strings/tokenize.ha:288. export fn cut(in: str, delim: str) (str, str) = { let (a, b) = bytes.cut(toutf8(in), toutf8(delim)); return (frombytes(a), frombytes(b)); }; -// rcut — like [[cut]] but split along the LAST instance of `delim`. // ref/hare/strings/tokenize.ha:302. export fn rcut(in: str, delim: str) (str, str) = { let (a, b) = bytes.rcut(toutf8(in), toutf8(delim)); return (frombytes(a), frombytes(b)); }; -// splitn — split `in` on any byte in `delim`, returning up to `n` -// tokens via forward iteration. The trailing slot (when more than -// `n - 1` tokens exist) holds the unconsumed remainder. Strings -// within the result are borrowed from `in`. +// The trailing slot (when more than `n - 1` tokens exist) holds the +// unconsumed remainder. Strings within the result are borrowed +// from `in`. // // The caller frees the returned slice via // `os.free(r.ptr: *void, (r.cap: u64) * size(str): u64)`. @@ -773,9 +729,8 @@ export fn splitn(in: str, delim: str, n: i32) []str = { return toks; }; -// rsplitn — reverse-direction counterpart to [[splitn]]: tokens are -// collected from the end of `in`. The trailing slot holds the -// unconsumed prefix (everything before the n-th-from-last delim hit). +// The trailing slot holds the unconsumed prefix (everything before +// the n-th-from-last delim hit). // // When the input has fewer than n tokens, the `done` short-circuit // returns toks UN-reversed (in last-token-first order). Mirrors Hare @@ -826,8 +781,7 @@ export fn rsplitn(in: str, delim: str, n: i32) []str = { return toks; }; -// split — full split of `in` on `delim` (no token cap). Mirrors -// `splitn(in, delim, types::SIZE_MAX)`. ww uses `types.I32_MAX` +// Mirrors `splitn(in, delim, types::SIZE_MAX)`. ww uses `types.I32_MAX` // because the index type is i32 (lib/CLAUDE.md). // // ref/hare/strings/tokenize.ha:242. @@ -835,8 +789,7 @@ export fn split(in: str, delim: str) []str = { return splitn(in, delim, types.I32_MAX); }; -// lpad — left-pad `s` with `p` rune until the result reaches `maxlen` -// bytes. Length comparison is BYTES, mirroring Hare's `len(s) >= maxlen` +// Length comparison is BYTES, mirroring Hare's `len(s) >= maxlen` // at ref/hare/strings/pad.ha:9. A multibyte `p` whose encoded width // doesn't divide `maxlen - s.len` evenly leaves a trailing pad byte // pair sliced mid-codepoint at byte `maxlen-1`, exactly as Hare's @@ -872,9 +825,9 @@ export fn lpad(s: str, p: rune, maxlen: i32) str = { return frombytes(buf); }; -// replace — fresh allocation of `s` with every non-overlapping -// occurrence of `needle` replaced by `target`. Caller releases with -// `os.free(r.ptr, r.len: u64)`. ref/hare/strings/replace.ha:8 (#4). +// Replaces every non-overlapping occurrence of `needle`. Caller +// releases with `os.free(r.ptr, r.len: u64)`. +// ref/hare/strings/replace.ha:8 (#4). // // Hare delegates to [[multireplace]] with a single pair; ww has no // `(str, str)` variadic shape today (#39), so this is a standalone @@ -928,8 +881,7 @@ export fn replace(s: str, needle: str, target: str) (str | nomem) = { return frombytes(res); }; -// rpad — right-pad `s` with `p` rune until the result reaches `maxlen` -// bytes. Symmetric with [[lpad]]. ref/hare/strings/pad.ha:39. +// Symmetric with [[lpad]]. ref/hare/strings/pad.ha:39. export fn rpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; diff --git a/lib/strings/suffix_test.ww b/lib/strings/suffix_test.ww index 7f966918..468c56e2 100644 --- a/lib/strings/suffix_test.ww +++ b/lib/strings/suffix_test.ww @@ -1,6 +1,4 @@ -// suffixtest — exercises strings.hasprefix/hassuffix. A failing row -// aborts via the assert/abort builtin (task #5 @test conversion). -// Vectors mirror ref/hare/strings/suffix.ha. +// Vectors mirror ref/hare/strings/suffix.ha (task #5 @test conversion). package strings_test; diff --git a/lib/strings/tokenize_test.ww b/lib/strings/tokenize_test.ww index 72e5ee47..784b1a03 100644 --- a/lib/strings/tokenize_test.ww +++ b/lib/strings/tokenize_test.ww @@ -162,7 +162,6 @@ fn expect_str_done(t: *strings.tokenizer) void = { assert(!(!streq(strings.remainingtokens(&t2), "a b c"))); }; -// ---- splitn / rsplitn / split ---------------------------------------- // ref/hare/strings/tokenize.ha:245 @test fn split. Hare's vectors // mirrored here directly; element reads go through `&toks.ptr[i]: *str` // rather than `toks[i]` so the 16B str element copy stays out of the @@ -290,7 +289,6 @@ fn expect_str(toks: []str, i: i32, want: str) void = { os.free(t3.ptr: *void, (t3.cap: u64) * size(str): u64); }; -// ---- cut / rcut ------------------------------------------------------- // ref/hare/strings/tokenize.ha:316 (@test fn cut). str wrappers over // bytes.cut/rcut. The `let (a, b) = cut(...)` destructure drives the // over-cap tuple-return (sret) path end-to-end (a 2nd #10 witness). diff --git a/lib/strings/trim_test.ww b/lib/strings/trim_test.ww index aba0d910..52fcef54 100644 --- a/lib/strings/trim_test.ww +++ b/lib/strings/trim_test.ww @@ -26,7 +26,6 @@ import strings; assert(!(!streq(strings.trimsuffix("hello", "hello"), ""))); }; -// ---- ltrim / rtrim / trim --------------------------------------------- // ref/hare/strings/trim.ha:75-97. 0-arg rows (#9) pin the ASCII // whitespace set (' ', '\t', '\n', '\r' — ref/hare/strings/trim.ha:6). @@ -167,4 +166,3 @@ import strings; i += 1; }; }; - diff --git a/lib/temp/temp.ww b/lib/temp/temp.ww index 628206bf..0808bd74 100644 --- a/lib/temp/temp.ww +++ b/lib/temp/temp.ww @@ -113,9 +113,8 @@ fn nextrand() u64 = { // exposes getenv; documented in the file header. fn gettmpdir() str = { return "/tmp"; }; -// puts — copy `s` into pathbuf starting at `off`. Caps writes -// against pathbuf's capacity so a long caller-supplied dir can't -// run off the end. Returns the new offset. +// Caps writes against pathbuf's capacity so a long caller-supplied +// dir can't run off the end. fn puts(off: i32, s: str) i32 = { let i: i32 = 0; for (i < s.len) { @@ -126,7 +125,6 @@ fn puts(off: i32, s: str) i32 = { return off + i; }; -// puthex — 16 lowercase hex digits of `v` into pathbuf[off..off+16]. fn puthex(off: i32, v: u64) i32 = { let hex: str = "0123456789abcdef"; let i: i32 = 0; diff --git a/lib/temp/temp_test.ww b/lib/temp/temp_test.ww index ba450676..919b76b5 100644 --- a/lib/temp/temp_test.ww +++ b/lib/temp/temp_test.ww @@ -1,6 +1,3 @@ -// temptest — exercises lib/temp. Run with -// `out/bin/ww build lib/temp/temptest.ww && ./temptest`. -// // Every @test enumerates parallel `[N]T` arrays of inputs and // expectations, then iterates one body across them. Parallel arrays // (rather than `[N]struct{...}`) sidestep the cstage cgen's chained @@ -28,8 +25,6 @@ fn streq(a: str, b: str) bool = { return true; }; -// ---- namedroundtrip: write + read-back across payload sizes ------------ - @test fn namedroundtrip() void = { // (payload size, fill byte). Row 0 covers the zero-byte edge. let sz: [4]i32; @@ -56,7 +51,6 @@ fn streq(a: str, b: str) bool = { assert(!(!streq(strslice(p, 0, 10), "/tmp/temp."))); assert(!(p.ptr[p.len] != 0u8)); - // Build fill payload, write it, lseek to 0, read it back. let wbuf: [64]u8; let k: i32 = 0; for (k < sz[i]) { wbuf[k] = fill[i]; k += 1; }; @@ -82,13 +76,11 @@ fn streq(a: str, b: str) bool = { k2 += 1; }; - // File exists pre-cleanup. assert(!(os.access(p, 0i32) != 0)); assert(!(os.close(fd) != 0)); assert(!(os.remove(p) != 0)); - // Cleanup landed. assert(!(os.access(p, 0i32) == 0)); i += 1; @@ -104,8 +96,6 @@ fn strslice(p: str, lo: i32, hi: i32) str = { return r; }; -// ---- namedoverwrite: static buffer is reused across calls -------------- -// // Hare docs: "The name is statically allocated, and will be // overwritten on subsequent calls." Match that contract — the second // named() call lands in the same buffer, so p1.ptr == p2.ptr. @@ -141,7 +131,6 @@ fn strslice(p: str, lo: i32, hi: i32) str = { assert(!(p1.ptr != p2.ptr)); assert(!(streq(strslice(p2, 0, p2.len), psnap))); - // Both fds are distinct. assert(!(fd1 == fd2)); assert(!(os.close(fd2) != 0)); @@ -160,8 +149,6 @@ fn strslice(p: str, lo: i32, hi: i32) str = { // Coverage for the underlying open+create+EXCL path lives in // [[namedroundtrip]] / [[namedoverwrite]]. -// ---- dirlifecycle: empty dir, then dir + one child file ---------------- - @test fn dirlifecycle() void = { // (child count). Row 0: empty dir. Row 1: dir + one file. let childn: [2]i32; @@ -175,7 +162,6 @@ fn strslice(p: str, lo: i32, hi: i32) str = { assert(!(!streq(strslice(d, 0, 5), "/tmp/"))); assert(!(d.ptr[d.len] != 0u8)); - // Dir exists. assert(!(os.access(d, 0i32) != 0)); // Snapshot the dir path into a local NUL-terminated buffer: @@ -192,7 +178,6 @@ fn strslice(p: str, lo: i32, hi: i32) str = { dview.ptr = &dsnap[0]; dview.len = dlen; if (childn[i] > 0) { - // Build "/x\0" in a local buffer. let cbuf: [144]u8; let off: i32 = 0; let j: i32 = 0; @@ -217,15 +202,12 @@ fn strslice(p: str, lo: i32, hi: i32) str = { // touched between dir() and here). assert(!(os.rmdir(dview) != 0)); - // Cleanup landed. assert(!(os.access(dview, 0i32) == 0)); i += 1; }; }; -// ---- diruniqueness: two dir() calls produce different paths ------------ - @test fn diruniqueness() void = { let d1: str = temp.dir(); let snap: [128]u8; diff --git a/lib/time/time.ww b/lib/time/time.ww index e54215cc..9351f825 100644 --- a/lib/time/time.ww +++ b/lib/time/time.ww @@ -78,8 +78,8 @@ export fn sleep(d: duration, c: clock) void = { }; }; -// ref/hare/time/arithm.ha:9. Adds duration to instant. The -// negative-duration branch normalises nsec into [0, second). +// ref/hare/time/arithm.ha:9. The negative-duration branch normalises +// nsec into [0, second). export fn add(i: instant, x: duration) instant = { let r: instant; let xi: i64 = x: i64; @@ -100,8 +100,7 @@ export fn add(i: instant, x: duration) instant = { return r; }; -// ref/hare/time/arithm.ha:26. Returns duration from a to b. -// Sign convention: b - a. +// ref/hare/time/arithm.ha:26. Sign convention: b - a. export fn diff(a: instant, b: instant) duration = { let sec: i64 = second: i64; let v: i64 = ((b.sec - a.sec) * sec) + (b.nsec - a.nsec); diff --git a/lib/ww/syntax/ast.ww b/lib/ww/syntax/ast.ww index d3c98a82..3527c631 100644 --- a/lib/ww/syntax/ast.ww +++ b/lib/ww/syntax/ast.ww @@ -1,7 +1,4 @@ -// lib/ww/syntax/ast.ww — port of cmd/wcc/ast.c (Node defs + printer). -// -// Status: AST printer is fully ported. Constructor `newnode` is here. -// The parser (parse.ww) is currently minimal — see its file header. +// Port of cmd/wcc/ast.c (Node defs + printer). // // Calling-convention shim: same as tok/lex — `node` is too big to pass // by value (8 *node pointers + 2 strs + a few ints), so callers always @@ -12,14 +9,10 @@ package syntax; import os; import strconv; -// ---- Nkind ------------------------------------------------------------ -// -// Mirror of cmd/wcc/ww.h Nkind. Values must stay numerically equal -// to the C side (rule-6 data-shape mirror). - -// Mirror of the C `Nkind` enum in cmd/wcc/ww.h. Numeric values are -// explicit and must stay in sync with the C side. Tail-appended -// entries (TYPETEST onward) preserve every prior N_* value. +// Mirror of the C `Nkind` enum in cmd/wcc/ww.h (rule-6 data-shape +// mirror). Numeric values are explicit and must stay in sync with the +// C side. Tail-appended entries (TYPETEST onward) preserve every prior +// N_* value. export type nkind = enum i32 { N_NONE = 0, @@ -112,8 +105,6 @@ export type nkind = enum i32 { N_LAST = 68, }; -// ---- Node ------------------------------------------------------------- - export type node = struct { kind: nkind, file: str, @@ -150,8 +141,6 @@ export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = { return n; }; -// ---- printer ---------------------------------------------------------- - export fn nkname(k: nkind) str = { switch (k) { case nkind.N_NONE: return "none"; diff --git a/lib/ww/syntax/ast_test.ww b/lib/ww/syntax/ast_test.ww index d2c9d4c6..edc3f69d 100644 --- a/lib/ww/syntax/ast_test.ww +++ b/lib/ww/syntax/ast_test.ww @@ -1,12 +1,9 @@ -// asttest — functional-equivalence pin for [[nkname]] after the -// if-ladder → switch fold (struct fold S2). Run with -// `ww run -I lib/ww lib/ww/syntax/asttest.ww`. +// Functional-equivalence pin for [[nkname]] after the +// if-ladder → switch fold (struct fold S2). // // nkname is checked against every nkind value (the full ladder the // switch replaced) plus the out-of-band fallback ("?"). A failing row // aborts via the assert/abort builtin (task #5 @test conversion). -// `package main` + bare `import ast` mirrors wwdump (the external -// astprint consumer). package syntax_test; diff --git a/lib/ww/syntax/decl.ww b/lib/ww/syntax/decl.ww index 01bf19b5..be00748b 100644 --- a/lib/ww/syntax/decl.ww +++ b/lib/ww/syntax/decl.ww @@ -1,4 +1,4 @@ -// lib/ww/syntax/decl.ww — declaration parsing, split out of parse.ww. +// Declaration-parsing half of the cmd/wcc/parse.c port. package syntax; @@ -14,7 +14,7 @@ fn parseuse(p: *parser) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - advance(p); // past `use` + advance(p); let n: *node = newnode(nkind.N_USE, pf, pl, pc); n.nmod = p.curmod; // M1 #22: accumulate the full dotted import path (n.usepath) for the @@ -24,7 +24,7 @@ fn parseuse(p: *parser) *node = { expectident(p, &leaf); let path: str = leaf; for (p.curkind == tkind.TK_DOT) { - advance(p); // past `.` + advance(p); expectident(p, &leaf); path = strings.concat(path, ".", leaf); }; @@ -38,7 +38,7 @@ fn parsedef(p: *parser, exported: i32) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - advance(p); // past `def` + advance(p); let n: *node = newnode(nkind.N_DEF, pf, pl, pc); n.nmod = p.curmod; let id: str; @@ -160,7 +160,7 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - advance(p); // past `fn` + advance(p); let n: *node = newnode(nkind.N_FNDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; @@ -190,7 +190,7 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { let pf: str = p.curfile; let pl: i32 = p.curline; let pc: i32 = p.curcol; - advance(p); // past `type` + advance(p); let n: *node = newnode(nkind.N_TYPEDECL, pf, pl, pc); n.nmod = p.curmod; let id: str; @@ -202,4 +202,3 @@ fn parsetypedecl(p: *parser, exported: i32) *node = { n.exported = exported; return n; }; - diff --git a/lib/ww/syntax/expr.ww b/lib/ww/syntax/expr.ww index 320b8a14..bffdf643 100644 --- a/lib/ww/syntax/expr.ww +++ b/lib/ww/syntax/expr.ww @@ -1,11 +1,10 @@ -// lib/ww/syntax/expr.ww — expression parsing, split out of parse.ww. +// Expression-parsing half of the cmd/wcc/parse.c port. package syntax; import os; -// streqlocal — str-to-str compare. Inlined here to avoid a cross- -// module `use sym;` for one call site. +// Inlined to avoid a cross-module `use sym;` for one call site. fn streqlocal(a: str, b: str) bool = { if (a.len != b.len) { return false; }; let i: i32 = 0; @@ -113,7 +112,6 @@ fn parseprimary(p: *parser) *node = { if (p.curkind == tkind.TK_LPAREN) { advance(p); let e: *node = parseexpr(p); - // Tuple literal: (a, b, ...) if (accepttok(p, tkind.TK_COMMA)) { let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc); t.list = e; @@ -194,7 +192,7 @@ fn parseprimary(p: *parser) *node = { let cf: str = p.curfile; let cl: i32 = p.curline; let cc: i32 = p.curcol; - advance(p); // past `case` + advance(p); let mc: *node = newnode(nkind.N_MCASE, cf, cl, cc); if (p.curkind == tkind.TK_LET) { advance(p); @@ -545,4 +543,3 @@ fn parseexpr(p: *parser) *node = { }; return e; }; - diff --git a/lib/ww/syntax/lex.ww b/lib/ww/syntax/lex.ww index f3557cb8..fa215d57 100644 --- a/lib/ww/syntax/lex.ww +++ b/lib/ww/syntax/lex.ww @@ -1,4 +1,4 @@ -// lib/ww/syntax/lex.ww — port of cmd/wcc/lex.c. +// Port of cmd/wcc/lex.c. // // The DFA, the helpers, and the order of decisions all mirror the C // version exactly; any divergence surfaces as a cs/ww byte split in @@ -18,9 +18,8 @@ import strings; import strconv; import encoding.utf8; -// isidstart / isidpart — identifier classification. Lexer-local -// because the "alpha or '_' / alnum or '_'" set isn't part of Hare's -// ascii::; ascii::isalpha + the '_' check live here instead. +// Lexer-local because the "alpha or '_' / alnum or '_'" set isn't part +// of Hare's ascii::; ascii::isalpha + the '_' check live here instead. fn isidstart(c: rune) bool = { if (ascii.isalpha(c)) { return true; }; if (c == '_') { return true; }; @@ -33,8 +32,6 @@ fn isidpart(c: rune) bool = { return false; }; -// hexval — value of `c` as a hex digit (0..15) or void if not a hex -// digit. Used by string-literal `\xHH` escapes. fn hexval(c: rune) (i32 | void) = { if (ascii.isdigit(c)) { return (c - '0'): i32; }; if (c >= 'A') { @@ -81,7 +78,6 @@ export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.modresetpathset = 0; }; -// srcb — byte at offset; helper that lifts the cast out of indexing. fn srcb(l: *lex, off: u64) i32 = { let i: i32 = off: i32; let b: u8 = l.src[i]; @@ -139,7 +135,7 @@ fn skipws(l: *lex) bool = { if (c == '/') { let c2: i32 = lpeek(l, 1u64); if (c2 == '/') { - lget(l); lget(l); // consume '//' + lget(l); lget(l); // #16 opt-B: recognize the driver's curmod-reset // boundary directive `//ww:module-reset` (whole // line) and flag it; lexnext emits TK_MODRESET. @@ -371,7 +367,6 @@ fn escape(l: *lex, out: *i32) bool = { return false; }; -// scandecimalrun — consume a run of decimal digits and underscores. fn scandecimalrun(l: *lex) void = { for (true) { let c: i32 = lpeek(l, 0u64); @@ -415,7 +410,6 @@ fn scanoctrun(l: *lex) void = { }; }; -// scanexp — consume the [eE][+-]?[0-9]+ tail of a float, if present. fn scanexp(l: *lex) void = { let e: i32 = lpeek(l, 0u64); if (e != 'e') { if (e != 'E') { return; }; }; @@ -752,8 +746,6 @@ fn emitsimple(start: *pos, k: tkind, out: *tok) void = { out.col = start.col; }; -// setposfrom — copy file/line/col from a *pos into a tok. Used by -// the err-token path where we already have a pos. fn setposfrom(out: *tok, p: *pos) void = { out.file = p.file; out.line = p.line; diff --git a/lib/ww/syntax/parse.ww b/lib/ww/syntax/parse.ww index e4a6d891..ca082c8b 100644 --- a/lib/ww/syntax/parse.ww +++ b/lib/ww/syntax/parse.ww @@ -1,9 +1,4 @@ -// lib/ww/syntax/parse.ww — port of cmd/wcc/parse.c (entry + plumbing). -// -// Split into Hare-style submodule: parse.ww (here) holds the parser -// struct, lexer plumbing, parsetype, parsefile (entry). Expression, -// statement, and declaration parsers live in expr.ww, stmt.ww, -// decl.ww respectively — all in the same `parse` module. +// Port of cmd/wcc/parse.c (entry + plumbing). // // Calling-convention shim: w6c can't yet pass a sub-struct field // (e.g. p.cur.line where p.cur is a `tok` of size 76). The parser @@ -96,7 +91,6 @@ fn expecttok(p: *parser, k: tkind, what: str) bool = { return false; }; -// expectident — consume the current tkind.TK_IDENT and return its text. // Returns the empty str on error (and advances to make progress). fn expectident(p: *parser, into: *str) bool = { if (p.curkind != tkind.TK_IDENT) { @@ -109,9 +103,7 @@ fn expectident(p: *parser, into: *str) bool = { return true; }; -// expectbindname — like expectident but also accepts a bare `_` -// discard marker. On `_`, returns "" so the checker skips -// scope_define for the binding. +// On `_`, returns "" so the checker skips scope_define for the binding. fn expectbindname(p: *parser, into: *str) bool = { if (p.curkind == tkind.TK_UNDER) { *into = ""; @@ -121,14 +113,7 @@ fn expectbindname(p: *parser, into: *str) bool = { return expectident(p, into); }; -// ---- type expressions ------------------------------------------------ -// -// Currently: TNAME (single ident, no dotted path yet) and TPTR (`*T`). -// Other forms (slice, array, struct, fn, chan, tuple, tagged) will -// land in subsequent commits. - -// joindotted — build "head.tail" for dotted type-name path -// collapse. Mirrors aprintf in C parser; pulled local to avoid a +// Mirrors aprintf in the C parser; pulled local to avoid a // cross-module dependency. fn joindotted(head: str, tail: str) str = { let n: u64 = head.len: u64 + 1u64 + tail.len: u64; @@ -391,13 +376,6 @@ fn parsetype(p: *parser) *node = { return newnode(nkind.N_TNAME, pf, pl, pc); }; -// ---- expressions (Pratt) --------------------------------------------- -// -// Forwards: parseexpr → parsebin → parseunary → parsepostfix(parseprimary). -// Tuple literals, match expressions, struct literals, slice [lo:hi], -// and the ?/! try operators are not yet wired — they'll arrive as the -// AST diff fixture grows to need them. - fn bprec(k: tkind) i32 = { if (k == tkind.TK_OR) { return 1; }; if (k == tkind.TK_AND) { return 2; }; diff --git a/lib/ww/syntax/stmt.ww b/lib/ww/syntax/stmt.ww index d9b4bba5..533bb894 100644 --- a/lib/ww/syntax/stmt.ww +++ b/lib/ww/syntax/stmt.ww @@ -1,4 +1,4 @@ -// lib/ww/syntax/stmt.ww — statement parsing, split out of parse.ww. +// Statement-parsing half of the cmd/wcc/parse.c port. package syntax; @@ -118,7 +118,7 @@ fn parseif(p: *parser) *node = { let pf = p.curfile; let pl = p.curline; let pc = p.curcol; - advance(p); // past `if` + advance(p); expecttok(p, tkind.TK_LPAREN, "expected '(' after if"); let n = newnode(nkind.N_IF, pf, pl, pc); n.cond = parseexpr(p); @@ -138,7 +138,7 @@ fn parsefor(p: *parser) *node = { let pf = p.curfile; let pl = p.curline; let pc = p.curcol; - advance(p); // past `for` + advance(p); // Go's bare `for { }` — no header at all (cmd/wcc/parse.c:1023; // Go's for has exactly three forms and this is the empty one). @@ -172,9 +172,8 @@ fn parsefor(p: *parser) *node = { // Range and 3-clause both lead with `let`, so we commit to consuming // `let` then disambiguate by looking at what follows. if (p.curkind == tkind.TK_LET) { - advance(p); // past `let` + advance(p); - // Tuple destructure: `for (let (a, b) .. expr)`. if (p.curkind == tkind.TK_LPAREN) { advance(p); let names: *node = nil; @@ -215,7 +214,7 @@ fn parsefor(p: *parser) *node = { let lpf = p.curfile; let lpl = p.curline; let lpc = p.curcol; - advance(p); // consume IDENT/UNDER + advance(p); if (p.curkind == tkind.TK_DOTDOT) { advance(p); @@ -277,7 +276,7 @@ fn parseswitch(p: *parser) *node = { let pf = p.curfile; let pl = p.curline; let pc = p.curcol; - advance(p); // past `switch` + advance(p); expecttok(p, tkind.TK_LPAREN, "expected '(' after switch"); let n = newnode(nkind.N_SWITCH, pf, pl, pc); n.lhs = parseexpr(p); @@ -289,7 +288,7 @@ fn parseswitch(p: *parser) *node = { let cpf = p.curfile; let cpl = p.curline; let cpc = p.curcol; - advance(p); // past `case` + advance(p); let cs = newnode(nkind.N_CASE, cpf, cpl, cpc); let eh: *node = nil; let et: *node = nil; @@ -437,4 +436,3 @@ fn parsestmt(p: *parser) *node = { expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement"); return n; }; - diff --git a/lib/ww/syntax/sym.ww b/lib/ww/syntax/sym.ww index 5bc6b7e1..dda98cee 100644 --- a/lib/ww/syntax/sym.ww +++ b/lib/ww/syntax/sym.ww @@ -1,8 +1,7 @@ -// lib/ww/syntax/sym.ww — port of cmd/wcc/sym.c. +// Port of cmd/wcc/sym.c. // -// Per-scope hashtable, chained to the parent. Lookup walks up. -// Plan 9 / Hare flavoured. Duplicate definitions in the same scope -// return nil; the caller flags the error. +// Duplicate definitions in the same scope return nil; the caller +// flags the error. package syntax; @@ -103,11 +102,8 @@ export fn scopelookup(s: *scope, name: str) *sym = { return nil; }; -// scopelookuptype — find an SK_TYPE entry by name, same-module preferred. -// -// Same FNV bucket + hashnext chain + parent walk as scopelookup, with -// an `skind == SK_TYPE` filter. Used to disambiguate the bare-TNAME -// vs imported-module-bareword collision: when scopelookup returns the +// Disambiguates the bare-TNAME vs imported-module-bareword +// collision: when scopelookup returns the // SK_USE sym for a leaf that ALSO names a type (a same-name `import X;` // SK_USE shadowing a struct X declared in another module), the resolver // needs the type entry — the struct's mod may differ from the leaf so @@ -151,10 +147,7 @@ export fn scopelookuptype(s: *scope, mod: str, name: str) *sym = { return nil; }; -// scopelookupuselocal — find a same-leaf SK_USE entry within ONE scope. -// -// Same FNV bucket + hashnext chain as scopelookuplocal, with a -// `skind == SK_USE` filter and NO parent walk. The dot-lhs twin of +// The dot-lhs twin of // scopelookuptype: when a `use mod;` and a colliding top-level // `fn mod` / `type mod` of the same leaf coexist (random.random, // fnmatch.fnmatch), the mod-preferring scopelookupprefer returns the @@ -198,12 +191,9 @@ export fn scopelookupuselocal(s: *scope, name: str) *sym = { return nil; }; -// scopelookupinmodule — module-filtered chain walk. -// -// Same FNV bucket + hashnext chain + parent walk as scopelookup, plus -// a `b.mod.len > 0 && streq(b.mod, mod)` filter. When `mod` is empty -// we fall back to unfiltered scopelookup semantics, so callers that -// don't care about disambiguation get the default. +// When `mod` is empty we fall back to unfiltered scopelookup +// semantics, so callers that don't care about disambiguation get the +// default. // // Used by the dot-prefixed type-name lookup in selfhost/cmd/wcc/ // check.ww to pick the right same-leaf-name type when two imports @@ -229,10 +219,7 @@ export fn scopelookupinmodule(s: *scope, mod: str, name: str) *sym = { return nil; }; -// scopelookupprefer — bare-leaf lookup with same-module preference. -// -// Walks the same FNV bucket + hashnext chain + parent walk scopelookup -// uses. Within each scope's bucket: Pass 1 prefers entries whose +// Within each scope's bucket: Pass 1 prefers entries whose // `sym.mod` matches `mod`; Pass 2 falls back to the first match // regardless of mod (same semantics as scopelookup). We only descend // to the parent scope when the current scope has no matching entry at @@ -276,8 +263,6 @@ export fn scopedefine(s: *scope, name: str, k: skind, t: *tinfo, decl: *node) *s return scopedefineinmodule(s, name, empty, k, t, decl); }; -// scopedefineinmodule — bucket insert with per-mod dedup. -// // Same insertion as scopedefine, but the duplicate-rejection key is // (name, mod) rather than name alone. This lets two imports each // register their own `stream` SK_TYPE in the flat scope, and lets the diff --git a/lib/ww/syntax/sym_test.ww b/lib/ww/syntax/sym_test.ww index 87a9bc3b..20ea5064 100644 --- a/lib/ww/syntax/sym_test.ww +++ b/lib/ww/syntax/sym_test.ww @@ -1,13 +1,11 @@ -// symtest — behavior pin for [[newscope]]/[[scopedefine]]/[[scopelookup]] +// Behavior pin for [[newscope]]/[[scopedefine]]/[[scopelookup]] // (hashtable scope semantics: define, same-scope duplicate reject, -// kind-preserving lookup, not-found nil). Run with -// `ww test -I lib/ww lib/ww/syntax/symtest.ww`. +// kind-preserving lookup, not-found nil). // // Migrated from selfhost/test/sym_link.ww (the 990_selfhost link // probe): the toolchain-link half of that probe is owned by the // fixture corpus' ww-stage cells, so only the scope behavior rows -// survive, as in-language rows. `package main` + bare `import syntax` -// mirrors toktest/asttest. +// survive, as in-language rows. package syntax_test; diff --git a/lib/ww/syntax/tok.ww b/lib/ww/syntax/tok.ww index da7fb62e..116b0953 100644 --- a/lib/ww/syntax/tok.ww +++ b/lib/ww/syntax/tok.ww @@ -1,12 +1,8 @@ -// lib/ww/syntax/tok.ww — port of cmd/wcc/tok.c plus the Tkind / -// Tok / Pos shapes from cmd/wcc/ww.h. +// Port of cmd/wcc/tok.c plus the Tkind / Tok / Pos shapes from cmd/wcc/ww.h. // // Token kind values must stay numerically equal to the C side // (rule-6 data-shape mirror of cmd/wcc/ww.h). Reordering this list // shifts the integers and splits the two frontends. -// -// Bottom of file: tokprint, which emits one token per line in a -// format identical to cmd/wcc/tok.c:tokprint(). package syntax; @@ -14,7 +10,6 @@ import os; import strconv; import strings; -// ---- tkind ------------------------------------------------------------ // Mirror of the C `Tkind` enum in cmd/wcc/ww.h. Numeric values are // explicit and must stay in sync with the C side. @@ -125,8 +120,6 @@ export type tkind = enum i32 { TK_LAST = 89, }; -// ---- Pos / Tok -------------------------------------------------------- -// // `pos` is used at error-reporting boundaries; we always pass it via // *pos so the value never gets struct-copied (w6c can't yet copy a // 24-byte struct). @@ -152,8 +145,6 @@ export type tok = struct { tsuffix: str, // typed numeric literal suffix or empty }; -// ---- keyword lookup --------------------------------------------------- - // keep alphabetised, so kwlookup is easy to read — mirrors the C twin // cmd/wcc/tok.c:18-47. Two parallel arrays, not a [N]kwent array-of- // struct: a str *inside* an aggregate element is the filed #18 follow-up @@ -180,9 +171,7 @@ let kwkinds: [30]tkind = [ tkind.TK_VOID, tkind.TK_YIELD, ]; -// kwlookup — returns the matching TK_* keyword kind for a byte run, -// or tkind.TK_NONE if it's an ordinary identifier. Linear scan over the -// table, matching cmd/wcc/tok.c:kwlookup (N=30, no hash). +// Linear scan over the table, matching cmd/wcc/tok.c:kwlookup (N=30, no hash). export fn kwlookup(p: *u8, n: i32) tkind = { let cand: str; cand.ptr = p; @@ -197,10 +186,7 @@ export fn kwlookup(p: *u8, n: i32) tkind = { return tkind.TK_NONE; }; -// ---- tokname ---------------------------------------------------------- -// -// Returns the canonical printable spelling for a token kind. Matches -// the C tokname()'s output exactly so wwdump output diffs cleanly. +// Matches the C tokname()'s output exactly so wwdump output diffs cleanly. export fn tokname(k: tkind) str = { switch (k) { @@ -306,8 +292,6 @@ export fn tokname(k: tkind) str = { return ""; }; -// ---- writer for tokprint ---------------------------------------------- -// // fputq mirrors cmd/wcc/tok.c:fputq — quote the string with C-style // escapes for \, ", \n, \t, \r and \xNN for other non-printables. @@ -358,8 +342,8 @@ fn fputq(fd: i32, p: *u8, n: i32) void = { fputcbyte(fd, '"'); }; -// tokprint — write one token line to fd. Format must match -// cmd/wcc/tok.c:tokprint() byte-for-byte: that's the diff anchor. +// Format must match cmd/wcc/tok.c:tokprint() byte-for-byte: that's +// the diff anchor. // ":: [ ]\n" // // Takes `t` by pointer because w6c can't yet pass a >16-byte struct diff --git a/lib/ww/syntax/tok_test.ww b/lib/ww/syntax/tok_test.ww index c700796d..69d00e66 100644 --- a/lib/ww/syntax/tok_test.ww +++ b/lib/ww/syntax/tok_test.ww @@ -1,7 +1,6 @@ -// toktest — functional-equivalence pin for [[tokname]], [[kwlookup]] +// Functional-equivalence pin for [[tokname]], [[kwlookup]] // (struct fold S1) and [[tokprint]]/fputq (struct fold S9, the // if-ladder → switch folds in tok.ww). -// Run with `ww run -I lib/ww lib/ww/syntax/toktest.ww`. // // tokname is checked against every tkind value (the full ladder the // switch replaced, plus the unknown-kind fallback); kwlookup is @@ -16,8 +15,6 @@ // A failing row aborts via the assert/abort builtin (task #5 @test // conversion); per-row exit-code pinpoint is intentionally dropped (the // abort reports the file, not the row; drew-t2-conversion-spec sec.5). -// `package main` + bare `import tok/lex` mirrors wwdump (the only other -// external lex consumer). package syntax_test; @@ -205,8 +202,7 @@ fn checkkw(s: str, want: tkind) void = { }; }; -// checkprint — tokprint `t` to a freshly-rewound fd, read the bytes -// back, and assert they equal `want`. The fd is RDWR; we lseek to 0 +// The fd is RDWR; we lseek to 0 // before each write so earlier (possibly longer) content past want.len // is irrelevant — only want.len bytes from offset 0 are compared. fn checkprint(fd: i32, t: *tok, want: str) void = { diff --git a/lib/ww/syntax/typ.ww b/lib/ww/syntax/typ.ww index a18e33e6..b6a28dd5 100644 --- a/lib/ww/syntax/typ.ww +++ b/lib/ww/syntax/typ.ww @@ -1,6 +1,6 @@ -// lib/ww/syntax/typ.ww — port of cmd/wcc/type.c. +// Port of cmd/wcc/type.c. // -// Status: full structural port. The C version uses module-globals for +// The C version uses module-globals for // the primitive types (tyvoid, tyi32, …); ww doesn't have writable // global storage yet, so we bundle the primitives into a `tctx` that // the checker passes around explicitly. typesinit fills the tctx @@ -10,11 +10,6 @@ package syntax; import os; -// ---- TypeKind --------------------------------------------------------- -// Numeric values must stay aligned with cmd/wcc/ww.h TypeKind so the -// next diff signal (typed-AST printer / cgen) can compare across the -// two implementations. - // Mirror of the C `TypeKind` enum in cmd/wcc/ww.h. Numeric values // are explicit and must stay in sync — the selfhost selfcheck and // typed-AST printers depend on matching numeric layout. @@ -67,8 +62,6 @@ export type tykind = enum i32 { // fabricate a 0-byte slot. Value == U64_MAX. def SIZE_UNDEFINED: u64 = 18446744073709551615; -// ---- tinfo / tfield / tparam ----------------------------------------- - export type tfield = struct { name: str, type_: *tinfo, @@ -173,8 +166,6 @@ export type tinfocacheent = struct { // scaled up — sym's 16 would give ~340-deep chains here. def NBUCKETS_TINFO: u64 = 8192u64; -// ---- tctx — the box of primitive types ------------------------------- - export type tctx = struct { tyvoid: *tinfo, tybool: *tinfo, @@ -206,8 +197,6 @@ export type tctx = struct { tinfobuckets: **tinfocacheent, // length NBUCKETS_TINFO; node-ptr hash index }; -// ---- constructors ----------------------------------------------------- - export fn newtype(k: tykind) *tinfo = { let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, tupleelems=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64, packed=0})!; return t; @@ -357,8 +346,6 @@ export fn tinfocachebind(c: *tctx, key: *node, val: *tinfo) void = { c.tinfobuckets[bi] = e; }; -// ---- predicates ------------------------------------------------------- - export fn typeisint(t: *tinfo) bool = { if (t == nil) { return false; }; let k: tykind = t.kind;