@shd101wyy/yo 0.1.32 → 0.1.34

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 (48) hide show
  1. package/.github/skills/yo-async-effects/async-effects-recipes.md +2 -2
  2. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  3. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +76 -22
  4. package/.github/skills/yo-syntax/SKILL.md +1 -1
  5. package/.github/skills/yo-syntax/syntax-cheatsheet.md +59 -67
  6. package/out/cjs/index.cjs +662 -574
  7. package/out/cjs/yo-cli.cjs +803 -715
  8. package/out/cjs/yo-lsp.cjs +771 -683
  9. package/out/esm/index.mjs +555 -467
  10. package/out/types/src/codegen/exprs/comptime-value.d.ts +2 -1
  11. package/out/types/src/codegen/functions/context.d.ts +1 -0
  12. package/out/types/src/codegen/types/generation.d.ts +1 -1
  13. package/out/types/src/codegen/utils/index.d.ts +2 -4
  14. package/out/types/src/evaluator/exprs/_expr.d.ts +1 -0
  15. package/out/types/src/evaluator/types/flowability.d.ts +22 -0
  16. package/out/types/src/expr.d.ts +4 -13
  17. package/out/types/src/types/creators.d.ts +2 -3
  18. package/out/types/src/types/definitions.d.ts +2 -3
  19. package/out/types/src/types/guards.d.ts +2 -2
  20. package/out/types/src/types/tags.d.ts +2 -2
  21. package/out/types/src/value-tag.d.ts +0 -1
  22. package/out/types/src/value.d.ts +2 -11
  23. package/out/types/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +1 -1
  25. package/std/alg/hash.yo +5 -3
  26. package/std/build.yo +46 -46
  27. package/std/collections/array_list.yo +73 -66
  28. package/std/collections/hash_map.yo +53 -95
  29. package/std/collections/list_view.yo +77 -0
  30. package/std/crypto/random.yo +5 -5
  31. package/std/encoding/base64.yo +12 -13
  32. package/std/encoding/hex.yo +6 -6
  33. package/std/encoding/json.yo +6 -5
  34. package/std/encoding/utf16.yo +9 -9
  35. package/std/env.yo +8 -8
  36. package/std/fmt/to_string.yo +12 -12
  37. package/std/http/client.yo +1 -1
  38. package/std/imm/list.yo +4 -3
  39. package/std/imm/map.yo +3 -2
  40. package/std/imm/set.yo +4 -3
  41. package/std/imm/sorted_map.yo +3 -2
  42. package/std/imm/sorted_set.yo +4 -3
  43. package/std/imm/string.yo +12 -5
  44. package/std/imm/vec.yo +8 -3
  45. package/std/prelude.yo +178 -401
  46. package/std/string/string.yo +198 -71
  47. package/std/url/index.yo +26 -26
  48. package/out/types/src/evaluator/types/slice.d.ts +0 -8
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shd101wyy/yo",
3
3
  "displayName": "Yo",
4
- "version": "0.1.32",
4
+ "version": "0.1.34",
5
5
  "main": "./out/cjs/index.cjs",
6
6
  "module": "./out/esm/index.mjs",
7
7
  "types": "./out/types/src/index.d.ts",
package/std/alg/hash.yo CHANGED
@@ -1,18 +1,20 @@
1
1
  //! FNV-1a (Fowler-Noll-Vo) hash function.
2
2
  //!
3
3
  //! A fast, non-cryptographic hash function with good distribution.
4
+ pragma(Pragma.AllowUnsafe);
4
5
  //! Used internally by `HashMap` and `HashSet`.
5
6
  /// FNV offset basis constant (0xcbf29ce484222325).
6
7
  FNV_OFFSET_BASIS :: u64(14695981039346656037);
7
8
  /// FNV prime constant (0x100000001b3).
8
9
  FNV_PRIME :: u64(1099511628211);
9
10
  /// Hash a byte sequence using FNV-1a.
