@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.
- package/README.md +43 -1
- package/out/cjs/index.cjs +581 -601
- package/out/cjs/yo-cli.cjs +739 -733
- package/out/cjs/yo-lsp.cjs +11615 -0
- package/out/esm/index.mjs +530 -550
- package/out/types/src/cache.d.ts +2 -0
- package/out/types/src/codegen/exprs/return.d.ts +1 -1
- package/out/types/src/codegen/types/generation.d.ts +0 -2
- package/out/types/src/codegen/utils/index.d.ts +2 -8
- package/out/types/src/doc/extractor.d.ts +4 -0
- package/out/types/src/evaluator/builtins/rc-fns.d.ts +0 -5
- package/out/types/src/evaluator/context.d.ts +7 -3
- package/out/types/src/evaluator/trait-checking.d.ts +2 -0
- package/out/types/src/evaluator/types/object.d.ts +2 -1
- package/out/types/src/evaluator/types/struct.d.ts +2 -1
- package/out/types/src/evaluator/types/utils.d.ts +3 -8
- package/out/types/src/evaluator/values/impl.d.ts +9 -1
- package/out/types/src/expr.d.ts +1 -2
- package/out/types/src/function-value.d.ts +1 -0
- package/out/types/src/lsp/completion.d.ts +3 -0
- package/out/types/src/lsp/definition.d.ts +3 -0
- package/out/types/src/lsp/diagnostics.d.ts +6 -0
- package/out/types/src/lsp/document-manager.d.ts +31 -0
- package/out/types/src/lsp/folding.d.ts +3 -0
- package/out/types/src/lsp/hover.d.ts +3 -0
- package/out/types/src/lsp/inlay-hints.d.ts +3 -0
- package/out/types/src/lsp/references.d.ts +3 -0
- package/out/types/src/lsp/rename.d.ts +16 -0
- package/out/types/src/lsp/server.d.ts +1 -0
- package/out/types/src/lsp/signature-help.d.ts +3 -0
- package/out/types/src/lsp/symbols.d.ts +3 -0
- package/out/types/src/lsp/utils.d.ts +11 -0
- package/out/types/src/tests/lsp.test.d.ts +1 -0
- package/out/types/src/tests/version.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +2 -3
- package/out/types/src/types/definitions.d.ts +3 -6
- package/out/types/src/types/guards.d.ts +5 -2
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/version-cache.d.ts +7 -0
- package/out/types/src/version.d.ts +5 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -1
- package/scripts/build-site.ts +32 -15
- package/scripts/check-liburing.js +2 -2
- package/std/imm/list.yo +254 -0
- package/std/imm/map.yo +917 -0
- package/std/imm/set.yo +179 -0
- package/std/imm/sorted_map.yo +595 -0
- package/std/imm/sorted_set.yo +202 -0
- package/std/imm/string.yo +667 -0
- package/std/imm/vec.yo +456 -0
- package/std/prelude.yo +22 -5
- package/std/sync/channel.yo +92 -44
- package/std/sync/cond.yo +5 -1
- package/std/sync/mutex.yo +5 -1
- package/std/sync/once.yo +2 -1
- package/std/sync/rwlock.yo +2 -1
- package/std/sync/waitgroup.yo +2 -1
- package/out/types/src/codegen/exprs/arc.d.ts +0 -5
- 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;
|