@shd101wyy/yo 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +43 -1
  2. package/out/cjs/index.cjs +581 -601
  3. package/out/cjs/yo-cli.cjs +739 -733
  4. package/out/cjs/yo-lsp.cjs +11615 -0
  5. package/out/esm/index.mjs +530 -550
  6. package/out/types/src/cache.d.ts +2 -0
  7. package/out/types/src/codegen/exprs/return.d.ts +1 -1
  8. package/out/types/src/codegen/types/generation.d.ts +0 -2
  9. package/out/types/src/codegen/utils/index.d.ts +2 -8
  10. package/out/types/src/doc/extractor.d.ts +4 -0
  11. package/out/types/src/evaluator/builtins/rc-fns.d.ts +0 -5
  12. package/out/types/src/evaluator/context.d.ts +7 -3
  13. package/out/types/src/evaluator/trait-checking.d.ts +2 -0
  14. package/out/types/src/evaluator/types/object.d.ts +2 -1
  15. package/out/types/src/evaluator/types/struct.d.ts +2 -1
  16. package/out/types/src/evaluator/types/utils.d.ts +3 -8
  17. package/out/types/src/evaluator/values/impl.d.ts +9 -1
  18. package/out/types/src/expr.d.ts +1 -2
  19. package/out/types/src/function-value.d.ts +1 -0
  20. package/out/types/src/lsp/completion.d.ts +3 -0
  21. package/out/types/src/lsp/definition.d.ts +3 -0
  22. package/out/types/src/lsp/diagnostics.d.ts +6 -0
  23. package/out/types/src/lsp/document-manager.d.ts +31 -0
  24. package/out/types/src/lsp/folding.d.ts +3 -0
  25. package/out/types/src/lsp/hover.d.ts +3 -0
  26. package/out/types/src/lsp/inlay-hints.d.ts +3 -0
  27. package/out/types/src/lsp/references.d.ts +3 -0
  28. package/out/types/src/lsp/rename.d.ts +16 -0
  29. package/out/types/src/lsp/server.d.ts +1 -0
  30. package/out/types/src/lsp/signature-help.d.ts +3 -0
  31. package/out/types/src/lsp/symbols.d.ts +3 -0
  32. package/out/types/src/lsp/utils.d.ts +11 -0
  33. package/out/types/src/tests/lsp.test.d.ts +1 -0
  34. package/out/types/src/tests/version.test.d.ts +1 -0
  35. package/out/types/src/types/creators.d.ts +2 -3
  36. package/out/types/src/types/definitions.d.ts +3 -6
  37. package/out/types/src/types/guards.d.ts +5 -2
  38. package/out/types/src/types/tags.d.ts +0 -1
  39. package/out/types/src/version-cache.d.ts +7 -0
  40. package/out/types/src/version.d.ts +5 -0
  41. package/out/types/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +3 -1
  43. package/scripts/build-site.ts +32 -15
  44. package/scripts/check-liburing.js +2 -2
  45. package/std/imm/list.yo +254 -0
  46. package/std/imm/map.yo +917 -0
  47. package/std/imm/set.yo +179 -0
  48. package/std/imm/sorted_map.yo +595 -0
  49. package/std/imm/sorted_set.yo +202 -0
  50. package/std/imm/string.yo +667 -0
  51. package/std/imm/vec.yo +456 -0
  52. package/std/prelude.yo +22 -5
  53. package/std/sync/channel.yo +92 -44
  54. package/std/sync/cond.yo +5 -1
  55. package/std/sync/mutex.yo +5 -1
  56. package/std/sync/once.yo +2 -1
  57. package/std/sync/rwlock.yo +2 -1
  58. package/std/sync/waitgroup.yo +2 -1
  59. package/out/types/src/codegen/exprs/arc.d.ts +0 -5
  60. package/out/types/src/evaluator/calls/arc.d.ts +0 -15
