|
24 | 24 |
|
25 | 25 | ## Current state |
26 | 26 |
|
27 | | -- **Phase**: **Phase 5 IN-PROGRESS** — §9.7 rows 5.0 / 5.1 / 5.2 / 5.3 / 5.4 / 5.5 `[x]`. |
28 | | - 5.5 closed at 5b978e8 (4 micro-commits 5.5.a → 5.5.d: ArrayMap |
29 | | - surface complete with 8 ops). 11 rows remain (5.6–5.16). |
30 | | - PersistentHashMap shipped on ArrayMap path (≤ 8 entries); HAMT |
31 | | - body deferred to D-045 follow-up. D13 / D14 named hamt_map_node / |
32 | | - hash_collision_map_node per ADR-0027 amendment 5. Reader-literal |
33 | | - `{...}` hook deferred to analyzer follow-up. |
34 | | -- **Branch**: `cw-from-scratch`. HEAD = 5b978e8. |
| 27 | +- **Phase**: **Phase 5 IN-PROGRESS** — §9.7 rows 5.0 / 5.1 / 5.2 / 5.3 / 5.4 / 5.5 / 5.6 `[x]`. |
| 28 | + 5.6 closed at 9553840 (single commit, 5 day-1 ops on HashMap- |
| 29 | + backed wrapper). 10 rows remain (5.7–5.16). Collection family |
| 30 | + trio (Vector / HashMap-ArrayMap / HashSet) all shipping; HAMT |
| 31 | + body still D-045. |
| 32 | +- **Branch**: `cw-from-scratch`. HEAD = 9553840. |
35 | 33 | - **Gate**: Mac 13/13 + OrbStack Ubuntu x86_64 12/12 green. |
36 | 34 | - **Chapter cadence**: dormant per ADR-0025 + F-007. |
37 | 35 |
|
38 | | -## Active task — §9.7.7 / 5.6 PersistentHashSet (HashMap-backed) |
39 | | - |
40 | | -Land `runtime/collection/set.zig`: HashSet backed by HashMap |
41 | | -(key = element, value = `:cw/present` sentinel per ROADMAP row 5.6). |
42 | | -Day-1: `conj` / `disj` / `contains?` / `count` / `seq`. `#{...}` |
43 | | -reader literal hook deferred to analyzer follow-up. |
44 | | - |
45 | | -Since 5.5's HAMT body is deferred (D-045), 5.6 lands on top of |
46 | | -ArrayMap-only — ≤ 8 entries via ArrayMap-backed set. The HAMT |
47 | | -expansion path co-lands when D-045 is taken. |
48 | | - |
49 | | -**Step 0 reading**: clojure JVM `PersistentHashSet.java` (thin |
50 | | -wrapper over PersistentHashMap with `:cw/present` sentinel); cw |
51 | | -v0 collections.zig PersistentHashSet (if present); 5.5 |
52 | | -implementation patterns from `runtime/collection/map.zig`. |
53 | | - |
54 | | -**Step 0 survey target**: not needed for 5.6 — the JVM pattern |
55 | | -(HashMap wrapper with sentinel value) is well-known and 5.5's |
56 | | -implementation already establishes the GC integration. Direct |
57 | | -implementation likely fits in 2-3 micro-commits. |
58 | | - |
59 | | -**Open hazards**: (a) `:cw/present` sentinel needs a stable |
60 | | -keyword pointer — must be interned via Runtime.keywords at first |
61 | | -use or via a Layer-0 const; (b) 5.5 deferred HAMT means 5.6 |
62 | | -inherits the same limit (≤ 8 entries); (c) set equality semantics |
63 | | -match clojure (order-independent) which the wrapper inherits. |
| 36 | +## Active task — §9.7.8 / 5.7 LazySeq `force()` + thunk realisation |
| 37 | + |
| 38 | +Activate `runtime/lazy_seq.zig` (4.24 skeleton): `force()` walks |
| 39 | +the thunk and caches the realised Seq into `seq_cache`. `seq` / |
| 40 | +`first` / `rest` / `next` understand `.lazy_seq` Values. Test: |
| 41 | +`(reduce + (range 1e6))` without OOM (chunked realisation through |
| 42 | +GC). Per ADR-0009 amendment + 5.1 input bullet #2 the mutex shape |
| 43 | +decision happens here. |
| 44 | + |
| 45 | +**Step 0 reading**: ADR-0009 amendment 2 (double-checked locking); |
| 46 | +`phase5-5.1-survey.md` Block A (cw v0 `io_default.zig` rationale, |
| 47 | +verbatim) + survey bullets 1 / 2 / 4 (root walker + mutex + thunk |
| 48 | +shape); `phase5-skeleton-audit.md` §"`src/runtime/lazy_seq.zig`" |
| 49 | +(skeleton has `std.atomic.Mutex` field — Zig-0.16 gap noted). |
| 50 | + |
| 51 | +**Mutex decision (5.7 owns)**: choose between (a) no lock per cw v0 |
| 52 | +single-thread (Phase 5 OK, Phase 15 revisit); (b) std.Io.Mutex via |
| 53 | +io_default pattern (matches survey Block A); (c) std.atomic.Value |
| 54 | +busy-spin (lock-free). Per F-002 + Phase 5 single-thread reality, |
| 55 | +(a) likely lands at 5.7 with explicit "Phase 15 STM activation |
| 56 | +re-evaluates" debt row. |
| 57 | + |
| 58 | +**Open hazards**: (a) `seq_cache` Value-typed slot pre-existing |
| 59 | +as `std.atomic.Value(?*SeqOpaque)` — atomic state survives even |
| 60 | +under choice (a); GC root walker must trace whatever pointer the |
| 61 | +atomic carries (5.1 input bullet #1); (b) `thunk: *const fn` is |
| 62 | +NOT a Value-encoded fn — it's a Zig fn pointer; ctx is *anyopaque |
| 63 | +which the GC trace cannot blindly walk per 5.1 input #1 — |
| 64 | +finished form may need ctx tagging or per-LazySeq trace fn |
| 65 | +registration; (c) `(reduce + (range 1e6))` exit smoke needs |
| 66 | +chunked realisation NOT to OOM — auto-trigger collect may finally |
| 67 | +become necessary here (defer-or-trigger decision lives in 5.7). |
64 | 68 |
|
65 | 69 | ## Open questions / blockers |
66 | 70 |
|
|
0 commit comments