@shd101wyy/yo 0.1.33 → 0.1.35

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 (46) hide show
  1. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  2. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +51 -21
  3. package/.github/skills/yo-syntax/SKILL.md +1 -1
  4. package/.github/skills/yo-syntax/syntax-cheatsheet.md +56 -67
  5. package/out/cjs/index.cjs +670 -655
  6. package/out/cjs/yo-cli.cjs +744 -729
  7. package/out/cjs/yo-lsp.cjs +687 -672
  8. package/out/esm/index.mjs +492 -477
  9. package/out/types/src/codegen/exprs/comptime-value.d.ts +2 -1
  10. package/out/types/src/codegen/types/generation.d.ts +1 -1
  11. package/out/types/src/codegen/utils/index.d.ts +2 -4
  12. package/out/types/src/evaluator/exprs/_expr.d.ts +1 -0
  13. package/out/types/src/evaluator/types/flowability.d.ts +21 -0
  14. package/out/types/src/expr.d.ts +5 -13
  15. package/out/types/src/types/creators.d.ts +2 -3
  16. package/out/types/src/types/definitions.d.ts +2 -3
  17. package/out/types/src/types/guards.d.ts +2 -2
  18. package/out/types/src/types/tags.d.ts +2 -2
  19. package/out/types/src/value-tag.d.ts +0 -1
  20. package/out/types/src/value.d.ts +2 -11
  21. package/out/types/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +1 -1
  23. package/std/alg/hash.yo +5 -3
  24. package/std/build.yo +46 -46
  25. package/std/collections/array_list.yo +73 -66
  26. package/std/collections/hash_map.yo +2 -81
  27. package/std/collections/list_view.yo +77 -0
  28. package/std/crypto/random.yo +5 -5
  29. package/std/encoding/base64.yo +12 -13
  30. package/std/encoding/hex.yo +6 -6
  31. package/std/encoding/json.yo +6 -5
  32. package/std/encoding/utf16.yo +9 -9
  33. package/std/env.yo +8 -8
  34. package/std/fmt/to_string.yo +12 -12
  35. package/std/http/client.yo +1 -1
  36. package/std/imm/list.yo +4 -3
  37. package/std/imm/map.yo +3 -2
  38. package/std/imm/set.yo +4 -3
  39. package/std/imm/sorted_map.yo +3 -2
  40. package/std/imm/sorted_set.yo +4 -3
  41. package/std/imm/string.yo +12 -5
  42. package/std/imm/vec.yo +8 -3
  43. package/std/prelude.yo +175 -401
  44. package/std/string/string.yo +198 -71
  45. package/std/url/index.yo +26 -26
  46. 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.33",
4
+ "version": "0.1.35",
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,9 +565,8 @@ 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
  )
@@ -690,84 +689,6 @@ impl(
690
689
  })
691
690
  )
692
691
  );
