@shd101wyy/yo 0.1.26 → 0.1.27

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 (167) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +4 -4
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
  3. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  4. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -26
  5. package/.github/skills/yo-project-workflow/SKILL.md +6 -3
  6. package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
  7. package/.github/skills/yo-syntax/SKILL.md +7 -6
  8. package/.github/skills/yo-syntax/syntax-cheatsheet.md +73 -60
  9. package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
  10. package/README.md +10 -8
  11. package/out/cjs/index.cjs +456 -438
  12. package/out/cjs/yo-cli.cjs +576 -543
  13. package/out/cjs/yo-lsp.cjs +559 -532
  14. package/out/esm/index.mjs +281 -263
  15. package/out/types/src/formatter.d.ts +11 -0
  16. package/out/types/src/lsp/formatting.d.ts +2 -0
  17. package/out/types/src/tests/formatter.test.d.ts +1 -0
  18. package/out/types/tsconfig.tsbuildinfo +1 -1
  19. package/package.json +1 -1
  20. package/std/alg/hash.yo +13 -21
  21. package/std/allocator.yo +25 -40
  22. package/std/async.yo +3 -7
  23. package/std/build.yo +105 -151
  24. package/std/cli/arg_parser.yo +184 -169
  25. package/std/collections/array_list.yo +350 -314
  26. package/std/collections/btree_map.yo +142 -131
  27. package/std/collections/deque.yo +132 -128
  28. package/std/collections/hash_map.yo +542 -566
  29. package/std/collections/hash_set.yo +623 -687
  30. package/std/collections/linked_list.yo +275 -293
  31. package/std/collections/ordered_map.yo +113 -85
  32. package/std/collections/priority_queue.yo +73 -73
  33. package/std/crypto/md5.yo +191 -95
  34. package/std/crypto/random.yo +56 -64
  35. package/std/crypto/sha256.yo +151 -107
  36. package/std/encoding/base64.yo +87 -81
  37. package/std/encoding/hex.yo +43 -50
  38. package/std/encoding/html.yo +56 -81
  39. package/std/encoding/html_char_utils.yo +7 -13
  40. package/std/encoding/html_entities.yo +2248 -2253
  41. package/std/encoding/json.yo +316 -224
  42. package/std/encoding/punycode.yo +86 -116
  43. package/std/encoding/toml.yo +67 -66
  44. package/std/encoding/utf16.yo +37 -44
  45. package/std/env.yo +62 -91
  46. package/std/error.yo +7 -15
  47. package/std/fmt/display.yo +5 -9
  48. package/std/fmt/index.yo +8 -14
  49. package/std/fmt/to_string.yo +330 -315
  50. package/std/fmt/writer.yo +58 -87
  51. package/std/fs/dir.yo +83 -102
  52. package/std/fs/file.yo +147 -180
  53. package/std/fs/metadata.yo +45 -78
  54. package/std/fs/temp.yo +55 -65
  55. package/std/fs/types.yo +27 -40
  56. package/std/fs/walker.yo +53 -68
  57. package/std/gc.yo +5 -8
  58. package/std/glob.yo +30 -43
  59. package/std/http/client.yo +107 -120
  60. package/std/http/http.yo +106 -96
  61. package/std/http/index.yo +4 -6
  62. package/std/imm/list.yo +88 -93
  63. package/std/imm/map.yo +528 -464
  64. package/std/imm/set.yo +52 -57
  65. package/std/imm/sorted_map.yo +340 -286
  66. package/std/imm/sorted_set.yo +57 -63
  67. package/std/imm/string.yo +404 -345
  68. package/std/imm/vec.yo +173 -181
  69. package/std/io/reader.yo +3 -6
  70. package/std/io/writer.yo +4 -8
  71. package/std/libc/assert.yo +5 -9
  72. package/std/libc/ctype.yo +32 -22
  73. package/std/libc/dirent.yo +26 -25
  74. package/std/libc/errno.yo +164 -90
  75. package/std/libc/fcntl.yo +52 -45
  76. package/std/libc/float.yo +66 -44
  77. package/std/libc/limits.yo +42 -33
  78. package/std/libc/math.yo +53 -82
  79. package/std/libc/signal.yo +72 -47
  80. package/std/libc/stdatomic.yo +217 -188
  81. package/std/libc/stdint.yo +5 -29
  82. package/std/libc/stdio.yo +5 -29
  83. package/std/libc/stdlib.yo +32 -39
  84. package/std/libc/string.yo +5 -23
  85. package/std/libc/sys/stat.yo +58 -56
  86. package/std/libc/time.yo +5 -19
  87. package/std/libc/unistd.yo +5 -20
  88. package/std/libc/wctype.yo +6 -9
  89. package/std/libc/windows.yo +26 -30
  90. package/std/log.yo +41 -55
  91. package/std/net/addr.yo +102 -97
  92. package/std/net/dns.yo +27 -28
  93. package/std/net/errors.yo +50 -49
  94. package/std/net/tcp.yo +113 -124
  95. package/std/net/udp.yo +55 -66
  96. package/std/os/env.yo +35 -33
  97. package/std/os/signal.yo +15 -25
  98. package/std/path.yo +276 -311
  99. package/std/prelude.yo +6304 -4315
  100. package/std/process/command.yo +87 -103
  101. package/std/process/index.yo +12 -31
  102. package/std/regex/compiler.yo +196 -95
  103. package/std/regex/flags.yo +58 -39
  104. package/std/regex/index.yo +157 -173
  105. package/std/regex/match.yo +20 -31
  106. package/std/regex/node.yo +134 -152
  107. package/std/regex/parser.yo +283 -259
  108. package/std/regex/unicode.yo +172 -202
  109. package/std/regex/vm.yo +155 -171
  110. package/std/string/index.yo +5 -7
  111. package/std/string/rune.yo +45 -55
  112. package/std/string/string.yo +937 -964
  113. package/std/string/string_builder.yo +94 -104
  114. package/std/string/unicode.yo +46 -64
  115. package/std/sync/channel.yo +72 -73
  116. package/std/sync/cond.yo +31 -36
  117. package/std/sync/mutex.yo +30 -32
  118. package/std/sync/once.yo +13 -16
  119. package/std/sync/rwlock.yo +26 -31
  120. package/std/sync/waitgroup.yo +20 -25
  121. package/std/sys/advise.yo +16 -24
  122. package/std/sys/bufio/buf_reader.yo +77 -93
  123. package/std/sys/bufio/buf_writer.yo +52 -65
  124. package/std/sys/clock.yo +4 -9
  125. package/std/sys/constants.yo +77 -61
  126. package/std/sys/copy.yo +4 -10
  127. package/std/sys/dir.yo +26 -43
  128. package/std/sys/dns.yo +41 -61
  129. package/std/sys/errors.yo +95 -103
  130. package/std/sys/events.yo +45 -57
  131. package/std/sys/externs.yo +319 -267
  132. package/std/sys/fallocate.yo +7 -11
  133. package/std/sys/fcntl.yo +14 -22
  134. package/std/sys/file.yo +26 -40
  135. package/std/sys/future.yo +5 -8
  136. package/std/sys/iov.yo +12 -25
  137. package/std/sys/lock.yo +12 -13
  138. package/std/sys/mmap.yo +38 -43
  139. package/std/sys/path.yo +3 -8
  140. package/std/sys/perm.yo +7 -21
  141. package/std/sys/pipe.yo +5 -12
  142. package/std/sys/process.yo +23 -29
  143. package/std/sys/seek.yo +10 -12
  144. package/std/sys/signal.yo +7 -13
  145. package/std/sys/signals.yo +52 -35
  146. package/std/sys/socket.yo +63 -58
  147. package/std/sys/socketpair.yo +3 -6
  148. package/std/sys/sockinfo.yo +11 -20
  149. package/std/sys/statfs.yo +11 -34
  150. package/std/sys/statx.yo +25 -52
  151. package/std/sys/sysinfo.yo +15 -20
  152. package/std/sys/tcp.yo +62 -92
  153. package/std/sys/temp.yo +5 -9
  154. package/std/sys/time.yo +5 -15
  155. package/std/sys/timer.yo +6 -11
  156. package/std/sys/tty.yo +10 -18
  157. package/std/sys/udp.yo +22 -39
  158. package/std/sys/umask.yo +3 -6
  159. package/std/sys/unix.yo +33 -52
  160. package/std/testing/bench.yo +49 -52
  161. package/std/thread.yo +10 -15
  162. package/std/time/datetime.yo +105 -89
  163. package/std/time/duration.yo +43 -56
  164. package/std/time/instant.yo +13 -18
  165. package/std/time/sleep.yo +5 -9
  166. package/std/url/index.yo +184 -209
  167. package/std/worker.yo +6 -10