package/std/imm/map.yo ADDED
@@ -0,0 +1,917 @@
1
+ //! Persistent immutable hash map using a Hash Array Mapped Trie (HAMT).
2
+ //!
3
+ //! `Map(K, V)` is an immutable hash map backed by `atomic object` nodes for
4
+ //! thread-safe structural sharing. All mutations return new maps, leaving the
5
+ //! original unchanged.
6
+ //!
7
+ //! Keys must implement `Eq`, `Hash`, and `Send`. Values must implement `Send`.
8
+ //!
9
+ //! # Examples
10
+ //!
11
+ //! ```rust
12
+ //! { Map } :: import "std/imm/map";
13
+ //!
14
+ //! m := Map(i32, i32).new();
15
+ //! m = m.insert(i32(1), i32(100));
16
+ //! m = m.insert(i32(2), i32(200));
17
+ //! assert((m.get(i32(1)).unwrap() == i32(100)), "key 1 maps to 100");
18
+ //! assert((m.len() == usize(2)), "two entries");
19
+ //! ```
20
+
21
+ { GlobalAllocator } :: import "../allocator.yo";
22
+ { malloc, free } :: GlobalAllocator;
23
+
24
+ /// Number of bits per HAMT level.
25
+ BITS :: usize(5);
26
+ /// Mask for extracting BITS-wide chunks from hash.
27
+ MASK :: u64(31);
28
+
29
+ /// Count the number of set bits in a u32 (popcount).
30
+ popcount :: (fn(x: u32) -> u32)({
31
+ (v : u32) = x;
32
+ v = (v - ((v >> u32(1)) & u32(1431655765)));
33
+ v = ((v & u32(858993459)) + ((v >> u32(2)) & u32(858993459)));
34
+ (((v + (v >> u32(4))) & u32(252645135)) * u32(16843009)) >> u32(24)
35
+ });
36
+
37
+ /// Key-value pair used in collision nodes and entries.
38
+ Pair :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
39
+ struct(key : K, value : V)
40
+ );
41
+
42
+ /// HAMT leaf node -- single key-value entry.
43
+ MapLeaf :: (fn(
44
+ comptime(K) : Type,
45
+ comptime(V) : Type,
46
+ where(K <: (Eq(K), Hash, Send), V <: Send)
47
+ ) -> comptime(Type))(
48
+ atomic object(
49
+ hash : u64,
50
+ key : K,
51
+ value : V
52
+ )
53
+ );
54
+
55
+ /// HAMT collision node -- multiple entries sharing the same hash.
56
+ MapCollision :: (fn(
57
+ comptime(K) : Type,
58
+ comptime(V) : Type,
59
+ where(K <: (Eq(K), Hash, Send), V <: Send)
60
+ ) -> comptime(Type))(
61
+ atomic object(
62
+ hash : u64,
63
+ _pairs_ptr : *(Pair(K, V)),
64
+ _pairs_len : usize
65
+ )
66
+ );
67
+
68
+ impl(forall(K : Type, V : Type), where(K <: (Eq(K), Hash, Send), V <: Send),
69
+ MapCollision(K, V), Dispose(
70
+ dispose : (fn(self: Self) -> unit)({
71
+ i := usize(0);
72
+ while (i < self._pairs_len), (i = (i + usize(1))), {
73
+ unsafe.drop((self._pairs_ptr &+ i).*);
74
+ };
75
+ free(.Some(*(void)(self._pairs_ptr)));
76
+ })
77
+ ));
78
+
79
+ /// HAMT branch node -- bitmap + compact child array.
80
+ ///
81
+ /// `_children_ptr` is `*(void)` to break the circular type dependency with
82
+ /// `MapNode`. It is cast to `*(MapNode(K, V))` in methods.
83
+ MapBranch :: (fn(
84
+ comptime(K) : Type,
85
+ comptime(V) : Type,
86
+ where(K <: (Eq(K), Hash, Send), V <: Send)
87
+ ) -> comptime(Type))(
88
+ atomic object(
89
+ bitmap : u32,
90
+ _children_ptr : *(void),
91
+ _children_len : u8
92
+ )
93
+ );
94
+
95
+ /// Tagged union representing a single HAMT node.
96
+ MapNode :: (fn(
97
+ comptime(K) : Type,
98
+ comptime(V) : Type,
99
+ where(K <: (Eq(K), Hash, Send), V <: Send)
100
+ ) -> comptime(Type))(
101
+ enum(
102
+ Branch(node : MapBranch(K, V)),
103
+ Leaf(node : MapLeaf(K, V)),
104
+ Collision(node : MapCollision(K, V))
105
+ )
106
+ );
107
+
108
+ impl(forall(K : Type, V : Type), where(K <: (Eq(K), Hash, Send), V <: Send),
109
+ MapBranch(K, V), Dispose(
110
+ dispose : (fn(self: Self) -> unit)({
111
+ children := *(MapNode(K, V))(self._children_ptr);
112
+ i := u8(0);
113
+ while (i < self._children_len), (i = (i + u8(1))), {
114
+ unsafe.drop((children &+ usize(i)).*);
115
+ };
116
+ free(.Some(self._children_ptr));
117
+ })
118
+ ));
119
+
120
+ /// Persistent immutable hash map.
121
+ Map :: (fn(
122
+ comptime(K) : Type,
123
+ comptime(V) : Type,
124
+ where(K <: (Eq(K), Hash, Send), V <: Send)
125
+ ) -> comptime(Type))(
126
+ struct(
127
+ _root : Option(MapNode(K, V)),
128
+ _len : usize
129
+ )
130
+ );
131
+
132
+ // -- MapBranch helpers --
133
+
134
+ _alloc_map_children :: (fn(comptime(K) : Type, comptime(V) : Type, count: u8, where(K <: (Eq(K), Hash, Send), V <: Send)) -> *(void))({
135
+ sz := (sizeof(MapNode(K, V)) * usize(count));
136
+ match(malloc(sz),
137
+ .Some(p) => p,
138
+ .None => panic("imm.Map: allocation failed")
139
+ )
140
+ });
141
+
142
+ _branch_index_for :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), bit: u32, where(K <: (Eq(K), Hash, Send), V <: Send)) -> u8)(
143
+ u8(popcount((branch.bitmap & (bit - u32(1)))))
144
+ );
145
+
146
+ _branch_has_child :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), bit: u32, where(K <: (Eq(K), Hash, Send), V <: Send)) -> bool)(
147
+ ((branch.bitmap & bit) != u32(0))
148
+ );
149
+
150
+ _branch_child_at :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), idx: u8, where(K <: (Eq(K), Hash, Send), V <: Send)) -> MapNode(K, V))({
151
+ offset := (sizeof(MapNode(K, V)) * usize(idx));
152
+ target := *(MapNode(K, V))((branch._children_ptr &+ offset));
153
+ target.*
154
+ });
155
+
156
+ _branch_set_child :: (fn(comptime(K) : Type, comptime(V) : Type, ptr: *(void), idx: u8, child: MapNode(K, V), where(K <: (Eq(K), Hash, Send), V <: Send)) -> unit)({
157
+ offset := (sizeof(MapNode(K, V)) * usize(idx));
158
+ target := *(MapNode(K, V))((ptr &+ offset));
159
+ target.* = child;
160
+ });
161
+
162
+ /// Copy children from source array to destination array element-by-element.
163
+ /// This ensures proper RC increment for each child (memcpy would bypass RC).
164
+ _copy_children :: (fn(
165
+ comptime(K) : Type, comptime(V) : Type,
166
+ dst: *(void), src: *(void),
167
+ dst_offset: u8, src_offset: u8, count: u8,
168
+ where(K <: (Eq(K), Hash, Send), V <: Send)
169
+ ) -> unit)({
170
+ node_sz := sizeof(MapNode(K, V));
171
+ i := u8(0);
172
+ while (i < count), (i = (i + u8(1))), {
173
+ src_ptr := *(MapNode(K, V))((src &+ (node_sz * usize((src_offset + i)))));
174
+ dst_ptr := *(MapNode(K, V))((dst &+ (node_sz * usize((dst_offset + i)))));
175
+ consume(dst_ptr.* = src_ptr.*);
176
+ };
177
+ });
178
+
179
+ _branch_with_child :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), bit: u32, child: MapNode(K, V), where(K <: (Eq(K), Hash, Send), V <: Send)) -> MapBranch(K, V))({
180
+ idx := _branch_index_for(K, V, branch, bit);
181
+ new_len := (branch._children_len + u8(1));
182
+ new_ptr := _alloc_map_children(K, V, new_len);
183
+ if((usize(idx) > usize(0)), {
184
+ _copy_children(K, V, new_ptr, branch._children_ptr, u8(0), u8(0), idx);
185
+ });
186
+ child_offset := (sizeof(MapNode(K, V)) * usize(idx));
187
+ child_target := *(MapNode(K, V))((new_ptr &+ child_offset));
188
+ consume(child_target.* = child);
189
+ remaining := (branch._children_len - idx);
190
+ if((usize(remaining) > usize(0)), {
191
+ _copy_children(K, V, new_ptr, branch._children_ptr, (idx + u8(1)), idx, remaining);
192
+ });
193
+ MapBranch(K, V)(bitmap: (branch.bitmap | bit), _children_ptr: new_ptr, _children_len: new_len)
194
+ });
195
+
196
+ _branch_replace_child :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), bit: u32, child: MapNode(K, V), where(K <: (Eq(K), Hash, Send), V <: Send)) -> MapBranch(K, V))({
197
+ idx := _branch_index_for(K, V, branch, bit);
198
+ new_ptr := _alloc_map_children(K, V, branch._children_len);
199
+ _copy_children(K, V, new_ptr, branch._children_ptr, u8(0), u8(0), branch._children_len);
200
+ _branch_set_child(K, V, new_ptr, idx, child);
201
+ MapBranch(K, V)(bitmap: branch.bitmap, _children_ptr: new_ptr, _children_len: branch._children_len)
202
+ });
203
+
204
+ _branch_without_child :: (fn(comptime(K) : Type, comptime(V) : Type, branch: MapBranch(K, V), bit: u32, where(K <: (Eq(K), Hash, Send), V <: Send)) -> MapBranch(K, V))({
205
+ idx := _branch_index_for(K, V, branch, bit);
206
+ new_len := (branch._children_len - u8(1));
207
+ alloc_len := cond((new_len == u8(0)) => u8(1), true => new_len);
208
+ new_ptr := _alloc_map_children(K, V, alloc_len);
209
+ if((usize(idx) > usize(0)), {
210
+ _copy_children(K, V, new_ptr, branch._children_ptr, u8(0), u8(0), idx);
211
+ });
212
+ remaining := (branch._children_len - (idx + u8(1)));
213
+ if((usize(remaining) > usize(0)), {
214
+ _copy_children(K, V, new_ptr, branch._children_ptr, idx, (idx + u8(1)), remaining);
215
+ });
216
+ MapBranch(K, V)(bitmap: (branch.bitmap & (~(bit))), _children_ptr: new_ptr, _children_len: new_len)
217
+ });
218
+
219
+ // -- MapCollision helpers --
220
+
221
+ _alloc_pairs :: (fn(comptime(K) : Type, comptime(V) : Type, count: usize, where(K <: (Eq(K), Hash, Send), V <: Send)) -> *(Pair(K, V)))({
222
+ sz := (sizeof(Pair(K, V)) * count);
223
+ match(malloc(sz),
224
+ .Some(p) => *(Pair(K, V))(p),
225
+ .None => panic("imm.Map: collision allocation failed")
226
+ )
227
+ });
228
+
229
+ _coll_find_key :: (fn(comptime(K) : Type, comptime(V) : Type, coll: MapCollision(K, V), k: K, where(K <: (Eq(K), Hash, Send), V <: Send)) -> Option(usize))({
230
+ i := usize(0);
231
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
232
+ if(((coll._pairs_ptr &+ i).*.key == k), {
233
+ return .Some(i);
234
+ });
235
+ };
236
+ .None
237
+ });
238
+
239
+ /// Copy pairs element-by-element to ensure proper RC for K/V.
240
+ _copy_pairs :: (fn(
241
+ comptime(K) : Type, comptime(V) : Type,
242
+ dst: *(Pair(K, V)), src: *(Pair(K, V)),
243
+ dst_offset: usize, src_offset: usize, count: usize,
244
+ where(K <: (Eq(K), Hash, Send), V <: Send)
245
+ ) -> unit)({
246
+ i := usize(0);
247
+ while (i < count), (i = (i + usize(1))), {
248
+ consume((dst &+ (dst_offset + i)).* = (src &+ (src_offset + i)).*);
249
+ };
250
+ });
251
+
252
+ _coll_with_pair :: (fn(comptime(K) : Type, comptime(V) : Type, coll: MapCollision(K, V), k: K, v: V, where(K <: (Eq(K), Hash, Send), V <: Send)) -> MapCollision(K, V))({
253
+ match(_coll_find_key(K, V, coll, k),
254
+ .Some(idx) => {
255
+ new_ptr := _alloc_pairs(K, V, coll._pairs_len);
256
+ _copy_pairs(K, V, new_ptr, coll._pairs_ptr, usize(0), usize(0), coll._pairs_len);
257
+ (new_ptr &+ idx).* = Pair(K, V)(key: k, value: v);
258
+ return MapCollision(K, V)(hash: coll.hash, _pairs_ptr: new_ptr, _pairs_len: coll._pairs_len);
259
+ },
260
+ .None => {
261
+ new_len := (coll._pairs_len + usize(1));
262
+ new_ptr := _alloc_pairs(K, V, new_len);
263
+ _copy_pairs(K, V, new_ptr, coll._pairs_ptr, usize(0), usize(0), coll._pairs_len);
264
+ consume((new_ptr &+ coll._pairs_len).* = Pair(K, V)(key: k, value: v));
265
+ return MapCollision(K, V)(hash: coll.hash, _pairs_ptr: new_ptr, _pairs_len: new_len);
266
+ }
267
+ )
268
+ });
269
+
270
+ _coll_without_key :: (fn(comptime(K) : Type, comptime(V) : Type, coll: MapCollision(K, V), k: K, where(K <: (Eq(K), Hash, Send), V <: Send)) -> Option(MapCollision(K, V)))({
271
+ match(_coll_find_key(K, V, coll, k),
272
+ .Some(idx) => {
273
+ if((coll._pairs_len <= usize(2)), {
274
+ return .None;
275
+ });
276
+ new_len := (coll._pairs_len - usize(1));
277
+ new_ptr := _alloc_pairs(K, V, new_len);
278
+ if((usize(idx) > usize(0)), {
279
+ _copy_pairs(K, V, new_ptr, coll._pairs_ptr, usize(0), usize(0), idx);
280
+ });
281
+ remaining := (coll._pairs_len - (idx + usize(1)));
282
+ if((usize(remaining) > usize(0)), {
283
+ _copy_pairs(K, V, new_ptr, coll._pairs_ptr, idx, (idx + usize(1)), remaining);
284
+ });
285
+ return .Some(MapCollision(K, V)(hash: coll.hash, _pairs_ptr: new_ptr, _pairs_len: new_len));
286
+ },
287
+ .None => .Some(coll)
288
+ )
289
+ });
290
+
291
+ // -- Core HAMT algorithms --
292
+
293
+ _fragment :: (fn(hash: u64, shift: usize) -> u32)(
294
+ u32((hash >> u64(shift)) & MASK)
295
+ );
296
+
297
+ _bit_for :: (fn(frag: u32) -> u32)(
298
+ (u32(1) << frag)
299
+ );
300
+
301
+ _make_branch :: (fn(
302
+ comptime(K) : Type,
303
+ comptime(V) : Type,
304
+ shift: usize,
305
+ node1: MapNode(K, V),
306
+ hash1: u64,
307
+ node2: MapNode(K, V),
308
+ hash2: u64,
309
+ where(K <: (Eq(K), Hash, Send), V <: Send)
310
+ ) -> MapNode(K, V))({
311
+ frag1 := _fragment(hash1, shift);
312
+ frag2 := _fragment(hash2, shift);
313
+ if((frag1 == frag2), {
314
+ child := _make_branch(K, V, (shift + BITS), node1, hash1, node2, hash2);
315
+ ptr := _alloc_map_children(K, V, u8(1));
316
+ consume((*(MapNode(K, V))(ptr)).* = child);
317
+ return .Branch(MapBranch(K, V)(
318
+ bitmap: _bit_for(frag1),
319
+ _children_ptr: ptr,
320
+ _children_len: u8(1)
321
+ ));
322
+ });
323
+ bit1 := _bit_for(frag1);
324
+ bit2 := _bit_for(frag2);
325
+ bitmap := (bit1 | bit2);
326
+ ptr := _alloc_map_children(K, V, u8(2));
327
+ children := *(MapNode(K, V))(ptr);
328
+ if((frag1 < frag2), {
329
+ consume(children.* = node1);
330
+ consume((children &+ usize(1)).* = node2);
331
+ }, {
332
+ consume(children.* = node2);
333
+ consume((children &+ usize(1)).* = node1);
334
+ });
335
+ .Branch(MapBranch(K, V)(
336
+ bitmap: bitmap,
337
+ _children_ptr: ptr,
338
+ _children_len: u8(2)
339
+ ))
340
+ });
341
+
342
+ InsertResult :: (fn(comptime(K) : Type, comptime(V) : Type, where(K <: (Eq(K), Hash, Send), V <: Send)) -> comptime(Type))(
343
+ struct(node: MapNode(K, V), added: bool)
344
+ );
345
+
346
+ _node_insert :: (fn(
347
+ comptime(K) : Type,
348
+ comptime(V) : Type,
349
+ node: MapNode(K, V),
350
+ shift: usize,
351
+ hash: u64,
352
+ k: K,
353
+ v: V,
354
+ where(K <: (Eq(K), Hash, Send), V <: Send)
355
+ ) -> InsertResult(K, V))(
356
+ match(node,
357
+ .Leaf(leaf) => {
358
+ if((leaf.hash == hash), {
359
+ if((leaf.key == k), {
360
+ return InsertResult(K, V)(
361
+ node: .Leaf(MapLeaf(K, V)(hash: hash, key: k, value: v)),
362
+ added: false
363
+ );
364
+ });
365
+ pairs_ptr := _alloc_pairs(K, V, usize(2));
366
+ consume(pairs_ptr.* = Pair(K, V)(key: leaf.key, value: leaf.value));
367
+ consume((pairs_ptr &+ usize(1)).* = Pair(K, V)(key: k, value: v));
368
+ return InsertResult(K, V)(
369
+ node: .Collision(MapCollision(K, V)(hash: hash, _pairs_ptr: pairs_ptr, _pairs_len: usize(2))),
370
+ added: true
371
+ );
372
+ });
373
+ new_leaf := MapNode(K, V).Leaf(MapLeaf(K, V)(hash: hash, key: k, value: v));
374
+ return InsertResult(K, V)(
375
+ node: _make_branch(K, V, shift, node, leaf.hash, new_leaf, hash),
376
+ added: true
377
+ );
378
+ },
379
+ .Branch(branch) => {
380
+ frag := _fragment(hash, shift);
381
+ bit := _bit_for(frag);
382
+ if(_branch_has_child(K, V, branch, bit), {
383
+ idx := _branch_index_for(K, V, branch, bit);
384
+ child := _branch_child_at(K, V, branch, idx);
385
+ result := _node_insert(K, V, child, (shift + BITS), hash, k, v);
386
+ return InsertResult(K, V)(
387
+ node: .Branch(_branch_replace_child(K, V, branch, bit, result.node)),
388
+ added: result.added
389
+ );
390
+ });
391
+ new_leaf_node := MapNode(K, V).Leaf(MapLeaf(K, V)(hash: hash, key: k, value: v));
392
+ return InsertResult(K, V)(
393
+ node: .Branch(_branch_with_child(K, V, branch, bit, new_leaf_node)),
394
+ added: true
395
+ );
396
+ },
397
+ .Collision(coll) => {
398
+ if((coll.hash == hash), {
399
+ found := _coll_find_key(K, V, coll, k);
400
+ return InsertResult(K, V)(
401
+ node: .Collision(_coll_with_pair(K, V, coll, k, v)),
402
+ added: found.is_none()
403
+ );
404
+ });
405
+ coll_node := MapNode(K, V).Collision(coll);
406
+ new_leaf := MapNode(K, V).Leaf(MapLeaf(K, V)(hash: hash, key: k, value: v));
407
+ return InsertResult(K, V)(
408
+ node: _make_branch(K, V, shift, coll_node, coll.hash, new_leaf, hash),
409
+ added: true
410
+ );
411
+ }
412
+ )
413
+ );
414
+
415
+ _node_get :: (fn(
416
+ comptime(K) : Type,
417
+ comptime(V) : Type,
418
+ node: MapNode(K, V),
419
+ shift: usize,
420
+ hash: u64,
421
+ k: K,
422
+ where(K <: (Eq(K), Hash, Send), V <: Send)
423
+ ) -> Option(V))(
424
+ match(node,
425
+ .Leaf(leaf) => cond(
426
+ ((leaf.hash == hash) && (leaf.key == k)) => .Some(leaf.value),
427
+ true => .None
428
+ ),
429
+ .Branch(branch) => {
430
+ frag := _fragment(hash, shift);
431
+ bit := _bit_for(frag);
432
+ if(!(_branch_has_child(K, V, branch, bit)), {
433
+ return .None;
434
+ });
435
+ idx := _branch_index_for(K, V, branch, bit);
436
+ return _node_get(K, V, _branch_child_at(K, V, branch, idx), (shift + BITS), hash, k);
437
+ },
438
+ .Collision(coll) => {
439
+ if((coll.hash != hash), {
440
+ return .None;
441
+ });
442
+ i := usize(0);
443
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
444
+ pair := (coll._pairs_ptr &+ i).*;
445
+ if((pair.key == k), {
446
+ return .Some(pair.value);
447
+ });
448
+ };
449
+ .None
450
+ }
451
+ )
452
+ );
453
+
454
+ RemoveResult :: (fn(comptime(K) : Type, comptime(V) : Type, where(K <: (Eq(K), Hash, Send), V <: Send)) -> comptime(Type))(
455
+ struct(node: Option(MapNode(K, V)), removed: bool)
456
+ );
457
+
458
+ _node_remove :: (fn(
459
+ comptime(K) : Type,
460
+ comptime(V) : Type,
461
+ node: MapNode(K, V),
462
+ shift: usize,
463
+ hash: u64,
464
+ k: K,
465
+ where(K <: (Eq(K), Hash, Send), V <: Send)
466
+ ) -> RemoveResult(K, V))(
467
+ match(node,
468
+ .Leaf(leaf) => cond(
469
+ ((leaf.hash == hash) && (leaf.key == k)) =>
470
+ RemoveResult(K, V)(node: .None, removed: true),
471
+ true =>
472
+ RemoveResult(K, V)(node: .Some(node), removed: false)
473
+ ),
474
+ .Branch(branch) => {
475
+ frag := _fragment(hash, shift);
476
+ bit := _bit_for(frag);
477
+ if(!(_branch_has_child(K, V, branch, bit)), {
478
+ return RemoveResult(K, V)(node: .Some(node), removed: false);
479
+ });
480
+ idx := _branch_index_for(K, V, branch, bit);
481
+ child := _branch_child_at(K, V, branch, idx);
482
+ sub := _node_remove(K, V, child, (shift + BITS), hash, k);
483
+ if(!(sub.removed), {
484
+ return RemoveResult(K, V)(node: .Some(node), removed: false);
485
+ });
486
+ match(sub.node,
487
+ .Some(new_child) => {
488
+ return RemoveResult(K, V)(
489
+ node: .Some(.Branch(_branch_replace_child(K, V, branch, bit, new_child))),
490
+ removed: true
491
+ );
492
+ },
493
+ .None => {
494
+ if((branch._children_len == u8(1)), {
495
+ return RemoveResult(K, V)(node: .None, removed: true);
496
+ });
497
+ if((branch._children_len == u8(2)), {
498
+ other_idx := cond((idx == u8(0)) => u8(1), true => u8(0));
499
+ remaining := _branch_child_at(K, V, branch, other_idx);
500
+ match(remaining,
501
+ .Leaf(_) => {
502
+ return RemoveResult(K, V)(node: .Some(remaining), removed: true);
503
+ },
504
+ _ => ()
505
+ );
506
+ });
507
+ return RemoveResult(K, V)(
508
+ node: .Some(.Branch(_branch_without_child(K, V, branch, bit))),
509
+ removed: true
510
+ );
511
+ }
512
+ );
513
+ },
514
+ .Collision(coll) => {
515
+ if((coll.hash != hash), {
516
+ return RemoveResult(K, V)(node: .Some(node), removed: false);
517
+ });
518
+ match(_coll_without_key(K, V, coll, k),
519
+ .Some(new_coll) => {
520
+ if((new_coll._pairs_len == coll._pairs_len), {
521
+ return RemoveResult(K, V)(node: .Some(node), removed: false);
522
+ });
523
+ return RemoveResult(K, V)(
524
+ node: .Some(.Collision(new_coll)),
525
+ removed: true
526
+ );
527
+ },
528
+ .None => {
529
+ remaining_idx := cond(
530
+ ((coll._pairs_ptr).*.key == k) => usize(1),
531
+ true => usize(0)
532
+ );
533
+ remaining_pair := (coll._pairs_ptr &+ remaining_idx).*;
534
+ return RemoveResult(K, V)(
535
+ node: .Some(.Leaf(MapLeaf(K, V)(hash: coll.hash, key: remaining_pair.key, value: remaining_pair.value))),
536
+ removed: true
537
+ );
538
+ }
539
+ );
540
+ }
541
+ )
542
+ );
543
+
544
+ // -- Collection helpers --
545
+
546
+ { List } :: import "./list.yo";
547
+
548
+ // -- Eq trait --
549
+
550
+ _merge_from_node :: (fn(
551
+ comptime(K) : Type,
552
+ comptime(V) : Type,
553
+ acc: Map(K, V),
554
+ node: MapNode(K, V),
555
+ where(K <: (Eq(K), Hash, Send), V <: Send)
556
+ ) -> Map(K, V))(
557
+ match(node,
558
+ .Leaf(leaf) => acc.insert(leaf.key, leaf.value),
559
+ .Branch(branch) => {
560
+ (result : Map(K, V)) = acc;
561
+ i := u8(0);
562
+ while (i < branch._children_len), (i = (i + u8(1))), {
563
+ result = _merge_from_node(K, V, result, _branch_child_at(K, V, branch, i));
564
+ };
565
+ result
566
+ },
567
+ .Collision(coll) => {
568
+ (result : Map(K, V)) = acc;
569
+ i := usize(0);
570
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
571
+ pair := (coll._pairs_ptr &+ i).*;
572
+ result = result.insert(pair.key, pair.value);
573
+ };
574
+ result
575
+ }
576
+ )
577
+ );
578
+
579
+ _collect_keys :: (fn(
580
+ comptime(K) : Type,
581
+ comptime(V) : Type,
582
+ node: MapNode(K, V),
583
+ acc: List(K),
584
+ where(K <: (Eq(K), Hash, Send), V <: Send)
585
+ ) -> List(K))(
586
+ match(node,
587
+ .Leaf(leaf) => acc.prepend(leaf.key),
588
+ .Branch(branch) => {
589
+ (result : List(K)) = acc;
590
+ i := u8(0);
591
+ while (i < branch._children_len), (i = (i + u8(1))), {
592
+ result = _collect_keys(K, V, _branch_child_at(K, V, branch, i), result);
593
+ };
594
+ result
595
+ },
596
+ .Collision(coll) => {
597
+ (result : List(K)) = acc;
598
+ i := usize(0);
599
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
600
+ result = result.prepend((coll._pairs_ptr &+ i).*.key);
601
+ };
602
+ result
603
+ }
604
+ )
605
+ );
606
+
607
+ _collect_values :: (fn(
608
+ comptime(K) : Type,
609
+ comptime(V) : Type,
610
+ node: MapNode(K, V),
611
+ acc: List(V),
612
+ where(K <: (Eq(K), Hash, Send), V <: Send)
613
+ ) -> List(V))(
614
+ match(node,
615
+ .Leaf(leaf) => acc.prepend(leaf.value),
616
+ .Branch(branch) => {
617
+ (result : List(V)) = acc;
618
+ i := u8(0);
619
+ while (i < branch._children_len), (i = (i + u8(1))), {
620
+ result = _collect_values(K, V, _branch_child_at(K, V, branch, i), result);
621
+ };
622
+ result
623
+ },
624
+ .Collision(coll) => {
625
+ (result : List(V)) = acc;
626
+ i := usize(0);
627
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
628
+ result = result.prepend((coll._pairs_ptr &+ i).*.value);
629
+ };
630
+ result
631
+ }
632
+ )
633
+ );
634
+
635
+ _collect_entries :: (fn(
636
+ comptime(K) : Type,
637
+ comptime(V) : Type,
638
+ node: MapNode(K, V),
639
+ acc: List(Pair(K, V)),
640
+ where(K <: (Eq(K), Hash, Send), V <: Send)
641
+ ) -> List(Pair(K, V)))(
642
+ match(node,
643
+ .Leaf(leaf) => acc.prepend(Pair(K, V)(key: leaf.key, value: leaf.value)),
644
+ .Branch(branch) => {
645
+ (result : List(Pair(K, V))) = acc;
646
+ i := u8(0);
647
+ while (i < branch._children_len), (i = (i + u8(1))), {
648
+ result = _collect_entries(K, V, _branch_child_at(K, V, branch, i), result);
649
+ };
650
+ result
651
+ },
652
+ .Collision(coll) => {
653
+ (result : List(Pair(K, V))) = acc;
654
+ i := usize(0);
655
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
656
+ result = result.prepend((coll._pairs_ptr &+ i).*);
657
+ };
658
+ result
659
+ }
660
+ )
661
+ );
662
+
663
+ _map_values_node :: (fn(
664
+ comptime(K) : Type,
665
+ comptime(V) : Type,
666
+ comptime(U) : Type,
667
+ node: MapNode(K, V),
668
+ f: Impl(Fn(a: V) -> U),
669
+ where(K <: (Eq(K), Hash, Send), V <: Send, U <: Send)
670
+ ) -> MapNode(K, U))(
671
+ match(node,
672
+ .Leaf(leaf) => .Leaf(MapLeaf(K, U)(hash: leaf.hash, key: leaf.key, value: f(leaf.value))),
673
+ .Branch(branch) => {
674
+ new_ptr := _alloc_map_children(K, U, branch._children_len);
675
+ new_children := *(MapNode(K, U))(new_ptr);
676
+ i := u8(0);
677
+ while (i < branch._children_len), (i = (i + u8(1))), {
678
+ consume((new_children &+ usize(i)).* = _map_values_node(K, V, U, _branch_child_at(K, V, branch, i), f));
679
+ };
680
+ .Branch(MapBranch(K, U)(
681
+ bitmap: branch.bitmap,
682
+ _children_ptr: new_ptr,
683
+ _children_len: branch._children_len
684
+ ))
685
+ },
686
+ .Collision(coll) => {
687
+ new_ptr := _alloc_pairs(K, U, coll._pairs_len);
688
+ i := usize(0);
689
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
690
+ old_pair := (coll._pairs_ptr &+ i).*;
691
+ consume((new_ptr &+ i).* = Pair(K, U)(key: old_pair.key, value: f(old_pair.value)));
692
+ };
693
+ .Collision(MapCollision(K, U)(
694
+ hash: coll.hash,
695
+ _pairs_ptr: new_ptr,
696
+ _pairs_len: coll._pairs_len
697
+ ))
698
+ }
699
+ )
700
+ );
701
+
702
+ _filter_from_node :: (fn(
703
+ comptime(K) : Type,
704
+ comptime(V) : Type,
705
+ acc: Map(K, V),
706
+ node: MapNode(K, V),
707
+ f: Impl(Fn(k: K, v: V) -> bool),
708
+ where(K <: (Eq(K), Hash, Send), V <: Send)
709
+ ) -> Map(K, V))(
710
+ match(node,
711
+ .Leaf(leaf) => cond(
712
+ f(leaf.key, leaf.value) => acc.insert(leaf.key, leaf.value),
713
+ true => acc
714
+ ),
715
+ .Branch(branch) => {
716
+ (result : Map(K, V)) = acc;
717
+ i := u8(0);
718
+ while (i < branch._children_len), (i = (i + u8(1))), {
719
+ result = _filter_from_node(K, V, result, _branch_child_at(K, V, branch, i), f);
720
+ };
721
+ result
722
+ },
723
+ .Collision(coll) => {
724
+ (result : Map(K, V)) = acc;
725
+ i := usize(0);
726
+ while (i < coll._pairs_len), (i = (i + usize(1))), {
727
+ pair := (coll._pairs_ptr &+ i).*;
728
+ if(f(pair.key, pair.value), {
729
+ result = result.insert(pair.key, pair.value);
730
+ });
731
+ };
732
+ result
733
+ }
734
+ )
735
+ );
736
+
737
+ _all_entries_match :: (fn(
738
+ comptime(K) : Type,
739
+ comptime(V) : Type,
740
+ node: MapNode(K, V),
741
+ target: Map(K, V),
742
+ where(K <: (Eq(K), Hash, Send), V <: (Send, Eq(V)))
743
+ ) -> bool)(
744
+ match(node,
745
+ .Leaf(leaf) => match(target.get(leaf.key),
746
+ .Some(tv) => (tv == leaf.value),
747
+ .None => false
748
+ ),
749
+ .Branch(branch) => {
750
+ i := u8(0);
751
+ (ok : bool) = true;
752
+ while ((i < branch._children_len) && ok), (i = (i + u8(1))), {
753
+ if(!(_all_entries_match(K, V, _branch_child_at(K, V, branch, i), target)), {
754
+ ok = false;
755
+ });
756
+ };
757
+ ok
758
+ },
759
+ .Collision(coll) => {
760
+ i := usize(0);
761
+ (ok : bool) = true;
762
+ while ((i < coll._pairs_len) && ok), (i = (i + usize(1))), {
763
+ pair := (coll._pairs_ptr &+ i).*;
764
+ match(target.get(pair.key),
765
+ .Some(tv) => {
766
+ if((tv != pair.value), {
767
+ ok = false;
768
+ });
769
+ },
770
+ .None => {
771
+ ok = false;
772
+ }
773
+ );
774
+ };
775
+ ok
776
+ }
777
+ )
778
+ );
779
+
780
+ // -- Public Map API --
781
+
782
+ impl(forall(K : Type, V : Type), where(K <: (Eq(K), Hash, Send), V <: Send), Map(K, V),
783
+ /// Create an empty map.
784
+ new : (fn() -> Self)(
785
+ Self(_root: .None, _len: usize(0))
786
+ ),
787
+
788
+ /// Number of key-value entries.
789
+ len : (fn(self: Self) -> usize)(self._len),
790
+
791
+ /// Check if the map is empty.
792
+ is_empty : (fn(self: Self) -> bool)((self._len == usize(0))),
793
+
794
+ /// Look up the value associated with `key`.
795
+ get : (fn(self: Self, key: K) -> Option(V))(
796
+ match(self._root,
797
+ .Some(root) => _node_get(K, V, root, usize(0), key.hash(), key),
798
+ .None => .None
799
+ )
800
+ ),
801
+
802
+ /// Check if the map contains `key`.
803
+ contains_key : (fn(self: Self, key: K) -> bool)(
804
+ self.get(key).is_some()
805
+ ),
806
+
807
+ /// Return a new map with `key` mapped to `value`.
808
+ insert : (fn(self: Self, key: K, value: V) -> Self)(
809
+ match(self._root,
810
+ .Some(root) => {
811
+ result := _node_insert(K, V, root, usize(0), key.hash(), key, value);
812
+ new_len := cond(result.added => (self._len + usize(1)), true => self._len);
813
+ return Self(_root: .Some(result.node), _len: new_len);
814
+ },
815
+ .None => Self(
816
+ _root: .Some(.Leaf(MapLeaf(K, V)(hash: key.hash(), key: key, value: value))),
817
+ _len: usize(1)
818
+ )
819
+ )
820
+ ),
821
+
822
+ /// Return a new map without `key`.
823
+ remove : (fn(self: Self, key: K) -> Self)(
824
+ match(self._root,
825
+ .Some(root) => {
826
+ result := _node_remove(K, V, root, usize(0), key.hash(), key);
827
+ if(!(result.removed), {
828
+ return self;
829
+ });
830
+ new_len := (self._len - usize(1));
831
+ return Self(_root: result.node, _len: new_len);
832
+ },
833
+ .None => self
834
+ )
835
+ ),
836
+
837
+ /// Merge another map into this one. Keys from `other` overwrite `self`.
838
+ merge : (fn(self: Self, other: Self) -> Self)(
839
+ match(other._root,
840
+ .Some(root) => _merge_from_node(K, V, self, root),
841
+ .None => self
842
+ )
843
+ ),
844
+
845
+ /// Collect all keys into a list.
846
+ keys : (fn(self: Self) -> List(K))(
847
+ match(self._root,
848
+ .Some(root) => _collect_keys(K, V, root, List(K).new()),
849
+ .None => List(K).new()
850
+ )
851
+ ),
852
+
853
+ /// Collect all values into a list.
854
+ values : (fn(self: Self) -> List(V))(
855
+ match(self._root,
856
+ .Some(root) => _collect_values(K, V, root, List(V).new()),
857
+ .None => List(V).new()
858
+ )
859
+ ),
860
+
861
+ /// Collect all entries into a list of pairs.
862
+ entries : (fn(self: Self) -> List(Pair(K, V)))(
863
+ match(self._root,
864
+ .Some(root) => _collect_entries(K, V, root, List(Pair(K, V)).new()),
865
+ .None => List(Pair(K, V)).new()
866
+ )
867
+ ),
868
+
869
+ /// Apply a function to each value, producing a new map.
870
+ map_values : (fn(forall(U : Type), self: Self, f: Impl(Fn(a: V) -> U), where(U <: Send)) -> Map(K, U))(
871
+ match(self._root,
872
+ .Some(root) => Map(K, U)(_root: .Some(_map_values_node(K, V, U, root, f)), _len: self._len),
873
+ .None => Map(K, U).new()
874
+ )
875
+ ),
876
+
877
+ /// Keep only entries where the predicate returns true.
878
+ filter : (fn(self: Self, f: Impl(Fn(k: K, v: V) -> bool)) -> Self)({
879
+ (result : Self) = Self.new();
880
+ match(self._root,
881
+ .Some(root) => {
882
+ result = _filter_from_node(K, V, result, root, f);
883
+ },
884
+ .None => ()
885
+ );
886
+ result
887
+ }),
888
+
889
+ /// Create a map from a slice of key-value pairs.
890
+ from_entries : (fn(pairs: Slice(Pair(K, V))) -> Self)({
891
+ (result : Self) = Self.new();
892
+ i := usize(0);
893
+ plen := pairs.len();
894
+ while (i < plen), (i = (i + usize(1))), {
895
+ p := (pairs.ptr() &+ i).*;
896
+ result = result.insert(p.key, p.value);
897
+ };
898
+ result
899
+ })
900
+ );
901
+
902
+ impl(forall(K : Type, V : Type), where(K <: (Eq(K), Hash, Send), V <: (Send, Eq(V))), Map(K, V), Eq(Map(K, V))(
903
+ (==) : (fn(lhs: Self, rhs: Self) -> bool)({
904
+ if((lhs._len != rhs._len), {
905
+ return false;
906
+ });
907
+ if(((lhs._len == usize(0)) && (rhs._len == usize(0))), {
908
+ return true;
909
+ });
910
+ match(lhs._root,
911
+ .Some(root) => _all_entries_match(K, V, root, rhs),
912
+ .None => true
913
+ )
914
+ })
915
+ ));
916
+
917
+ export Map, MapNode, MapBranch, MapLeaf, MapCollision, Pair, InsertResult, RemoveResult;