693
- /// Position iterator for HashMap that walks occupied buckets and yields
694
- /// their bucket indices. Pairs with the `Indexable(usize)` impl below to
695
- /// make `for(map, ref(b) => body)` legal: `b` becomes a `ref(Bucket(K, V))`
696
- /// and the loop body can destructure `b.key` / `b.value`.
697
- HashMapPosIter :: (fn(comptime(K) : Type, comptime(V) : Type) -> comptime(Type))(
698
- struct(
699
- _map : HashMap(K, V),
700
- _index : usize
701
- )
702
- );
703
- impl(
704
- forall(K : Type, V : Type),
705
- where(K <: (Eq(K), Hash)),
706
- HashMapPosIter(K, V),
707
- Iterator(
708
- Item : usize,
709
- next : (fn(ref(self) : Self) -> Option(usize))(
710
- cond(
711
- (self._map.capacity == usize(0)) =>.None,
712
- true => {
713
- ctrl_ptr := self._map.ctrl.unwrap();
714
- result := Option(usize).None;
715
- while((self._index < self._map.capacity) && result.is_none(), self._index = (self._index + usize(1)), {
716
- ctrl_byte := (ctrl_ptr &+ self._index).*;
717
- cond(
718
- ((ctrl_byte != CTRL_EMPTY) && (ctrl_byte != CTRL_DELETED)) => {
719
- result =.Some(self._index);
720
- },
721
- true => ()
722
- );
723
- });
724
- result
725
- }
726
- )
727
- )
728
- )
729
- );
730
- /// Indexable(usize) — projects an occupied bucket index back to a
731
- /// `ref(Bucket(K, V))` so `for(map, ref(b) => ...)` works. The body of
732
- /// `for` (Phase D) calls `coll.iter()` to obtain a position iter and
733
- /// then `coll.project(pos)` for each yielded position. We override
734
- /// `iter` for HashMap to return the position-iter rather than the
735
- /// `*(Bucket)` iter — the for-macro only cares about which yields
736
- /// positions consumable by `project`.
737
- ///
738
- /// See plans/ITERATOR_REDESIGN.md Open Question 3. The choice here is
739
- /// "projection-returns a single Bucket struct, user destructures
740
- /// inside the loop" — chosen over the rejected `(ref(K), ref(V))`
741
- /// tuple-of-inouts shape.
742
- impl(
743
- forall(K : Type, V : Type),
744
- where(K <: (Eq(K), Hash)),
745
- HashMap(K, V),
746
- Indexable(usize)(
747
- Element : Bucket(K, V),
748
- project : (fn(ref(self) : Self, pos : usize) -> ref(Bucket(K, V)))(
749
- cond(
750
- (pos >= self.capacity) => panic("HashMap: project out of bounds"),
751
- // SAFETY: cond above bounds `pos`; `_data_ptr` returns the
752
- // start of the Rc-managed _data buffer, which is alive while
753
- // `self` holds the Rc.
754
- true => unsafe(Self._data_ptr(self) &+ pos)
755
- )
756
- )
757
- )
758
- );
759
- /// Position-iter constructor for HashMap (paired with the Indexable
760
- /// impl above): `iter()` yields each occupied bucket index, and the
761
- /// for-macro then calls `coll.project(pos)` to materialize the
762
- /// `ref(Bucket)` borrow for the body.
763
- impl(
764
- forall(K : Type, V : Type),
765
- where(K <: (Eq(K), Hash)),
766
- HashMap(K, V),
767
- iter : (fn(self : Self) -> HashMapPosIter(K, V))(
768
- HashMapPosIter(K, V)(_map : self, _index : usize(0))
769
- )
770
- );
771
692
  /// Clone implementation for HashMap — deep-clones all key-value entries.