@@ -1,8 +1,6 @@
1
1
  //! Hash set using SwissTable algorithm with set-theoretic operations.
2
-
3
- { GlobalAllocator, AllocError } :: import "../allocator.yo";
2
+ { GlobalAllocator, AllocError } :: import("../allocator.yo");
4
3
  { malloc, calloc, realloc, free } :: GlobalAllocator;
5
-
6
4
  /// Error variants for HashSet operations.
7
5
  HashSetError :: enum(
8
6
  /// Memory allocation failed.
@@ -12,430 +10,380 @@ HashSetError :: enum(
12
10
  /// Capacity calculation overflowed.
13
11
  CapacityOverflow
14
12
  );
15
-
16
13
  /// Control byte for an empty slot.
17
14
  CTRL_EMPTY :: u8(255);
18
15
  /// Control byte for a deleted slot (tombstone).
19
16
  CTRL_DELETED :: u8(254);
20
-
21
17
  /// Default initial capacity (must be power of 2).
22
18
  DEFAULT_CAPACITY :: usize(16);
23
-
24
19
  /// Maximum load factor numerator (7/8 = 0.875).
25
20
  MAX_LOAD_FACTOR_NUMERATOR :: usize(7);
26
21
  MAX_LOAD_FACTOR_DENOMINATOR :: usize(8);
27
-
28
22
  /// Extract H2 hash (lower 7 bits) from full hash.
29
- h2_hash :: (fn(hash: u64) -> u8)
30
- (u8((hash & u64(127))))
31
- ;
32
-
23
+ h2_hash :: (fn(hash : u64) -> u8)(u8(hash & u64(127)));
33
24
  /// Extract H1 hash (upper bits) for slot index.
34
- h1_hash :: (fn(hash: u64, capacity: usize) -> usize)
35
- ((usize((hash >> u64(7))) % capacity))
36
- ;
37
-
25
+ h1_hash :: (fn(hash : u64, capacity : usize) -> usize)(usize(hash >> u64(7)) % capacity);
38
26
  /// High-performance hash set using SwissTable algorithm.
39
27
  /// Elements must implement `Eq` and `Hash`. Provides O(1) average lookup and insert.
40
- HashSet :: (fn(
41
- comptime(T): Type,
42
- where(T <: (Eq(T), Hash))
43
- ) -> comptime(Type))
28
+ HashSet :: (
29
+ fn(
30
+ comptime(T) : Type,
31
+ where(T <: (Eq(T), Hash))
32
+ ) -> comptime(Type)
33
+ )(
44
34
  object(
45
35
  ctrl : ?*(u8),
46
36
  data : ?*(T),
47
37
  capacity : usize,
48
38
  size : usize
49
39
  )
50
- ;
51
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T),
40
+ );
41
+ impl(
42
+ forall(T : Type),
43
+ where(T <: (Eq(T), Hash)),
44
+ HashSet(T),
52
45
  /**
53
- * Allocate memory for HashSet with given capacity
54
- * Initializes all control bytes to EMPTY
55
- */
56
- _alloc_with_capacity : (fn(capacity: usize) -> Result(Self, HashSetError))(
57
- {
58
- element_size :: sizeof(T);
59
- ctrl_size := capacity;
60
- data_size := (capacity * element_size);
61
-
62
- ctrl_result := malloc(ctrl_size);
63
- match(ctrl_result,
64
- .None => .Err(.AllocError(error: .OutOfMemory)),
65
- .Some(ctrl_void_ptr) => {
66
- ctrl_ptr := *(u8)(ctrl_void_ptr);
67
-
68
- data_result := malloc(data_size);
69
- match(data_result,
70
- .None => {
71
- free(.Some(*(void)(ctrl_ptr)));
72
- .Err(.AllocError(error: .OutOfMemory))
73
- },
74
- .Some(data_void_ptr) => {
75
- data_ptr := *(T)(data_void_ptr);
76
-
77
- i := usize(0);
78
- while(i < capacity, i = (i + usize(1)), {
79
- (ctrl_ptr &+ i).* = CTRL_EMPTY;
80
- });
81
-
82
- .Ok(Self(
83
- ctrl: .Some(ctrl_ptr),
84
- data: .Some(data_ptr),
85
- capacity: capacity,
86
- size: usize(0)
87
- ))
88
- }
89
- )
90
- }
91
- )
92
- }
93
- ),
94
-
46
+ * Allocate memory for HashSet with given capacity
47
+ * Initializes all control bytes to EMPTY
48
+ */
49
+ _alloc_with_capacity : (fn(capacity : usize) -> Result(Self, HashSetError))({
50
+ element_size :: sizeof(T);
51
+ ctrl_size := capacity;
52
+ data_size := (capacity * element_size);
53
+ ctrl_result := malloc(ctrl_size);
54
+ match(
55
+ ctrl_result,
56
+ .None =>.Err(.AllocError(error :.OutOfMemory)),
57
+ .Some(ctrl_void_ptr) => {
58
+ ctrl_ptr := *(u8)(ctrl_void_ptr);
59
+ data_result := malloc(data_size);
60
+ match(
61
+ data_result,
62
+ .None => {
63
+ free(.Some(*(void)(ctrl_ptr)));
64
+ .Err(.AllocError(error :.OutOfMemory))
65
+ },
66
+ .Some(data_void_ptr) => {
67
+ data_ptr := *(T)(data_void_ptr);
68
+ i := usize(0);
69
+ while(i < capacity, i = (i + usize(1)), {
70
+ (ctrl_ptr &+ i).* = CTRL_EMPTY;
71
+ });
72
+ .Ok(
73
+ Self(
74
+ ctrl :.Some(ctrl_ptr),
75
+ data :.Some(data_ptr),
76
+ capacity : capacity,
77
+ size : usize(0)
78
+ )
79
+ )
80
+ }
81
+ )
82
+ }
83
+ )
84
+ }),
95
85
  /**
96
- * Create a new empty HashSet with default capacity
97
- */
98
- new : (fn() -> Self)(
99
- {
100
- result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
101
- match(result,
102
- .Ok(set) => set,
103
- .Err(_) => panic("Failed to allocate HashSet")
104
- )
105
- }
106
- ),
107
-
86
+ * Create a new empty HashSet with default capacity
87
+ */
88
+ new : (fn() -> Self)({
89
+ result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
90
+ match(
91
+ result,
92
+ .Ok(set) => set,
93
+ .Err(_) => panic("Failed to allocate HashSet")
94
+ )
95
+ }),
108
96
  /**
109
- * Create a HashSet with a specific initial capacity
110
- * Capacity will be rounded up to next power of 2
111
- */
112
- with_capacity : (fn(requested_capacity: usize) -> Self)(
113
- {
114
- capacity := cond(
115
- (requested_capacity < DEFAULT_CAPACITY) => DEFAULT_CAPACITY,
116
- true => {
117
- c := requested_capacity;
118
- c = (c - usize(1));
119
- c = (c | (c >> usize(1)));
120
- c = (c | (c >> usize(2)));
121
- c = (c | (c >> usize(4)));
122
- c = (c | (c >> usize(8)));
123
- c = (c | (c >> usize(16)));
124
- (c + usize(1))
125
- }
126
- );
127
-
128
- result := Self._alloc_with_capacity(capacity);
129
- match(result,
130
- .Ok(set) => set,
131
- .Err(_) => panic("Failed to allocate HashSet")
132
- )
133
- }
134
- ),
135
-
97
+ * Create a HashSet with a specific initial capacity
98
+ * Capacity will be rounded up to next power of 2
99
+ */
100
+ with_capacity : (fn(requested_capacity : usize) -> Self)({
101
+ capacity := cond(
102
+ (requested_capacity < DEFAULT_CAPACITY) => DEFAULT_CAPACITY,
103
+ true => {
104
+ c := requested_capacity;
105
+ c = (c - usize(1));
106
+ c = (c | (c >> usize(1)));
107
+ c = (c | (c >> usize(2)));
108
+ c = (c | (c >> usize(4)));
109
+ c = (c | (c >> usize(8)));
110
+ c = (c | (c >> usize(16)));
111
+ c + usize(1)
112
+ }
113
+ );
114
+ result := Self._alloc_with_capacity(capacity);
115
+ match(
116
+ result,
117
+ .Ok(set) => set,
118
+ .Err(_) => panic("Failed to allocate HashSet")
119
+ )
120
+ }),
136
121
  /**
137
- * Get ctrl pointer (unwrapped for internal use)
138
- */
139
- _ctrl_ptr : (fn(self: Self) -> *(u8))(
140
- match(self.ctrl,
122
+ * Get ctrl pointer (unwrapped for internal use)
123
+ */
124
+ _ctrl_ptr : (fn(self : Self) -> *(u8))(
125
+ match(
126
+ self.ctrl,
141
127
  .Some(ptr) => ptr,
142
128
  .None => panic("HashSet ctrl pointer is null")
143
129
  )
144
130
  ),
145
-
146
131
  /**
147
- * Get data pointer (unwrapped for internal use)
148
- */
149
- _data_ptr : (fn(self: Self) -> *(T))(
150
- match(self.data,
132
+ * Get data pointer (unwrapped for internal use)
133
+ */
134
+ _data_ptr : (fn(self : Self) -> *(T))(
135
+ match(
136
+ self.data,
151
137
  .Some(ptr) => ptr,
152
138
  .None => panic("HashSet data pointer is null")
153
139
  )
154
140
  ),
155
-
156
141
  /**
157
- * Find slot index for a given element using quadratic probing
158
- * Returns Some(index) if element is found, None otherwise
159
- */
160
- _find_slot : (fn(self: Self, element: T, hash: u64) -> Option(usize))(
161
- {
162
- h2 := h2_hash(hash);
163
- index := h1_hash(hash, self.capacity);
164
- probe := usize(0);
165
- ctrl_ptr := Self._ctrl_ptr(self);
166
- data_ptr := Self._data_ptr(self);
167
-
168
- while(probe < self.capacity, probe = (probe + usize(1)), {
169
- probe_index := ((index + probe) % self.capacity);
170
- ctrl_byte := (ctrl_ptr &+ probe_index).*;
171
-
142
+ * Find slot index for a given element using quadratic probing
143
+ * Returns Some(index) if element is found, None otherwise
144
+ */
145
+ _find_slot : (fn(self : Self, element : T, hash : u64) -> Option(usize))({
146
+ h2 := h2_hash(hash);
147
+ index := h1_hash(hash, self.capacity);
148
+ probe := usize(0);
149
+ ctrl_ptr := Self._ctrl_ptr(self);
150
+ data_ptr := Self._data_ptr(self);
151
+ while(probe < self.capacity, probe = (probe + usize(1)), {
152
+ probe_index := ((index + probe) % self.capacity);
153
+ ctrl_byte := (ctrl_ptr &+ probe_index).*;
154
+ cond(
155
+ (ctrl_byte == CTRL_EMPTY) => {
156
+ return(.None);
157
+ },
158
+ (ctrl_byte == h2) => {
159
+ stored_element := (data_ptr &+ probe_index).*;
160
+ cond(
161
+ (stored_element == element) => {
162
+ return(.Some(probe_index));
163
+ },
164
+ true => ()
165
+ );
166
+ },
167
+ true => ()
168
+ );
169
+ });
170
+ .None
171
+ }),
172
+ /**
173
+ * Find first available slot (EMPTY or DELETED) for insertion
174
+ * Returns slot index using quadratic probing
175
+ */
176
+ _find_insert_slot : (fn(self : Self, hash : u64) -> usize)({
177
+ index := h1_hash(hash, self.capacity);
178
+ probe := usize(0);
179
+ ctrl_ptr := Self._ctrl_ptr(self);
180
+ while(probe < self.capacity, probe = (probe + usize(1)), {
181
+ probe_index := ((index + probe) % self.capacity);
182
+ ctrl_byte := (ctrl_ptr &+ probe_index).*;
183
+ cond(
184
+ ((ctrl_byte == CTRL_EMPTY) || (ctrl_byte == CTRL_DELETED)) => {
185
+ return(probe_index);
186
+ },
187
+ true => ()
188
+ );
189
+ });
190
+ panic("HashSet is full - should have resized")
191
+ }),
192
+ /**
193
+ * Check if HashSet needs resizing based on load factor
194
+ */
195
+ _needs_resize : (fn(self : Self) -> bool)({
196
+ threshold := ((self.capacity * MAX_LOAD_FACTOR_NUMERATOR) / MAX_LOAD_FACTOR_DENOMINATOR);
197
+ self.size >= threshold
198
+ }),
199
+ /**
200
+ * Resize and rehash the HashSet to a new capacity
201
+ */
202
+ _resize : (fn(self : Self, new_capacity : usize) -> Result(unit, HashSetError))({
203
+ result := Self._alloc_with_capacity(new_capacity);
204
+ match(
205
+ result,
206
+ .Err(err) =>.Err(err),
207
+ .Ok(new_set) => {
208
+ i := usize(0);
209
+ ctrl_ptr := Self._ctrl_ptr(self);
210
+ data_ptr := Self._data_ptr(self);
211
+ while(i < self.capacity, i = (i + usize(1)), {
212
+ ctrl_byte := (ctrl_ptr &+ i).*;
213
+ cond(
214
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
215
+ element := (data_ptr &+ i).*;
216
+ hash := element.hash();
217
+ h2 := h2_hash(hash);
218
+ new_index := Self._find_insert_slot(new_set, hash);
219
+ new_ctrl_ptr := Self._ctrl_ptr(new_set);
220
+ new_data_ptr := Self._data_ptr(new_set);
221
+ (new_ctrl_ptr &+ new_index).* = h2;
222
+ consume((new_data_ptr &+ new_index).* = element);
223
+ new_set.size = (new_set.size + usize(1));
224
+ },
225
+ true => ()
226
+ );
227
+ });
228
+ // Drop old elements before freeing old data array
229
+ // (element := ... above duped them, so we need to drop the old refs)
172
230
  cond(
173
- (ctrl_byte == CTRL_EMPTY) => {
174
- return .None;
175
- },
176
- (ctrl_byte == h2) => {
177
- stored_element := (data_ptr &+ probe_index).*;
178
- cond(
179
- (stored_element == element) => {
180
- return .Some(probe_index);
181
- },
182
- true => ()
183
- );
231
+ Type.contains_rc_type(T) => {
232
+ j := usize(0);
233
+ while(j < self.capacity, j = (j + usize(1)), {
234
+ ctrl_byte := (ctrl_ptr &+ j).*;
235
+ cond(
236
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
237
+ element_ptr := (data_ptr &+ j);
238
+ unsafe.drop(element_ptr.*);
239
+ },
240
+ true => ()
241
+ );
242
+ });
184
243
  },
185
244
  true => ()
186
245
  );
187
- });
188
-
189
- .None
190
- }
191
- ),
192
-
246
+ match(
247
+ self.ctrl,
248
+ .Some(ptr) => free(.Some(*(void)(ptr))),
249
+ .None => ()
250
+ );
251
+ match(
252
+ self.data,
253
+ .Some(ptr) => free(.Some(*(void)(ptr))),
254
+ .None => ()
255
+ );
256
+ self.ctrl = new_set.ctrl;
257
+ self.data = new_set.data;
258
+ self.capacity = new_set.capacity;
259
+ new_set.ctrl =.None;
260
+ new_set.data =.None;
261
+ .Ok(())
262
+ }
263
+ )
264
+ }),
193
265
  /**
194
- * Find first available slot (EMPTY or DELETED) for insertion
195
- * Returns slot index using quadratic probing
196
- */
197
- _find_insert_slot : (fn(self: Self, hash: u64) -> usize)(
198
- {
199
- index := h1_hash(hash, self.capacity);
200
- probe := usize(0);
201
- ctrl_ptr := Self._ctrl_ptr(self);
202
-
203
- while(probe < self.capacity, probe = (probe + usize(1)), {
204
- probe_index := ((index + probe) % self.capacity);
205
- ctrl_byte := (ctrl_ptr &+ probe_index).*;
206
-
207
- cond(
208
- ((ctrl_byte == CTRL_EMPTY) || (ctrl_byte == CTRL_DELETED)) => {
209
- return probe_index;
266
+ * Insert an element into the set
267
+ * Returns Ok(true) if element was newly inserted, Ok(false) if already present
268
+ */
269
+ add : (fn(self : Self, element : T) -> Result(bool, HashSetError))({
270
+ hash := element.hash();
271
+ slot_opt := Self._find_slot(self, element, hash);
272
+ match(
273
+ slot_opt,
274
+ .Some(_) =>.Ok(false),
275
+ .None => {
276
+ resize_check := cond(
277
+ (Self._needs_resize(self)) => {
278
+ new_capacity := (self.capacity * usize(2));
279
+ Self._resize(self, new_capacity)
210
280
  },
211
- true => ()
281
+ true => Result(unit, HashSetError).Ok(())
212
282
  );
213
- });
214
-
215
- panic("HashSet is full - should have resized")
216
- }
217
- ),
218
-
283
+ match(
284
+ resize_check,
285
+ .Err(err) =>.Err(err),
286
+ .Ok(_) => {
287
+ h2 := h2_hash(hash);
288
+ index := Self._find_insert_slot(self, hash);
289
+ ctrl_ptr := Self._ctrl_ptr(self);
290
+ data_ptr := Self._data_ptr(self);
291
+ (ctrl_ptr &+ index).* = h2;
292
+ consume((data_ptr &+ index).* = element);
293
+ self.size = (self.size + usize(1));
294
+ .Ok(true)
295
+ }
296
+ )
297
+ }
298
+ )
299
+ }),
219
300
  /**
220
- * Check if HashSet needs resizing based on load factor
221
- */
222
- _needs_resize : (fn(self: Self) -> bool)(
223
- {
224
- threshold := ((self.capacity * MAX_LOAD_FACTOR_NUMERATOR) / MAX_LOAD_FACTOR_DENOMINATOR);
225
- (self.size >= threshold)
226
- }
227
- ),
228
-
301
+ * Check if an element exists in the set
302
+ */
303
+ contains : (fn(self : Self, element : T) -> bool)({
304
+ hash := element.hash();
305
+ slot_opt := Self._find_slot(self, element, hash);
306
+ match(
307
+ slot_opt,
308
+ .Some(_) => true,
309
+ .None => false
310
+ )
311
+ }),
229
312
  /**
230
- * Resize and rehash the HashSet to a new capacity
231
- */
232
- _resize : (fn(self: Self, new_capacity: usize) -> Result(unit, HashSetError))(
233
- {
234
- result := Self._alloc_with_capacity(new_capacity);
235
- match(result,
236
- .Err(err) => .Err(err),
237
- .Ok(new_set) => {
238
- i := usize(0);
239
- ctrl_ptr := Self._ctrl_ptr(self);
240
- data_ptr := Self._data_ptr(self);
241
- while(i < self.capacity, i = (i + usize(1)), {
242
- ctrl_byte := (ctrl_ptr &+ i).*;
243
- cond(
244
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
245
- element := (data_ptr &+ i).*;
246
- hash := element.hash();
247
- h2 := h2_hash(hash);
248
- new_index := Self._find_insert_slot(new_set, hash);
249
-
250
- new_ctrl_ptr := Self._ctrl_ptr(new_set);
251
- new_data_ptr := Self._data_ptr(new_set);
252
- (new_ctrl_ptr &+ new_index).* = h2;
253
- consume((new_data_ptr &+ new_index).* = element);
254
- new_set.size = (new_set.size + usize(1));
255
- },
256
- true => ()
257
- );
258
- });
259
-
260
- // Drop old elements before freeing old data array
261
- // (element := ... above duped them, so we need to drop the old refs)
262
- cond(
263
- Type.contains_rc_type(T) => {
264
- j := usize(0);
265
- while(j < self.capacity, j = (j + usize(1)), {
266
- ctrl_byte := (ctrl_ptr &+ j).*;
267
- cond(
268
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
269
- element_ptr := (data_ptr &+ j);
270
- unsafe.drop(element_ptr.*);
271
- },
272
- true => ()
273
- );
274
- });
275
- },
276
- true => ()
277
- );
278
-
279
- match(self.ctrl,
280
- .Some(ptr) => free(.Some(*(void) ptr)),
281
- .None => ()
282
- );
283
- match(self.data,
284
- .Some(ptr) => free(.Some(*(void) ptr)),
285
- .None => ()
286
- );
287
-
288
- self.ctrl = new_set.ctrl;
289
- self.data = new_set.data;
290
- self.capacity = new_set.capacity;
291
-
292
- new_set.ctrl = .None;
293
- new_set.data = .None;
294
-
295
- .Ok(())
296
- }
297
- )
298
- }
299
- ),
300
-
313
+ * Remove an element from the set
314
+ * Returns true if the element was present and removed, false otherwise
315
+ */
316
+ remove : (fn(self : Self, element : T) -> bool)({
317
+ hash := element.hash();
318
+ slot_opt := Self._find_slot(self, element, hash);
319
+ match(
320
+ slot_opt,
321
+ .Some(index) => {
322
+ // Drop the element value before marking as deleted
323
+ cond(
324
+ Type.contains_rc_type(T) => {
325
+ data_ptr := Self._data_ptr(self);
326
+ element_ptr := (data_ptr &+ index);
327
+ unsafe.drop(element_ptr.*);
328
+ },
329
+ true => ()
330
+ );
331
+ ctrl_ptr := Self._ctrl_ptr(self);
332
+ (ctrl_ptr &+ index).* = CTRL_DELETED;
333
+ self.size = (self.size - usize(1));
334
+ true
335
+ },
336
+ .None => false
337
+ )
338
+ }),
301
339
  /**
302
- * Insert an element into the set
303
- * Returns Ok(true) if element was newly inserted, Ok(false) if already present
304
- */
305
- add : (fn(self: Self, element: T) -> Result(bool, HashSetError))(
306
- {
307
- hash := element.hash();
308
- slot_opt := Self._find_slot(self, element, hash);
309
-
310
- match(slot_opt,
311
- .Some(_) => .Ok(false),
312
- .None => {
313
- resize_check := cond(
314
- (Self._needs_resize(self)) => {
315
- new_capacity := (self.capacity * usize(2));
316
- Self._resize(self, new_capacity)
317
- },
318
- true => (Result(unit, HashSetError).Ok(()))
319
- );
320
-
321
- match(resize_check,
322
- .Err(err) => .Err(err),
323
- .Ok(_) => {
324
- h2 := h2_hash(hash);
325
- index := Self._find_insert_slot(self, hash);
326
-
327
- ctrl_ptr := Self._ctrl_ptr(self);
328
- data_ptr := Self._data_ptr(self);
329
- (ctrl_ptr &+ index).* = h2;
330
- consume((data_ptr &+ index).* = element);
331
- self.size = (self.size + usize(1));
332
-
333
- .Ok(true)
334
- }
335
- )
336
- }
337
- )
338
- }
340
+ * Get the number of elements in the set
341
+ */
342
+ len : (fn(self : Self) -> usize)(
343
+ self.size
339
344
  ),
340
-
341
345
  /**
342
- * Check if an element exists in the set
343
- */
344
- contains : (fn(self: Self, element: T) -> bool)(
345
- {
346
- hash := element.hash();
347
- slot_opt := Self._find_slot(self, element, hash);
348
- match(slot_opt,
349
- .Some(_) => true,
350
- .None => false
351
- )
352
- }
346
+ * Check if the set is empty
347
+ */
348
+ is_empty : (fn(self : Self) -> bool)(
349
+ self.size == usize(0)
353
350
  ),
354
-
355
351
  /**
356
- * Remove an element from the set
357
- * Returns true if the element was present and removed, false otherwise
358
- */
359
- remove : (fn(self: Self, element: T) -> bool)(
360
- {
361
- hash := element.hash();
362
- slot_opt := Self._find_slot(self, element, hash);
363
- match(slot_opt,
364
- .Some(index) => {
365
- // Drop the element value before marking as deleted
352
+ * Clear all elements from the set
353
+ * Resets all control bytes to EMPTY
354
+ */
355
+ clear : (fn(self : Self) -> unit)({
356
+ // Drop all occupied elements before clearing
357
+ cond(
358
+ Type.contains_rc_type(T) => {
359
+ ctrl_ptr := Self._ctrl_ptr(self);
360
+ data_ptr := Self._data_ptr(self);
361
+ i := usize(0);
362
+ while(i < self.capacity, i = (i + usize(1)), {
363
+ ctrl_byte := (ctrl_ptr &+ i).*;
366
364
  cond(
367
- Type.contains_rc_type(T) => {
368
- data_ptr := Self._data_ptr(self);
369
- element_ptr := (data_ptr &+ index);
365
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
366
+ element_ptr := (data_ptr &+ i);
370
367
  unsafe.drop(element_ptr.*);
371
368
  },
372
369
  true => ()
373
370
  );
374
-
375
- ctrl_ptr := Self._ctrl_ptr(self);
376
- (ctrl_ptr &+ index).* = CTRL_DELETED;
377
- self.size = (self.size - usize(1));
378
- true
379
- },
380
- .None => false
381
- )
382
- }
383
- ),
384
-
385
- /**
386
- * Get the number of elements in the set
387
- */
388
- len : (fn(self: Self) -> usize)(
389
- self.size
390
- ),
391
-
392
- /**
393
- * Check if the set is empty
394
- */
395
- is_empty : (fn(self: Self) -> bool)(
396
- (self.size == usize(0))
397
- ),
398
-
399
- /**
400
- * Clear all elements from the set
401
- * Resets all control bytes to EMPTY
402
- */
403
- clear : (fn(self: Self) -> unit)(
404
- {
405
- // Drop all occupied elements before clearing
406
- cond(
407
- Type.contains_rc_type(T) => {
408
- ctrl_ptr := Self._ctrl_ptr(self);
409
- data_ptr := Self._data_ptr(self);
410
- i := usize(0);
411
- while(i < self.capacity, i = (i + usize(1)), {
412
- ctrl_byte := (ctrl_ptr &+ i).*;
413
- cond(
414
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
415
- element_ptr := (data_ptr &+ i);
416
- unsafe.drop(element_ptr.*);
417
- },
418
- true => ()
419
- );
420
- });
421
- },
422
- true => ()
423
- );
424
-
425
- ctrl_ptr := Self._ctrl_ptr(self);
426
- i := usize(0);
427
- while(i < self.capacity, i = (i + usize(1)), {
428
- (ctrl_ptr &+ i).* = CTRL_EMPTY;
429
- });
430
- self.size = usize(0);
431
- }
432
- ),
433
-
371
+ });
372
+ },
373
+ true => ()
374
+ );
375
+ ctrl_ptr := Self._ctrl_ptr(self);
376
+ i := usize(0);
377
+ while(i < self.capacity, i = (i + usize(1)), {
378
+ (ctrl_ptr &+ i).* = CTRL_EMPTY;
379
+ });
380
+ self.size = usize(0);
381
+ }),
434
382
  /**
435
- * Check if this set is a subset of another set
436
- * Returns true if all elements in self are also in other
437
- */
438
- is_subset : (fn(self: Self, other: Self) -> bool)(
383
+ * Check if this set is a subset of another set
384
+ * Returns true if all elements in self are also in other
385
+ */
386
+ is_subset : (fn(self : Self, other : Self) -> bool)(
439
387
  cond(
440
388
  (self.size > other.size) => false,
441
389
  true => {
@@ -443,7 +391,6 @@ impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T),
443
391
  ctrl_ptr := Self._ctrl_ptr(self);
444
392
  data_ptr := Self._data_ptr(self);
445
393
  is_sub := true;
446
-
447
394
  while(i < self.capacity, i = (i + usize(1)), {
448
395
  ctrl_byte := (ctrl_ptr &+ i).*;
449
396
  cond(
@@ -460,257 +407,237 @@ impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T),
460
407
  true => ()
461
408
  );
462
409
  });
463
-
464
410
  is_sub
465
411
  }
466
412
  )
467
413
  ),
468
-
469
414
  /**
470
- * Check if this set is a superset of another set
471
- * Returns true if all elements in other are also in self
472
- */
473
- is_superset : (fn(self: Self, other: Self) -> bool)(
415
+ * Check if this set is a superset of another set
416
+ * Returns true if all elements in other are also in self
417
+ */
418
+ is_superset : (fn(self : Self, other : Self) -> bool)(
474
419
  other.is_subset(self)
475
420
  ),
476
-
477
421
  /**
478
- * Check if this set is disjoint from another set
479
- * Returns true if the sets have no elements in common
480
- */
481
- is_disjoint : (fn(self: Self, other: Self) -> bool)(
482
- {
483
- smaller := cond((self.size <= other.size) => self, true => other);
484
- larger := cond((self.size <= other.size) => other, true => self);
485
-
486
- i := usize(0);
487
- ctrl_ptr := Self._ctrl_ptr(smaller);
488
- data_ptr := Self._data_ptr(smaller);
489
- result := true;
490
-
491
- while(i < smaller.capacity, i = (i + usize(1)), {
492
- ctrl_byte := (ctrl_ptr &+ i).*;
493
- cond(
494
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
495
- element := (data_ptr &+ i).*;
496
- contains_result := larger.contains(element);
497
- cond(
498
- (contains_result == true) => {
499
- result = false;
500
- },
501
- true => ()
502
- );
503
- },
504
- true => ()
505
- );
506
- });
507
-
508
- result
509
- }
510
- ),
511
-
512
- /**
513
- * Create a new set containing the union of two sets
514
- * Returns a new HashSet containing all elements from both sets
515
- */
516
- union : (fn(self: Self, other: Self) -> Result(Self, HashSetError))(
517
- {
518
- new_capacity := cond(
519
- ((self.size + other.size) > DEFAULT_CAPACITY) => {
520
- combined := (self.size + other.size);
521
- c := combined;
522
- c = (c - usize(1));
523
- c = (c | (c >> usize(1)));
524
- c = (c | (c >> usize(2)));
525
- c = (c | (c >> usize(4)));
526
- c = (c | (c >> usize(8)));
527
- c = (c | (c >> usize(16)));
528
- (c + usize(1))
422
+ * Check if this set is disjoint from another set
423
+ * Returns true if the sets have no elements in common
424
+ */
425
+ is_disjoint : (fn(self : Self, other : Self) -> bool)({
426
+ smaller := cond((self.size <= other.size) => self, true => other);
427
+ larger := cond((self.size <= other.size) => other, true => self);
428
+ i := usize(0);
429
+ ctrl_ptr := Self._ctrl_ptr(smaller);
430
+ data_ptr := Self._data_ptr(smaller);
431
+ result := true;
432
+ while(i < smaller.capacity, i = (i + usize(1)), {
433
+ ctrl_byte := (ctrl_ptr &+ i).*;
434
+ cond(
435
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
436
+ element := (data_ptr &+ i).*;
437
+ contains_result := larger.contains(element);
438
+ cond(
439
+ (contains_result == true) => {
440
+ result = false;
441
+ },
442
+ true => ()
443
+ );
529
444
  },
530
- true => DEFAULT_CAPACITY
445
+ true => ()
531
446
  );
532
-
533
- result_set_result := Self._alloc_with_capacity(new_capacity);
534
- match(result_set_result,
535
- .Err(err) => .Err(err),
536
- .Ok(result_set) => {
537
- i := usize(0);
538
- ctrl_ptr := Self._ctrl_ptr(self);
539
- data_ptr := Self._data_ptr(self);
540
- while(i < self.capacity, i = (i + usize(1)), {
541
- ctrl_byte := (ctrl_ptr &+ i).*;
542
- cond(
543
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
544
- element := (data_ptr &+ i).*;
545
- result_set.add(element);
546
- },
547
- true => ()
548
- );
549
- });
550
-
551
- j := usize(0);
552
- other_ctrl_ptr := Self._ctrl_ptr(other);
553
- other_data_ptr := Self._data_ptr(other);
554
- while(j < other.capacity, j = (j + usize(1)), {
555
- ctrl_byte := (other_ctrl_ptr &+ j).*;
556
- cond(
557
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
558
- element := (other_data_ptr &+ j).*;
559
- result_set.add(element);
560
- },
561
- true => ()
562
- );
563
- });
564
-
565
- .Ok(result_set)
566
- }
567
- )
568
- }
569
- ),
570
-
447
+ });
448
+ result
449
+ }),
571
450
  /**
572
- * Create a new set containing the intersection of two sets
573
- * Returns a new HashSet containing only elements present in both sets
574
- */
575
- intersection : (fn(self: Self, other: Self) -> Result(Self, HashSetError))(
576
- {
577
- smaller := cond((self.size <= other.size) => self, true => other);
578
- larger := cond((self.size <= other.size) => other, true => self);
579
-
580
- result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
581
- match(result_set_result,
582
- .Err(err) => .Err(err),
583
- .Ok(result_set) => {
584
- i := usize(0);
585
- ctrl_ptr := Self._ctrl_ptr(smaller);
586
- data_ptr := Self._data_ptr(smaller);
587
- while(i < smaller.capacity, i = (i + usize(1)), {
588
- ctrl_byte := (ctrl_ptr &+ i).*;
589
- cond(
590
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
591
- element := (data_ptr &+ i).*;
592
- cond(
593
- (larger.contains(element)) => {
594
- _ := result_set.add(element);
595
- },
596
- true => ()
597
- );
598
- },
599
- true => ()
600
- );
601
- });
602
-
603
- .Ok(result_set)
604
- }
605
- )
606
- }
607
- ),
608
-
451
+ * Create a new set containing the union of two sets
452
+ * Returns a new HashSet containing all elements from both sets
453
+ */
454
+ union : (fn(self : Self, other : Self) -> Result(Self, HashSetError))({
455
+ new_capacity := cond(
456
+ ((self.size + other.size) > DEFAULT_CAPACITY) => {
457
+ combined := (self.size + other.size);
458
+ c := combined;
459
+ c = (c - usize(1));
460
+ c = (c | (c >> usize(1)));
461
+ c = (c | (c >> usize(2)));
462
+ c = (c | (c >> usize(4)));
463
+ c = (c | (c >> usize(8)));
464
+ c = (c | (c >> usize(16)));
465
+ c + usize(1)
466
+ },
467
+ true => DEFAULT_CAPACITY
468
+ );
469
+ result_set_result := Self._alloc_with_capacity(new_capacity);
470
+ match(
471
+ result_set_result,
472
+ .Err(err) =>.Err(err),
473
+ .Ok(result_set) => {
474
+ i := usize(0);
475
+ ctrl_ptr := Self._ctrl_ptr(self);
476
+ data_ptr := Self._data_ptr(self);
477
+ while(i < self.capacity, i = (i + usize(1)), {
478
+ ctrl_byte := (ctrl_ptr &+ i).*;
479
+ cond(
480
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
481
+ element := (data_ptr &+ i).*;
482
+ result_set.add(element);
483
+ },
484
+ true => ()
485
+ );
486
+ });
487
+ j := usize(0);
488
+ other_ctrl_ptr := Self._ctrl_ptr(other);
489
+ other_data_ptr := Self._data_ptr(other);
490
+ while(j < other.capacity, j = (j + usize(1)), {
491
+ ctrl_byte := (other_ctrl_ptr &+ j).*;
492
+ cond(
493
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
494
+ element := (other_data_ptr &+ j).*;
495
+ result_set.add(element);
496
+ },
497
+ true => ()
498
+ );
499
+ });
500
+ .Ok(result_set)
501
+ }
502
+ )
503
+ }),
609
504
  /**
610
- * Create a new set containing the difference of two sets
611
- * Returns a new HashSet containing elements in self but not in other
612
- */
613
- difference : (fn(self: Self, other: Self) -> Result(Self, HashSetError))(
614
- {
615
- result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
616
- match(result_set_result,
617
- .Err(err) => .Err(err),
618
- .Ok(result_set) => {
619
- i := usize(0);
620
- ctrl_ptr := Self._ctrl_ptr(self);
621
- data_ptr := Self._data_ptr(self);
622
- while(i < self.capacity, i = (i + usize(1)), {
623
- ctrl_byte := (ctrl_ptr &+ i).*;
624
- cond(
625
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
626
- element := (data_ptr &+ i).*;
627
- contains_result := other.contains(element);
628
- cond(
629
- (contains_result == false) => {
630
- _ := result_set.add(element);
631
- },
632
- true => ()
633
- );
634
- },
635
- true => ()
636
- );
637
- });
638
-
639
- .Ok(result_set)
640
- }
641
- )
642
- }
643
- ),
644
-
505
+ * Create a new set containing the intersection of two sets
506
+ * Returns a new HashSet containing only elements present in both sets
507
+ */
508
+ intersection : (fn(self : Self, other : Self) -> Result(Self, HashSetError))({
509
+ smaller := cond((self.size <= other.size) => self, true => other);
510
+ larger := cond((self.size <= other.size) => other, true => self);
511
+ result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
512
+ match(
513
+ result_set_result,
514
+ .Err(err) =>.Err(err),
515
+ .Ok(result_set) => {
516
+ i := usize(0);
517
+ ctrl_ptr := Self._ctrl_ptr(smaller);
518
+ data_ptr := Self._data_ptr(smaller);
519
+ while(i < smaller.capacity, i = (i + usize(1)), {
520
+ ctrl_byte := (ctrl_ptr &+ i).*;
521
+ cond(
522
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
523
+ element := (data_ptr &+ i).*;
524
+ cond(
525
+ (larger.contains(element)) => {
526
+ _ := result_set.add(element);
527
+ },
528
+ true => ()
529
+ );
530
+ },
531
+ true => ()
532
+ );
533
+ });
534
+ .Ok(result_set)
535
+ }
536
+ )
537
+ }),
645
538
  /**
646
- * Create a new set containing the symmetric difference of two sets
647
- * Returns a new HashSet containing elements in either set but not in both
648
- */
649
- symmetric_difference : (fn(self: Self, other: Self) -> Result(Self, HashSetError))(
650
- {
651
- result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
652
- match(result_set_result,
653
- .Err(err) => .Err(err),
654
- .Ok(result_set) => {
655
- i := usize(0);
656
- ctrl_ptr := Self._ctrl_ptr(self);
657
- data_ptr := Self._data_ptr(self);
658
- while(i < self.capacity, i = (i + usize(1)), {
659
- ctrl_byte := (ctrl_ptr &+ i).*;
660
- cond(
661
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
662
- element := (data_ptr &+ i).*;
663
- contains_result := other.contains(element);
664
- cond(
665
- (contains_result == false) => {
666
- _ := result_set.add(element);
667
- },
668
- true => ()
669
- );
670
- },
671
- true => ()
672
- );
673
- });
674
-
675
- j := usize(0);
676
- other_ctrl_ptr := Self._ctrl_ptr(other);
677
- other_data_ptr := Self._data_ptr(other);
678
- while(j < other.capacity, j = (j + usize(1)), {
679
- ctrl_byte := (other_ctrl_ptr &+ j).*;
680
- cond(
681
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
682
- element := (other_data_ptr &+ j).*;
683
- contains_result := self.contains(element);
684
- cond(
685
- (contains_result == false) => {
686
- _ := result_set.add(element);
687
- },
688
- true => ()
689
- );
690
- },
691
- true => ()
692
- );
693
- });
694
-
695
- .Ok(result_set)
696
- }
697
- )
698
- }
699
- )
700
- );
701
-
702
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T), Dispose(
539
+ * Create a new set containing the difference of two sets
540
+ * Returns a new HashSet containing elements in self but not in other
541
+ */
542
+ difference : (fn(self : Self, other : Self) -> Result(Self, HashSetError))({
543
+ result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
544
+ match(
545
+ result_set_result,
546
+ .Err(err) =>.Err(err),
547
+ .Ok(result_set) => {
548
+ i := usize(0);
549
+ ctrl_ptr := Self._ctrl_ptr(self);
550
+ data_ptr := Self._data_ptr(self);
551
+ while(i < self.capacity, i = (i + usize(1)), {
552
+ ctrl_byte := (ctrl_ptr &+ i).*;
553
+ cond(
554
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
555
+ element := (data_ptr &+ i).*;
556
+ contains_result := other.contains(element);
557
+ cond(
558
+ (contains_result == false) => {
559
+ _ := result_set.add(element);
560
+ },
561
+ true => ()
562
+ );
563
+ },
564
+ true => ()
565
+ );
566
+ });
567
+ .Ok(result_set)
568
+ }
569
+ )
570
+ }),
703
571
  /**
572
+ * Create a new set containing the symmetric difference of two sets
573
+ * Returns a new HashSet containing elements in either set but not in both
574
+ */
575
+ symmetric_difference : (fn(self : Self, other : Self) -> Result(Self, HashSetError))({
576
+ result_set_result := Self._alloc_with_capacity(DEFAULT_CAPACITY);
577
+ match(
578
+ result_set_result,
579
+ .Err(err) =>.Err(err),
580
+ .Ok(result_set) => {
581
+ i := usize(0);
582
+ ctrl_ptr := Self._ctrl_ptr(self);
583
+ data_ptr := Self._data_ptr(self);
584
+ while(i < self.capacity, i = (i + usize(1)), {
585
+ ctrl_byte := (ctrl_ptr &+ i).*;
586
+ cond(
587
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
588
+ element := (data_ptr &+ i).*;
589
+ contains_result := other.contains(element);
590
+ cond(
591
+ (contains_result == false) => {
592
+ _ := result_set.add(element);
593
+ },
594
+ true => ()
595
+ );
596
+ },
597
+ true => ()
598
+ );
599
+ });
600
+ j := usize(0);
601
+ other_ctrl_ptr := Self._ctrl_ptr(other);
602
+ other_data_ptr := Self._data_ptr(other);
603
+ while(j < other.capacity, j = (j + usize(1)), {
604
+ ctrl_byte := (other_ctrl_ptr &+ j).*;
605
+ cond(
606
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
607
+ element := (other_data_ptr &+ j).*;
608
+ contains_result := self.contains(element);
609
+ cond(
610
+ (contains_result == false) => {
611
+ _ := result_set.add(element);
612
+ },
613
+ true => ()
614
+ );
615
+ },
616
+ true => ()
617
+ );
618
+ });
619
+ .Ok(result_set)
620
+ }
621
+ )
622
+ })
623
+ );
624
+ impl(
625
+ forall(T : Type),
626
+ where(T <: (Eq(T), Hash)),
627
+ HashSet(T),
628
+ Dispose(
629
+ /**
704
630
  * RAII destructor - automatically called when HashSet goes out of scope
705
631
  */
706
- dispose : (fn(self: Self) -> unit)(
707
- {
632
+ dispose : (fn(self : Self) -> unit)({
708
633
  // Drop all occupied elements before freeing memory
709
634
  cond(
710
635
  Type.contains_rc_type(T) => {
711
- match(self.ctrl,
636
+ match(
637
+ self.ctrl,
712
638
  .Some(ctrl_ptr) => {
713
- match(self.data,
639
+ match(
640
+ self.data,
714
641
  .Some(data_ptr) => {
715
642
  i := usize(0);
716
643
  while(i < self.capacity, i = (i + usize(1)), {
@@ -732,112 +659,120 @@ impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T), Dispose(
732
659
  },
733
660
  true => ()
734
661
  );
735
-
736
- match(self.ctrl,
737
- .Some(ptr) => free(.Some(*(void) ptr)),
662
+ match(
663
+ self.ctrl,
664
+ .Some(ptr) => free(.Some(*(void)(ptr))),
738
665
  .None => ()
739
666
  );
740
- match(self.data,
741
- .Some(ptr) => free(.Some(*(void) ptr)),
667
+ match(
668
+ self.data,
669
+ .Some(ptr) => free(.Some(*(void)(ptr))),
742
670
  .None => ()
743
671
  );
744
- }
672
+ })
745
673
  )
746
- ));
747
-
674
+ );
748
675
  /**
749
- * Value iterator for HashSet - yields elements by value (T)
750
- * Scans ctrl bytes to find occupied slots.
751
- */
676
+ * Value iterator for HashSet - yields elements by value (T)
677
+ * Scans ctrl bytes to find occupied slots.
678
+ */
752
679
  HashSetIter :: (fn(comptime(T) : Type) -> comptime(Type))(
753
680
  struct(
754
- _set : HashSet(T),
681
+ _set : HashSet(T),
755
682
  _index : usize
756
683
  )
757
684
  );
758
-
759
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSetIter(T), Iterator(
760
- Item : T,
761
- next : (fn(self : *(Self)) -> Option(T))(
762
- cond(
763
- (self._set.capacity == usize(0)) => .None,
764
- true => {
765
- ctrl_ptr := self._set.ctrl.unwrap();
766
- data_ptr := self._set.data.unwrap();
767
- result := Option(T).None;
768
- while ((self._index < self._set.capacity) && result.is_none()), (self._index = (self._index + usize(1))), {
769
- ctrl_byte := (ctrl_ptr &+ self._index).*;
770
- cond(
771
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
772
- result = .Some((data_ptr &+ self._index).*);
773
- },
774
- true => ()
775
- );
776
- };
777
- result
778
- }
685
+ impl(
686
+ forall(T : Type),
687
+ where(T <: (Eq(T), Hash)),
688
+ HashSetIter(T),
689
+ Iterator(
690
+ Item : T,
691
+ next : (fn(self : *(Self)) -> Option(T))(
692
+ cond(
693
+ (self._set.capacity == usize(0)) =>.None,
694
+ true => {
695
+ ctrl_ptr := self._set.ctrl.unwrap();
696
+ data_ptr := self._set.data.unwrap();
697
+ result := Option(T).None;
698
+ while((self._index < self._set.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
699
+ ctrl_byte := (ctrl_ptr &+ self._index).*;
700
+ cond(
701
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
702
+ result =.Some((data_ptr &+ self._index).*);
703
+ },
704
+ true => ()
705
+ );
706
+ });
707
+ result
708
+ }
709
+ )
779
710
  )
780
711
  )
781
- ));
782
-
783
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T),
712
+ );
713
+ impl(
714
+ forall(T : Type),
715
+ where(T <: (Eq(T), Hash)),
716
+ HashSet(T),
784
717
  into_iter : (fn(self : Self) -> HashSetIter(T))(
785
- HashSetIter(T)(_set: self, _index: usize(0))
718
+ HashSetIter(T)(_set : self, _index : usize(0))
786
719
  )
787
720
  );
788
-
789
721
  /**
790
- * Pointer iterator for HashSet - yields pointers to elements (*(T))
791
- * Pointers are valid as long as the set is not modified during iteration.
792
- */
722
+ * Pointer iterator for HashSet - yields pointers to elements (*(T))
723
+ * Pointers are valid as long as the set is not modified during iteration.
724
+ */
793
725
  HashSetIterPtr :: (fn(comptime(T) : Type) -> comptime(Type))(
794
726
  struct(
795
- _set : HashSet(T),
727
+ _set : HashSet(T),
796
728
  _index : usize
797
729
  )
798
730
  );
799
-
800
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSetIterPtr(T), Iterator(
801
- Item : *(T),
802
- next : (fn(self : *(Self)) -> Option(*(T)))(
803
- cond(
804
- (self._set.capacity == usize(0)) => .None,
805
- true => {
806
- ctrl_ptr := self._set.ctrl.unwrap();
807
- data_ptr := self._set.data.unwrap();
808
- result := Option(*(T)).None;
809
- while ((self._index < self._set.capacity) && result.is_none()), (self._index = (self._index + usize(1))), {
810
- ctrl_byte := (ctrl_ptr &+ self._index).*;
811
- cond(
812
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
813
- result = .Some((data_ptr &+ self._index));
814
- },
815
- true => ()
816
- );
817
- };
818
- result
819
- }
731
+ impl(
732
+ forall(T : Type),
733
+ where(T <: (Eq(T), Hash)),
734
+ HashSetIterPtr(T),
735
+ Iterator(
736
+ Item : *(T),
737
+ next : (fn(self : *(Self)) -> Option(*(T)))(
738
+ cond(
739
+ (self._set.capacity == usize(0)) =>.None,
740
+ true => {
741
+ ctrl_ptr := self._set.ctrl.unwrap();
742
+ data_ptr := self._set.data.unwrap();
743
+ result := Option(*(T)).None;
744
+ while((self._index < self._set.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
745
+ ctrl_byte := (ctrl_ptr &+ self._index).*;
746
+ cond(
747
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
748
+ result =.Some(data_ptr &+ self._index);
749
+ },
750
+ true => ()
751
+ );
752
+ });
753
+ result
754
+ }
755
+ )
820
756
  )
821
757
  )
822
- ));
823
-
824
- impl(forall(T : Type), where(T <: (Eq(T), Hash)), HashSet(T),
758
+ );
759
+ impl(
760
+ forall(T : Type),
761
+ where(T <: (Eq(T), Hash)),
762
+ HashSet(T),
825
763
  iter : (fn(self : *(Self)) -> HashSetIterPtr(T))(
826
- HashSetIterPtr(T)(_set: self.*, _index: usize(0))
764
+ HashSetIterPtr(T)(_set : self.*, _index : usize(0))
827
765
  )
828
766
  );
829
-
830
- export
767
+ export(
831
768
  HashSet,
832
769
  HashSetError,
833
770
  HashSetIter,
834
771
  HashSetIterPtr
835
- ;
836
-
772
+ );
837
773
  // =============================================================================
838
774
  // hash_set! literal macro
839
775
  // =============================================================================
840
-
841
776
  /// Internal helper: build a list of `tmp.add(elem).unwrap()` statements from `elems`.
842
777
  __hash_set_build_adds :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprList) -> comptime(ExprList))(
843
778
  cond(
@@ -845,12 +780,11 @@ __hash_set_build_adds :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprList) -
845
780
  true => {
846
781
  first :: elems.car();
847
782
  rest :: elems.cdr();
848
- stmt :: quote((unquote(tmp).add(unquote(first)).unwrap()));
783
+ stmt :: quote(unquote(tmp).add(unquote(first)).unwrap());
849
784
  stmt.cons(recur(tmp, rest))
850
785
  }
851
786
  )
852
787
  );
853
-
854
788
  /// `hash_set` macro — construct a `HashSet(T)` literal.
855
789
  ///
856
790
  /// `T` is inferred from the first element via `typeof`, so at least one
@@ -860,20 +794,22 @@ __hash_set_build_adds :: (fn(comptime(tmp) : Expr, comptime(elems) : ExprList) -
860
794
  /// ```rust
861
795
  /// s := hash_set(i32(1), i32(2), i32(3));
862
796
  /// ```
863
- hash_set :: (fn(...(quote(elems))) -> unquote(Expr)) {
864
- __ :: comptime_assert((elems.len() > usize(0)),
865
- "hash_set requires at least one element to infer the element type");
797
+ hash_set :: (fn(...(quote(elems))) -> unquote(Expr))({
798
+ __ :: comptime_assert(
799
+ elems.len() > usize(0),
800
+ "hash_set requires at least one element to infer the element type"
801
+ );
866
802
  first :: elems.car();
867
803
  rest :: elems.cdr();
868
804
  tmp :: gensym("hash_set");
869
805
  first_tmp :: gensym("hash_set_first");
870
806
  rest_adds :: __hash_set_build_adds(tmp, rest);
871
- quote {
807
+ quote({
872
808
  unquote(first_tmp) := unquote(first);
873
809
  unquote(tmp) := HashSet(typeof(unquote(first_tmp))).new();
874
810
  unquote(tmp).add(unquote(first_tmp)).unwrap();
875
811
  unquote_splicing(rest_adds);
876
812
  unquote(tmp)
877
- }
878
- };
879
- export hash_set;
813
+ })
814
+ });
815
+ export(hash_set);