10
- fnv1a_hash_bytes :: (fn(bytes : Slice(u8)) -> u64)({
11
+ fnv1a_hash_bytes :: (fn(bytes : RawSlice(u8)) -> u64)({
11
12
  hash := FNV_OFFSET_BASIS;
12
- length := bytes.len();
13
+ length := bytes.len;
13
14
  i := usize(0);
14
15
  while(i < length, i = (i + usize(1)), {
15
- byte := bytes(i);
16
+ // SAFETY: i < len; the RawSlice contract requires ptr to cover len bytes.
17
+ byte := unsafe((bytes.ptr &+ i).*);
16
18
  xor := (hash ^ u64(byte));
17
19
  hash = (xor * FNV_PRIME);
18
20
  });
package/std/build.yo CHANGED
@@ -76,11 +76,11 @@ export(target_host);
76
76
  /// Configuration for building an executable.
77
77
  Executable :: struct(
78
78
  /// Artifact name.
79
- name : comptime_string,
79
+ name : comptime_str,
80
80
  /// Root source file.
81
- root : comptime_string,
81
+ root : comptime_str,
82
82
  /// Compilation target triple (defaults to host).
83
- (target : comptime_string) ?= __yo_build_target_host(),
83
+ (target : comptime_str) ?= __yo_build_target_host(),
84
84
  /// Optimization level.
85
85
  (optimize : Optimize) ?= Optimize.Debug,
86
86
  /// Memory allocator.
@@ -92,11 +92,11 @@ export(Executable);
92
92
  /// Configuration for building a static library.
93
93
  StaticLibrary :: struct(
94
94
  /// Artifact name.
95
- name : comptime_string,
95
+ name : comptime_str,
96
96
  /// Root source file.
97
- root : comptime_string,
97
+ root : comptime_str,
98
98
  /// Compilation target triple (defaults to host).
99
- (target : comptime_string) ?= __yo_build_target_host(),
99
+ (target : comptime_str) ?= __yo_build_target_host(),
100
100
  /// Optimization level.
101
101
  (optimize : Optimize) ?= Optimize.Debug
102
102
  );
@@ -104,11 +104,11 @@ export(StaticLibrary);
104
104
  /// Configuration for building a shared/dynamic library.
105
105
  SharedLibrary :: struct(
106
106
  /// Artifact name.
107
- name : comptime_string,
107
+ name : comptime_str,
108
108
  /// Root source file.
109
- root : comptime_string,
109
+ root : comptime_str,
110
110
  /// Compilation target triple (defaults to host).
111
- (target : comptime_string) ?= __yo_build_target_host(),
111
+ (target : comptime_str) ?= __yo_build_target_host(),
112
112
  /// Optimization level.
113
113
  (optimize : Optimize) ?= Optimize.Debug
114
114
  );
@@ -116,11 +116,11 @@ export(SharedLibrary);
116
116
  /// Configuration for a test suite.
117
117
  TestSuite :: struct(
118
118
  /// Suite name.
119
- name : comptime_string,
119
+ name : comptime_str,
120
120
  /// Root test file.
121
- root : comptime_string,
121
+ root : comptime_str,
122
122
  /// Compilation target triple (defaults to host).
123
- (target : comptime_string) ?= __yo_build_target_host()
123
+ (target : comptime_str) ?= __yo_build_target_host()
124
124
  );
125
125
  export(TestSuite);
126
126
  // ── Build module type ────────────────────────────────────────────────
@@ -128,17 +128,17 @@ export(TestSuite);
128
128
  /// Modules are the unit of reuse across Yo dependencies.
129
129
  BuildModule :: struct(
130
130
  /// Module name.
131
- name : comptime_string,
131
+ name : comptime_str,
132
132
  /// Root source file.
133
- root : comptime_string,
134
- _dep : comptime_string
133
+ root : comptime_str,
134
+ _dep : comptime_str
135
135
  );
136
136
  export(BuildModule);
137
137
  // ── Import entry type ────────────────────────────────────────────────
138
138
  /// Pairs an import name with a module for use with `add_import`/`add_import_list`.
139
139
  ImportEntry :: struct(
140
140
  /// Import alias used in source code.
141
- name : comptime_string,
141
+ name : comptime_str,
142
142
  /// The module to import.
143
143
  module : BuildModule
144
144
  );
@@ -148,7 +148,7 @@ export(ImportEntry);
148
148
  /// Use `step.depend_on(dep)` to wire dependencies between steps.
149
149
  Step :: struct(
150
150
  /// Step name.
151
- name : comptime_string,
151
+ name : comptime_str,
152
152
  /// Kind of step.
153
153
  kind : StepKind
154
154
  );
@@ -179,7 +179,7 @@ impl(
179
179
  )
180
180
  ),
181
181
  /// Add extra C compiler flags to this step.
182
- add_c_flags : (fn(comptime(self) : Self, comptime(flags) : comptime_string) -> comptime(unit))({
182
+ add_c_flags : (fn(comptime(self) : Self, comptime(flags) : comptime_str) -> comptime(unit))({
183
183
  __yo_build_add_cflags(self.name, flags);
184
184
  })
185
185
  );
@@ -197,46 +197,46 @@ impl(
197
197
  /// User-configurable build option (declared in `build.yo`, set via `yo build -Dname=value`).
198
198
  BuildOption :: struct(
199
199
  /// Option name (used with `-D`).
200
- name : comptime_string,
200
+ name : comptime_str,
201
201
  /// Human-readable description.
202
- description : comptime_string,
202
+ description : comptime_str,
203
203
  /// Default value if not provided.
204
- (default : comptime_string) ?= ""
204
+ (default : comptime_str) ?= ""
205
205
  );
206
206
  export(BuildOption);
207
207
  // ── Dependency config types ──────────────────────────────────────────
208
208
  /// Git-hosted dependency configuration.
209
209
  GitDependency :: struct(
210
210
  /// Dependency name.
211
- name : comptime_string,
211
+ name : comptime_str,
212
212
  /// Git repository URL.
213
- url : comptime_string,
213
+ url : comptime_str,
214
214
  /// Git ref (tag, branch, or commit SHA). Defaults to `"HEAD"`.
215
- (ref : comptime_string) ?= "HEAD",
215
+ (ref : comptime_str) ?= "HEAD",
216
216
  /// Subdirectory within the repository.
217
- (path : comptime_string) ?= ""
217
+ (path : comptime_str) ?= ""
218
218
  );
219
219
  export(GitDependency);
220
220
  /// Local path dependency configuration.
221
221
  PathDependency :: struct(
222
222
  /// Dependency name.
223
- name : comptime_string,
223
+ name : comptime_str,
224
224
  /// Filesystem path to the dependency root.
225
- path : comptime_string
225
+ path : comptime_str
226
226
  );
227
227
  export(PathDependency);
228
228
  /// System C library discovered via `pkg-config`.
229
229
  SystemLibrary :: struct(
230
230
  /// Library name (passed to `pkg-config`).
231
- name : comptime_string,
231
+ name : comptime_str,
232
232
  /// Fallback include path if pkg-config fails.
233
- (fallback_include : comptime_string) ?= "",
233
+ (fallback_include : comptime_str) ?= "",
234
234
  /// Fallback library path.
235
- (fallback_lib : comptime_string) ?= "",
235
+ (fallback_lib : comptime_str) ?= "",
236
236
  /// Fallback link flags.
237
- (fallback_link : comptime_string) ?= "",
237
+ (fallback_link : comptime_str) ?= "",
238
238
  /// Extra C preprocessor defines.
239
- (defines : comptime_string) ?= ""
239
+ (defines : comptime_str) ?= ""
240
240
  );
241
241
  export(SystemLibrary);
242
242
  // ── Dependency handle ────────────────────────────────────────────────
@@ -244,20 +244,20 @@ export(SystemLibrary);
244
244
  // Provides access to artifacts defined in the dependency's build.yo.
245
245
  /// Handle to a registered dependency. Use `.artifact()` or `.module()` to access its exports.
246
246
  Dependency :: struct(
247
- name : comptime_string
247
+ name : comptime_str
248
248
  );
249
249
  export(Dependency);
250
250
  impl(
251
251
  Dependency,
252
252
  /// Access a named artifact from the dependency's `build.yo`.
253
253
  /// Returns a `Step` that can be linked to the consumer's artifacts.
254
- artifact : (fn(comptime(self) : Self, comptime(artifact_name) : comptime_string) -> comptime(Step))({
254
+ artifact : (fn(comptime(self) : Self, comptime(artifact_name) : comptime_str) -> comptime(Step))({
255
255
  __yo_build_dep_artifact(self.name, artifact_name);
256
256
  Step(name : artifact_name, kind : StepKind.StaticLibrary)
257
257
  }),
258
258
  /// Get a module from the dependency's `build.yo`.
259
259
  /// Empty `module_name` defaults to the sole module if exactly one exists.
260
- module : (fn(comptime(self) : Self, (comptime(module_name) : comptime_string) ?= "") -> comptime(BuildModule))({
260
+ module : (fn(comptime(self) : Self, (comptime(module_name) : comptime_str) ?= "") -> comptime(BuildModule))({
261
261
  _encoded :: __yo_build_dep_module(self.name, module_name);
262
262
  BuildModule(name : module_name, root : "", _dep : self.name)
263
263
  })
@@ -331,8 +331,8 @@ export(run);
331
331
  /// Register a named build step. Use `step.depend_on(dep)` to add dependencies.
332
332
  step :: (
333
333
  fn(
334
- comptime(name) : comptime_string,
335
- comptime(description) : comptime_string
334
+ comptime(name) : comptime_str,
335
+ comptime(description) : comptime_str
336
336
  ) -> comptime(Step)
337
337
  )({
338
338
  __yo_build_step(name, description);
@@ -360,9 +360,9 @@ export(system_library);
360
360
  /// Module configuration for shared compilation units.
361
361
  ModuleConfig :: struct(
362
362
  /// Module name.
363
- name : comptime_string,
363
+ name : comptime_str,
364
364
  /// Root source file for the module.
365
- root : comptime_string
365
+ root : comptime_str
366
366
  );
367
367
  export(ModuleConfig);
368
368
  /// Register a named module. Returns a `BuildModule` for linking system libraries
@@ -398,11 +398,11 @@ export(DocFormat);
398
398
  /// Configuration for documentation generation.
399
399
  DocConfig :: struct(
400
400
  /// Step name (e.g., "doc").
401
- name : comptime_string,
401
+ name : comptime_str,
402
402
  /// Root source file or directory to document.
403
- root : comptime_string,
403
+ root : comptime_str,
404
404
  /// Output directory (default: "yo-out/doc").
405
- (output : comptime_string) ?= "yo-out/doc",
405
+ (output : comptime_str) ?= "yo-out/doc",
406
406
  /// Output format (default: Html).
407
407
  (format : DocFormat) ?= DocFormat.Html,
408
408
  /// Document non-exported (private) items.
@@ -410,14 +410,14 @@ DocConfig :: struct(
410
410
  /// Document dependencies too.
411
411
  (include_deps : bool) ?= false,
412
412
  /// Custom site title (default: project name).
413
- (title : comptime_string) ?= "",
413
+ (title : comptime_str) ?= "",
414
414
  /// Release version to display (e.g., "v1.0.0").
415
415
  /// When empty, auto-detects from git tag or commit hash.
416
- (version : comptime_string) ?= "",
416
+ (version : comptime_str) ?= "",
417
417
  /// Path to logo image.
418
- (logo : comptime_string) ?= "",
418
+ (logo : comptime_str) ?= "",
419
419
  /// Path to favicon.
420
- (favicon : comptime_string) ?= ""
420
+ (favicon : comptime_str) ?= ""
421
421
  );
422
422
  export(DocConfig);
423
423
  /// Register a documentation generation step. Returns a Step for dependency wiring.
@@ -37,19 +37,6 @@ impl(
37
37
  ptr : (fn(self : Self) -> ?*(T))(
38
38
  self._ptr
39
39
  ),
40
- /**
41
- * Get a slice view of the ArrayList
42
- * Returns a fat pointer Slice(T) with data pointer and length
43
- * This allows passing ArrayList to functions expecting slices
44
- * Returns .None for an empty ArrayList with no allocated buffer
45
- */
46
- as_slice : (fn(self : Self) -> Option(Slice(T)))(
47
- match(
48
- self._ptr,
49
- .Some(p) =>.Some(Slice(T).from_raw_parts(p, self._length)),
50
- .None =>.None
51
- )
52
- ),
53
40
  /** * Directly set the length of the ArrayList
54
41
  * UNSAFE: This does not initialize new elements or free removed elements
55
42
  * Only use when you've manually populated the buffer (e.g., via direct memory writes)
@@ -73,6 +60,55 @@ impl(
73
60
  )
74
61
  ),
75
62
  /**
63
+ * Create an ArrayList by copying the elements of a fixed-size array.
64
+ * The owned-copy companion to array range-indexing
65
+ * (plans/SLICE_REWORK.md).
66
+ */
67
+ /**
68
+ * Owned copy of the elements in `[r.start, r.end)` — JS-style range
69
+ * slicing with value semantics (plans/SLICE_REWORK.md: `list(a..b)`
70
+ * lowers to this).
71
+ */
72
+ slice_copy : (fn(self : Self, r : Range(usize)) -> Self)({
73
+ e := cond((r.end > self.len()) => self.len(), true => r.end);
74
+ out := Self.new();
75
+ i := r.start;
76
+ while(i < e, i = (i + usize(1)), {
77
+ match(
78
+ self.get(i),
79
+ .Some(v) => {
80
+ ___ := out.push(v);
81
+ },
82
+ .None => ()
83
+ );
84
+ });
85
+ out
86
+ }),
87
+ /// Inclusive-range companion of `slice_copy` (`list(a..=b)`).
88
+ slice_copy_inclusive : (fn(self : Self, r : RangeInclusive(usize)) -> Self)({
89
+ last := cond((r.end >= self.len()) => self.len(), true => (r.end + usize(1)));
90
+ out := Self.new();
91
+ i := r.start;
92
+ while(i < last, i = (i + usize(1)), {
93
+ match(
94
+ self.get(i),
95
+ .Some(v) => {
96
+ ___ := out.push(v);
97
+ },
98
+ .None => ()
99
+ );
100
+ });
101
+ out
102
+ }),
103
+ from_array : (fn(forall(N : usize), arr : Array(T, N)) -> Self)({
104
+ out := Self.with_capacity(N);
105
+ i := usize(0);
106
+ while(i < N, i = (i + usize(1)), {
107
+ out.push(arr(i));
108
+ });
109
+ out
110
+ }),
111
+ /**
76
112
  * Create an ArrayList with a specific initial cap
77
113
  */
78
114
  with_capacity : (fn(cap : usize) -> Self)(
@@ -507,28 +543,6 @@ impl(
507
543
  })
508
544
  )
509
545
  );
510
- /// Indexable impl — projection-style indexing yielding `ref(T)`.
511
- /// See plans/ITERATOR_REDESIGN.md. Body wraps the pointer arithmetic
512
- /// in `unsafe(...)` to pass the flowability check.
513
- impl(
514
- forall(T : Type),
515
- ArrayList(T),
516
- Indexable(usize)(
517
- Element : T,
518
- project : (fn(ref(self) : Self, pos : usize) -> ref(T))({
519
- assert(pos < self._length, "ArrayList: project out of bounds");
520
- match(
521
- self._ptr,
522
- // SAFETY: assert above bounds `pos < self._length` and the
523
- // length invariant guarantees `pos < self._capacity`, so
524
- // `_ptr &+ pos` stays inside the Rc-managed heap buffer
525
- // for the duration of the borrow.
526
- .Some(_ptr) => unsafe(_ptr &+ pos),
527
- .None => panic("ArrayList: project on empty list")
528
- )
529
- })
530
- )
531
- );
532
546
  impl(
533
547
  forall(T : Type),
534
548
  ArrayList(T),
@@ -586,37 +600,6 @@ impl(
586
600
  ArrayListIter(T)(_list : self, _index : usize(0))
587
601
  )
588
602
  );
589
- /// Position iterator for ArrayList — yields `usize` indices into the
590
- /// list. Used by `ArrayList.iter()`; the for-macro pairs each yielded
591
- /// position with `ArrayList.project(pos)` (Indexable from Phase C) to
592
- /// bind the body's `ref`-name. See plans/ITERATOR_REDESIGN.md.
593
- _ArrayListPosIter :: struct(
594
- _index : usize,
595
- _len : usize
596
- );
597
- impl(
598
- _ArrayListPosIter,
599
- Iterator(
600
- Item : usize,
601
- next : (fn(ref(self) : Self) -> Option(usize))(
602
- cond(
603
- (self._index >= self._len) =>.None,
604
- true => {
605
- out := self._index;
606
- self._index = (self._index + usize(1));
607
- .Some(out)
608
- }
609
- )
610
- )
611
- )
612
- );
613
- impl(
614
- forall(T : Type),
615
- ArrayList(T),
616
- iter : (fn(ref(self) : Self) -> _ArrayListPosIter)(
617
- _ArrayListPosIter(_index : usize(0), _len : self._length)
618
- )
619
- );
620
603
  impl(
621
604
  forall(T : Type),
622
605
  where(T <: Eq(T)),
@@ -859,4 +842,28 @@ array_list :: (fn(...(quote(elems))) -> unquote(Expr))({
859
842
  unquote(tmp)
860
843
  })
861
844
  });
845
+ /// Range slicing on fixed-size arrays returns an OWNED ArrayList copy
846
+ /// (`arr(a..b)` lowers to this — plans/SLICE_REWORK.md).
847
+ impl(
848
+ forall(T : Type, N : usize),
849
+ Array(T, N),
850
+ slice_copy : (fn(self : Array(T, N), r : Range(usize)) -> ArrayList(T))({
851
+ e := cond((r.end > N) => N, true => r.end);
852
+ out := ArrayList(T).new();
853
+ i := r.start;
854
+ while(i < e, i = (i + usize(1)), {
855
+ out.push(self(i));
856
+ });
857
+ out
858
+ }),
859
+ slice_copy_inclusive : (fn(self : Array(T, N), r : RangeInclusive(usize)) -> ArrayList(T))({
860
+ last := cond((r.end >= N) => N, true => (r.end + usize(1)));
861
+ out := ArrayList(T).new();
862
+ i := r.start;
863
+ while(i < last, i = (i + usize(1)), {
864
+ out.push(self(i));
865
+ });
866
+ out
867
+ })
868
+ );
862
869
  export(array_list);
@@ -565,19 +565,25 @@ impl(
565
565
  where(K <: (Eq(K), Hash)),
566
566
  HashMap(K, V),
567
567
  /// Pointer iterator — yields `*(Bucket(K, V))` for each occupied bucket.
568
- /// Kept as a separate method (not `iter()`) so the Phase D for-macro's
569
- /// `coll.iter()` call dispatches to the position-iter variant defined
570
- /// later in the file, enabling `for(map, ref(b) => body)`.
568
+ /// For privileged/unsafe internal use; value iteration goes through
569
+ /// `into_iter()`.
571
570
  iter_ptr : (fn(self : Self) -> HashMapIterPtr(K, V))(
572
571
  HashMapIterPtr(K, V)(_map : self, _index : usize(0))
573
572
  )
574
573
  );
575
574
  /**
576
- * Keys iterator - wraps HashMapIter and yields only the keys
575
+ * Keys iterator - scans ctrl bytes directly and yields only the keys.
576
+ *
577
+ * NOTE: This held a wrapped `_inner : HashMapIter(K, V)` and delegated
578
+ * `self._inner.next()` — but a method call on a struct FIELD of `ref(self)`
579
+ * advances a COPY of the field, so `_index` never moved and manual
580
+ * `it.next()` loops yielded the first key forever (`for(...)` masked it).
581
+ * Scan directly instead, mirroring `HashMapIterPtr`.
577
582
  */
578
583
  HashMapKeys :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
579
584
  struct(
580
- _inner : HashMapIter(K, V)
585
+ _map : HashMap(K, V),
586
+ _index : usize
581
587
  )
582
588
  );
583
589
  impl(
@@ -587,10 +593,23 @@ impl(
587
593
  Iterator(
588
594
  Item : K,
589
595
  next : (fn(ref(self) : Self) -> Option(K))(
590
- match(
591
- self._inner.next(),
592
- .None =>.None,
593
- .Some(bucket) =>.Some(bucket.key)
596
+ cond(
597
+ (self._map.capacity == usize(0)) =>.None,
598
+ true => {
599
+ ctrl_ptr := self._map.ctrl.unwrap();
600
+ data_ptr := self._map.data.unwrap();
601
+ result := Option(K).None;
602
+ while((self._index < self._map.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
603
+ ctrl_byte := (ctrl_ptr &+ self._index).*;
604
+ cond(
605
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
606
+ result =.Some((data_ptr &+ self._index).*.key);
607
+ },
608
+ true => ()
609
+ );
610
+ });
611
+ result
612
+ }
594
613
  )
595
614
  )
596
615
  )
@@ -600,15 +619,19 @@ impl(
600
619
  where(K <: (Eq(K), Hash)),
601
620
  HashMap(K, V),
602
621
  keys : (fn(self : Self) -> HashMapKeys(K, V))(
603
- HashMapKeys(K, V)(_inner : HashMapIter(K, V)(_map : self, _index : usize(0)))
622
+ HashMapKeys(K, V)(_map : self, _index : usize(0))
604
623
  )
605
624
  );
606
625
  /**
607
- * Values iterator - wraps HashMapIter and yields only the values
626
+ * Values iterator - scans ctrl bytes directly and yields only the values.
627
+ *
628
+ * NOTE: Same direct-scan structure as `HashMapKeys` — see the note there for
629
+ * why the wrapped-`_inner` delegation form was replaced.
608
630
  */
609
631
  HashMapValues :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
610
632
  struct(
611
- _inner : HashMapIter(K, V)
633
+ _map : HashMap(K, V),
634
+ _index : usize
612
635
  )
613
636
  );
614
637
  impl(
@@ -618,10 +641,23 @@ impl(
618
641
  Iterator(
619
642
  Item : V,
620
643
  next : (fn(ref(self) : Self) -> Option(V))(
621
- match(
622
- self._inner.next(),
623
- .None =>.None,
624
- .Some(bucket) =>.Some(bucket.value)
644
+ cond(
645
+ (self._map.capacity == usize(0)) =>.None,
646
+ true => {
647
+ ctrl_ptr := self._map.ctrl.unwrap();
648
+ data_ptr := self._map.data.unwrap();
649
+ result := Option(V).None;
650
+ while((self._index < self._map.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
651
+ ctrl_byte := (ctrl_ptr &+ self._index).*;
652
+ cond(
653
+ ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
654
+ result =.Some((data_ptr &+ self._index).*.value);
655
+ },
656
+ true => ()
657
+ );
658
+ });
659
+ result
660
+ }
625
661
  )
626
662
  )
627
663
  )
@@ -631,7 +667,7 @@ impl(
631
667
  where(K <: (Eq(K), Hash)),
632
668
  HashMap(K, V),
633
669
  values : (fn(self : Self) -> HashMapValues(K, V))(
634
- HashMapValues(K, V)(_inner : HashMapIter(K, V)(_map : self, _index : usize(0)))
670
+ HashMapValues(K, V)(_map : self, _index : usize(0))
635
671
  )
636
672
  );
637
673
  impl(
@@ -653,84 +689,6 @@ impl(
653
689
  })
654
690
  )
655
691
  );
656
- /// Position iterator for HashMap that walks occupied buckets and yields
657
- /// their bucket indices. Pairs with the `Indexable(usize)` impl below to
658
- /// make `for(map, ref(b) => body)` legal: `b` becomes a `ref(Bucket(K, V))`
659
- /// and the loop body can destructure `b.key` / `b.value`.
660
- HashMapPosIter :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
661
- struct(
662
- _map : HashMap(K, V),
663
- _index : usize
664
- )
665
- );
666
- impl(
667
- forall(K : Type, V : Type),
668
- where(K <: (Eq(K), Hash)),
669
- HashMapPosIter(K, V),
670
- Iterator(
671
- Item : usize,
672
- next : (fn(ref(self) : Self) -> Option(usize))(
673
- cond(
674
- (self._map.capacity == usize(0)) =>.None,
675
- true => {
676
- ctrl_ptr := self._map.ctrl.unwrap();
677
- result := Option(usize).None;
678
- while((self._index < self._map.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
679
- ctrl_byte := (ctrl_ptr &+ self._index).*;
680
- cond(
681
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
682
- result =.Some(self._index);
683
- },
684
- true => ()
685
- );
686
- });
687
- result
688
- }
689
- )
690
- )
691
- )
692
- );
693
- /// Indexable(usize) — projects an occupied bucket index back to a
694
- /// `ref(Bucket(K, V))` so `for(map, ref(b) => ...)` works. The body of
695
- /// `for` (Phase D) calls `coll.iter()` to obtain a position iter and
696
- /// then `coll.project(pos)` for each yielded position. We override
697
- /// `iter` for HashMap to return the position-iter rather than the
698
- /// `*(Bucket)` iter — the for-macro only cares about which yields
699
- /// positions consumable by `project`.
700
- ///
701
- /// See plans/ITERATOR_REDESIGN.md Open Question 3. The choice here is
702
- /// "projection-returns a single Bucket struct, user destructures
703
- /// inside the loop" — chosen over the rejected `(ref(K), ref(V))`
704
- /// tuple-of-inouts shape.
705
- impl(
706
- forall(K : Type, V : Type),
707
- where(K <: (Eq(K), Hash)),
708
- HashMap(K, V),
709
- Indexable(usize)(
710
- Element : Bucket(K, V),
711
- project : (fn(ref(self) : Self, pos : usize) -> ref(Bucket(K, V)))(
712
- cond(
713
- (pos >= self.capacity) => panic("HashMap: project out of bounds"),
714
- // SAFETY: cond above bounds `pos`; `_data_ptr` returns the
715
- // start of the Rc-managed _data buffer, which is alive while
716
- // `self` holds the Rc.
717
- true => unsafe(Self._data_ptr(self) &+ pos)
718
- )
719
- )
720
- )
721
- );
722
- /// Position-iter constructor for HashMap (paired with the Indexable
723
- /// impl above): `iter()` yields each occupied bucket index, and the
724
- /// for-macro then calls `coll.project(pos)` to materialize the
725
- /// `ref(Bucket)` borrow for the body.
726
- impl(
727
- forall(K : Type, V : Type),
728
- where(K <: (Eq(K), Hash)),
729
- HashMap(K, V),
730
- iter : (fn(self : Self) -> HashMapPosIter(K, V))(
731
- HashMapPosIter(K, V)(_map : self, _index : usize(0))
732
- )
733
- );
734
692
  /// Clone implementation for HashMap — deep-clones all key-value entries.
735
693
  impl(
736
694
  forall(K : Type, V : Type),