772
693
  impl(
773
694
  forall(K : Type, V : Type),
@@ -0,0 +1,77 @@
1
+ //! ListView — a SAFE window over an `ArrayList(T)`.
2
+ //!
3
+ //! The safe replacement for borrowed slices (plans/SLICE_REWORK.md §3):
4
+ //! a ListView holds the Rc'd backing list and indexes through the LIVE
5
+ //! handle. By construction it cannot dangle:
6
+ //! - the view's Rc keeps the backing object alive (reassigning the
7
+ //! original variable doesn't matter),
8
+ //! - every access re-reads the CURRENT buffer through the handle, so
9
+ //! realloc-on-growth cannot leave a stale pointer,
10
+ //! - shrinkage is caught by bounds checks (a clean `.None`, never UB),
11
+ //! - alias mutation is VISIBLE (alias semantics, not a snapshot).
12
+ //!
13
+ //! Cost model: copying a view = one Rc incref; access = one extra
14
+ //! indirection + bounds check. No copy-on-write.
15
+ { ArrayList } :: import("./array_list.yo");
16
+ ListView :: (fn(comptime(T) : Type) -> comptime(Type))(
17
+ struct(
18
+ _backing : ArrayList(T),
19
+ _offset : usize,
20
+ _len : usize
21
+ )
22
+ );
23
+ impl(
24
+ forall(T : Type),
25
+ ListView(T),
26
+ /// Create a view of `[offset, offset+len)` over `backing`. The window is
27
+ /// clamped to the backing's CURRENT length.
28
+ new : (fn(backing : ArrayList(T), offset : usize, len : usize) -> Self)({
29
+ blen := backing.len();
30
+ o := cond((offset > blen) => blen, true => offset);
31
+ available := (blen - o);
32
+ l := cond((len > available) => available, true => len);
33
+ Self(_backing : backing, _offset : o, _len : l)
34
+ }),
35
+ /// View of the whole list.
36
+ of : (fn(backing : ArrayList(T)) -> Self)({
37
+ n := backing.len();
38
+ Self(_backing : backing, _offset : usize(0), _len : n)
39
+ }),
40
+ /// The view's length (fixed at construction; may exceed what the
41
+ /// backing currently holds if it shrank — reads past it yield .None).
42
+ len : (fn(self : Self) -> usize)(self._len),
43
+ is_empty : (fn(self : Self) -> bool)(self._len == usize(0)),
44
+ /// Read element `i` THROUGH the live backing. Bounds-checked against
45
+ /// both the view window and the backing's current length.
46
+ get : (fn(self : Self, i : usize) -> Option(T))(
47
+ cond(
48
+ (i >= self._len) => Option(T).None,
49
+ true => self._backing.get(self._offset + i)
50
+ )
51
+ ),
52
+ /// A sub-view of this view (still aliasing the same backing).
53
+ /// (Params avoid the names of sibling methods bound earlier in this
54
+ /// impl — e.g. `len` — which cannot be shadowed.)
55
+ view : (fn(self : Self, sub_offset : usize, sub_len : usize) -> Self)({
56
+ o := cond((sub_offset > self._len) => self._len, true => sub_offset);
57
+ available := (self._len - o);
58
+ l := cond((sub_len > available) => available, true => sub_len);
59
+ Self(_backing : self._backing, _offset : (self._offset + o), _len : l)
60
+ }),
61
+ /// Owned copy of the window's CURRENT contents.
62
+ to_list : (fn(self : Self) -> ArrayList(T))({
63
+ out := ArrayList(T).new();
64
+ i := usize(0);
65
+ while(i < self._len, i = (i + usize(1)), {
66
+ match(
67
+ self._backing.get(self._offset + i),
68
+ .Some(v) => {
69
+ ___ := out.push(v);
70
+ },
71
+ .None => ()
72
+ );
73
+ });
74
+ out
75
+ })
76
+ );
77
+ export(ListView);
@@ -55,9 +55,9 @@ extern(
55
55
  // ============================================================================
56
56
  // Fill a buffer with cryptographically secure random bytes.
57
57
  // ============================================================================
58
- random_bytes :: (fn(buf : Slice(u8), exn : Exception) -> unit)({
59
- buf_ptr := buf.ptr();
60
- size := buf.len();
58
+ random_bytes :: (fn(buf : RawSlice(u8), exn : Exception) -> unit)({
59
+ buf_ptr := buf.ptr;
60
+ size := buf.len;
61
61
  cond(
62
62
  (platform == Platform.Macos) => {
63
63
  __yo_arc4random_buf(buf_ptr, size);
@@ -109,7 +109,7 @@ export(random_bytes);
109
109
  // ============================================================================
110
110
  random_u32 :: (fn(exn : Exception) -> u32)({
111
111
  buf := Array(u8, usize(4)).fill(u8(0));
112
- random_bytes(Slice(u8).from_raw_parts(&(buf(usize(0))), usize(4)), exn);
112
+ random_bytes(RawSlice(u8)(ptr : &(buf(usize(0))), len : usize(4)), exn);
113
113
  u32(buf(usize(0))) |
114
114
  (u32(buf(usize(1))) << u32(8)) |
115
115
  (u32(buf(usize(2))) << u32(16)) |
@@ -142,7 +142,7 @@ export(random_u32, random_u64, random_f64, random_range);
142
142
  uuid_v4 :: (fn(exn : Exception) -> String)({
143
143
  bytes := ArrayList(u8).with_capacity(usize(16));
144
144
  buf := Array(u8, usize(16)).fill(u8(0));
145
- random_bytes(Slice(u8).from_raw_parts(&(buf(usize(0))), usize(16)), exn);
145
+ random_bytes(RawSlice(u8)(ptr : &(buf(usize(0))), len : usize(16)), exn);
146
146
  // Set version bits (v4)
147
147
  buf(usize(6)) = ((buf(usize(6)) & u8(0x0F)) | u8(0x40));
148
148
  // Set variant bits