@shd101wyy/yo 0.1.28 → 0.1.30

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 (183) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +15 -15
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +118 -121
  3. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +33 -13
  4. package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +1 -1
  5. package/.github/skills/yo-syntax/SKILL.md +2 -2
  6. package/.github/skills/yo-syntax/syntax-cheatsheet.md +108 -96
  7. package/README.md +6 -3
  8. package/out/cjs/index.cjs +812 -706
  9. package/out/cjs/yo-cli.cjs +1023 -907
  10. package/out/cjs/yo-lsp.cjs +836 -730
  11. package/out/esm/index.mjs +757 -651
  12. package/out/types/src/codegen/exprs/async.d.ts +2 -0
  13. package/out/types/src/codegen/exprs/await.d.ts +1 -0
  14. package/out/types/src/codegen/exprs/closures.d.ts +4 -0
  15. package/out/types/src/codegen/functions/context.d.ts +6 -0
  16. package/out/types/src/codegen/functions/declarations.d.ts +1 -1
  17. package/out/types/src/doc/model.d.ts +0 -1
  18. package/out/types/src/env.d.ts +2 -2
  19. package/out/types/src/evaluator/builtins/pragma.d.ts +9 -0
  20. package/out/types/src/evaluator/builtins/unsafe.d.ts +8 -0
  21. package/out/types/src/evaluator/context.d.ts +3 -1
  22. package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
  23. package/out/types/src/evaluator/index.d.ts +1 -1
  24. package/out/types/src/evaluator/memory-safety.d.ts +14 -0
  25. package/out/types/src/evaluator/types/flowability.d.ts +6 -0
  26. package/out/types/src/evaluator/types/function.d.ts +1 -2
  27. package/out/types/src/evaluator/utils.d.ts +0 -1
  28. package/out/types/src/expr-traversal.d.ts +1 -0
  29. package/out/types/src/expr.d.ts +9 -7
  30. package/out/types/src/public-safe-report.d.ts +19 -0
  31. package/out/types/src/tests/comptime-ref-gate.test.d.ts +1 -0
  32. package/out/types/src/tests/pragma-validation.test.d.ts +1 -0
  33. package/out/types/src/tests/public-safe-report.test.d.ts +1 -0
  34. package/out/types/src/tests/type-representation-pointer.test.d.ts +1 -0
  35. package/out/types/src/tests/unsafe-gate.test.d.ts +1 -0
  36. package/out/types/src/tests/unsafe-report-classify.test.d.ts +1 -0
  37. package/out/types/src/types/creators.d.ts +4 -6
  38. package/out/types/src/types/definitions.d.ts +9 -16
  39. package/out/types/src/types/guards.d.ts +1 -2
  40. package/out/types/src/types/tags.d.ts +0 -1
  41. package/out/types/src/types/utils.d.ts +5 -0
  42. package/out/types/src/unsafe-report.d.ts +29 -0
  43. package/out/types/src/value.d.ts +1 -0
  44. package/out/types/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +1 -1
  46. package/scripts/add-pragma-for-pointer-decls.ts +134 -0
  47. package/scripts/add-pragma.ts +58 -0
  48. package/scripts/migrate-amp-method-calls.ts +186 -0
  49. package/scripts/migrate-clone-calls.ts +93 -0
  50. package/scripts/migrate-get-unwrap.ts +166 -0
  51. package/scripts/migrate-index-patterns.ts +210 -0
  52. package/scripts/migrate-index-trait.ts +142 -0
  53. package/scripts/migrate-iterator.ts +150 -0
  54. package/scripts/migrate-self-ptr.ts +220 -0
  55. package/scripts/migrate-skip-pragmas.ts +109 -0
  56. package/scripts/migrate-tostring.ts +134 -0
  57. package/scripts/trim-pragma.ts +130 -0
  58. package/scripts/wrap-extern-calls.ts +161 -0
  59. package/std/alg/hash.yo +3 -2
  60. package/std/allocator.yo +6 -5
  61. package/std/async.yo +2 -2
  62. package/std/collections/array_list.yo +59 -40
  63. package/std/collections/btree_map.yo +19 -18
  64. package/std/collections/deque.yo +9 -8
  65. package/std/collections/hash_map.yo +101 -13
  66. package/std/collections/hash_set.yo +5 -4
  67. package/std/collections/linked_list.yo +39 -4
  68. package/std/collections/ordered_map.yo +3 -3
  69. package/std/collections/priority_queue.yo +14 -13
  70. package/std/crypto/md5.yo +2 -1
  71. package/std/crypto/random.yo +21 -20
  72. package/std/crypto/sha256.yo +2 -1
  73. package/std/encoding/base64.yo +18 -18
  74. package/std/encoding/hex.yo +5 -5
  75. package/std/encoding/json.yo +62 -13
  76. package/std/encoding/punycode.yo +24 -23
  77. package/std/encoding/toml.yo +4 -3
  78. package/std/encoding/utf16.yo +3 -3
  79. package/std/env.yo +43 -28
  80. package/std/error.yo +15 -3
  81. package/std/fmt/display.yo +2 -2
  82. package/std/fmt/index.yo +6 -5
  83. package/std/fmt/to_string.yo +39 -38
  84. package/std/fmt/writer.yo +9 -8
  85. package/std/fs/dir.yo +61 -66
  86. package/std/fs/file.yo +121 -126
  87. package/std/fs/metadata.yo +13 -18
  88. package/std/fs/temp.yo +35 -30
  89. package/std/fs/walker.yo +14 -19
  90. package/std/gc.yo +1 -0
  91. package/std/glob.yo +7 -7
  92. package/std/http/client.yo +33 -36
  93. package/std/http/http.yo +6 -6
  94. package/std/http/index.yo +4 -4
  95. package/std/imm/list.yo +33 -0
  96. package/std/imm/map.yo +2 -1
  97. package/std/imm/set.yo +1 -0
  98. package/std/imm/sorted_map.yo +1 -0
  99. package/std/imm/sorted_set.yo +1 -0
  100. package/std/imm/string.yo +27 -23
  101. package/std/imm/vec.yo +18 -2
  102. package/std/io/reader.yo +2 -1
  103. package/std/io/writer.yo +3 -2
  104. package/std/libc/assert.yo +1 -0
  105. package/std/libc/ctype.yo +1 -0
  106. package/std/libc/dirent.yo +1 -0
  107. package/std/libc/errno.yo +1 -0
  108. package/std/libc/fcntl.yo +1 -0
  109. package/std/libc/float.yo +1 -0
  110. package/std/libc/limits.yo +1 -0
  111. package/std/libc/math.yo +1 -0
  112. package/std/libc/signal.yo +1 -0
  113. package/std/libc/stdatomic.yo +1 -0
  114. package/std/libc/stdint.yo +1 -0
  115. package/std/libc/stdio.yo +1 -0
  116. package/std/libc/stdlib.yo +1 -0
  117. package/std/libc/string.yo +1 -0
  118. package/std/libc/sys/stat.yo +1 -0
  119. package/std/libc/time.yo +1 -0
  120. package/std/libc/unistd.yo +1 -0
  121. package/std/libc/wctype.yo +1 -0
  122. package/std/libc/windows.yo +2 -0
  123. package/std/log.yo +7 -6
  124. package/std/net/addr.yo +6 -5
  125. package/std/net/dns.yo +13 -16
  126. package/std/net/errors.yo +9 -9
  127. package/std/net/tcp.yo +71 -74
  128. package/std/net/udp.yo +40 -43
  129. package/std/os/signal.yo +5 -5
  130. package/std/path.yo +1 -0
  131. package/std/prelude.yo +377 -200
  132. package/std/process/command.yo +57 -46
  133. package/std/process/index.yo +2 -1
  134. package/std/regex/compiler.yo +10 -9
  135. package/std/regex/index.yo +41 -41
  136. package/std/regex/match.yo +2 -2
  137. package/std/regex/parser.yo +31 -31
  138. package/std/regex/vm.yo +42 -41
  139. package/std/string/string.yo +95 -40
  140. package/std/string/string_builder.yo +9 -9
  141. package/std/string/unicode.yo +50 -49
  142. package/std/sync/channel.yo +2 -1
  143. package/std/sync/cond.yo +5 -4
  144. package/std/sync/mutex.yo +4 -3
  145. package/std/sys/advise.yo +1 -0
  146. package/std/sys/bufio/buf_reader.yo +27 -26
  147. package/std/sys/bufio/buf_writer.yo +22 -21
  148. package/std/sys/clock.yo +1 -0
  149. package/std/sys/copy.yo +1 -0
  150. package/std/sys/dir.yo +10 -9
  151. package/std/sys/dns.yo +6 -5
  152. package/std/sys/errors.yo +12 -12
  153. package/std/sys/events.yo +1 -0
  154. package/std/sys/externs.yo +38 -37
  155. package/std/sys/file.yo +17 -16
  156. package/std/sys/future.yo +4 -3
  157. package/std/sys/iov.yo +1 -0
  158. package/std/sys/mmap.yo +1 -0
  159. package/std/sys/path.yo +1 -0
  160. package/std/sys/perm.yo +2 -1
  161. package/std/sys/pipe.yo +1 -0
  162. package/std/sys/process.yo +5 -4
  163. package/std/sys/signal.yo +1 -0
  164. package/std/sys/socketpair.yo +1 -0
  165. package/std/sys/sockinfo.yo +1 -0
  166. package/std/sys/statfs.yo +2 -1
  167. package/std/sys/statx.yo +1 -0
  168. package/std/sys/sysinfo.yo +1 -0
  169. package/std/sys/tcp.yo +15 -14
  170. package/std/sys/temp.yo +1 -0
  171. package/std/sys/time.yo +2 -1
  172. package/std/sys/timer.yo +6 -6
  173. package/std/sys/tty.yo +2 -1
  174. package/std/sys/udp.yo +13 -12
  175. package/std/sys/unix.yo +12 -11
  176. package/std/testing/bench.yo +4 -3
  177. package/std/thread.yo +7 -6
  178. package/std/time/datetime.yo +18 -15
  179. package/std/time/duration.yo +11 -10
  180. package/std/time/instant.yo +4 -4
  181. package/std/time/sleep.yo +1 -0
  182. package/std/url/index.yo +5 -5
  183. package/std/worker.yo +4 -3
@@ -1,4 +1,5 @@
1
1
  //! Hash map using SwissTable algorithm with SIMD-accelerated lookup.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { GlobalAllocator, AllocError } :: import("../allocator.yo");
3
4
  { malloc, calloc, realloc, free } :: GlobalAllocator;
4
5
  /// Error variants for HashMap operations.
@@ -491,7 +492,7 @@ impl(
491
492
  HashMapIter(K, V),
492
493
  Iterator(
493
494
  Item : Bucket(K, V),
494
- next : (fn(self : *(Self)) -> Option(Bucket(K, V)))(
495
+ next : (fn(ref(self) : Self) -> Option(Bucket(K, V)))(
495
496
  cond(
496
497
  (self._map.capacity == usize(0)) =>.None,
497
498
  true => {
@@ -537,7 +538,7 @@ impl(
537
538
  HashMapIterPtr(K, V),
538
539
  Iterator(
539
540
  Item : *(Bucket(K, V)),
540
- next : (fn(self : *(Self)) -> Option(*(Bucket(K, V))))(
541
+ next : (fn(ref(self) : Self) -> Option(*(Bucket(K, V))))(
541
542
  cond(
542
543
  (self._map.capacity == usize(0)) =>.None,
543
544
  true => {
@@ -563,8 +564,12 @@ impl(
563
564
  forall(K : Type, V : Type),
564
565
  where(K <: (Eq(K), Hash)),
565
566
  HashMap(K, V),
566
- iter : (fn(self : *(Self)) -> HashMapIterPtr(K, V))(
567
- HashMapIterPtr(K, V)(_map : self.*, _index : usize(0))
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)`.
571
+ iter_ptr : (fn(self : Self) -> HashMapIterPtr(K, V))(
572
+ HashMapIterPtr(K, V)(_map : self, _index : usize(0))
568
573
  )
569
574
  );
570
575
  /**
@@ -581,7 +586,7 @@ impl(
581
586
  HashMapKeys(K, V),
582
587
  Iterator(
583
588
  Item : K,
584
- next : (fn(self : *(Self)) -> Option(K))(
589
+ next : (fn(ref(self) : Self) -> Option(K))(
585
590
  match(
586
591
  self._inner.next(),
587
592
  .None =>.None,
@@ -612,7 +617,7 @@ impl(
612
617
  HashMapValues(K, V),
613
618
  Iterator(
614
619
  Item : V,
615
- next : (fn(self : *(Self)) -> Option(V))(
620
+ next : (fn(ref(self) : Self) -> Option(V))(
616
621
  match(
617
622
  self._inner.next(),
618
623
  .None =>.None,
@@ -634,13 +639,13 @@ impl(
634
639
  HashMap(K, V),
635
640
  Index(K)(
636
641
  Output : V,
637
- index : (fn(self : *(Self), idx : K, where(K <: (Eq(K), Hash))) -> *(Self.Output))({
642
+ index : (fn(ref(self) : Self, idx : K, where(K <: (Eq(K), Hash))) -> *(Self.Output))({
638
643
  hash := idx.hash();
639
- bucket_opt := Self._find_bucket(self.*, idx, hash);
644
+ bucket_opt := Self._find_bucket(self, idx, hash);
640
645
  match(
641
646
  bucket_opt,
642
647
  .Some(i) => {
643
- data_ptr := Self._data_ptr(self.*);
648
+ data_ptr := Self._data_ptr(self);
644
649
  &((data_ptr &+ i).*.value)
645
650
  },
646
651
  .None => panic("HashMap: key not found")
@@ -648,15 +653,93 @@ impl(
648
653
  })
649
654
  )
650
655
  );
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
+ );
651
734
  /// Clone implementation for HashMap — deep-clones all key-value entries.
652
735
  impl(
653
736
  forall(K : Type, V : Type),
654
737
  where(K <: (Clone, Eq(K), Hash), V <: Clone),
655
738
  HashMap(K, V),
656
739
  Clone(
657
- clone : (fn(self : *(Self)) -> Self)({
740
+ clone : (fn(ref(self) : Self) -> Self)({
658
741
  result := Self.new();
659
- it := self.iter();
742
+ it := self.iter_ptr();
660
743
  running := true;
661
744
  while(running, {
662
745
  nxt := it.next();
@@ -666,8 +749,13 @@ impl(
666
749
  running = false;
667
750
  },
668
751
  .Some(bucket_ptr) => {
669
- k := (&(bucket_ptr.*.key)).clone();
670
- v := (&(bucket_ptr.*.value)).clone();
752
+ // SAFETY: iter_ptr().next() returns .Some(p) only when p
753
+ // points at an occupied bucket within the Rc-managed
754
+ // _data buffer; the buffer is alive while `self` holds
755
+ // the Rc (we received `ref(self)` so the caller still
756
+ // owns it across this call).
757
+ k := unsafe(bucket_ptr.*.key.clone());
758
+ v := unsafe(bucket_ptr.*.value.clone());
671
759
  result.set(k, v);
672
760
  }
673
761
  );
@@ -1,4 +1,5 @@
1
1
  //! Hash set using SwissTable algorithm with set-theoretic operations.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { GlobalAllocator, AllocError } :: import("../allocator.yo");
3
4
  { malloc, calloc, realloc, free } :: GlobalAllocator;
4
5
  /// Error variants for HashSet operations.
@@ -688,7 +689,7 @@ impl(
688
689
  HashSetIter(T),
689
690
  Iterator(
690
691
  Item : T,
691
- next : (fn(self : *(Self)) -> Option(T))(
692
+ next : (fn(ref(self) : Self) -> Option(T))(
692
693
  cond(
693
694
  (self._set.capacity == usize(0)) =>.None,
694
695
  true => {
@@ -734,7 +735,7 @@ impl(
734
735
  HashSetIterPtr(T),
735
736
  Iterator(
736
737
  Item : *(T),
737
- next : (fn(self : *(Self)) -> Option(*(T)))(
738
+ next : (fn(ref(self) : Self) -> Option(*(T)))(
738
739
  cond(
739
740
  (self._set.capacity == usize(0)) =>.None,
740
741
  true => {
@@ -760,8 +761,8 @@ impl(
760
761
  forall(T : Type),
761
762
  where(T <: (Eq(T), Hash)),
762
763
  HashSet(T),
763
- iter : (fn(self : *(Self)) -> HashSetIterPtr(T))(
764
- HashSetIterPtr(T)(_set : self.*, _index : usize(0))
764
+ iter : (fn(self : Self) -> HashSetIterPtr(T))(
765
+ HashSetIterPtr(T)(_set : self, _index : usize(0))
765
766
  )
766
767
  );
767
768
  export(
@@ -1,5 +1,6 @@
1
1
  //! Doubly-linked list with O(1) push/pop at both ends.
2
2
  /// Error variants for LinkedList operations.
3
+ pragma(Pragma.AllowUnsafe);
3
4
  LinkedListError :: enum(
4
5
  /// Index is out of bounds for the current length.
5
6
  IndexOutOfBounds(index : usize, length : usize),
@@ -409,7 +410,7 @@ impl(
409
410
  LinkedListIter(T),
410
411
  Iterator(
411
412
  Item : T,
412
- next : (fn(self : *(Self)) -> Option(T))(
413
+ next : (fn(ref(self) : Self) -> Option(T))(
413
414
  match(
414
415
  self._current,
415
416
  .None =>.None,
@@ -443,7 +444,7 @@ impl(
443
444
  LinkedListIterPtr(T),
444
445
  Iterator(
445
446
  Item : *(T),
446
- next : (fn(self : *(Self)) -> Option(*(T)))(
447
+ next : (fn(ref(self) : Self) -> Option(*(T)))(
447
448
  match(
448
449
  self._current,
449
450
  .None =>.None,
@@ -458,8 +459,42 @@ impl(
458
459
  impl(
459
460
  forall(T : Type),
460
461
  LinkedList(T),
461
- iter : (fn(self : *(Self)) -> LinkedListIterPtr(T))(
462
- LinkedListIterPtr(T)(_current : self.*.head)
462
+ iter : (fn(self : Self) -> LinkedListIterPtr(T))(
463
+ LinkedListIterPtr(T)(_current : self.head)
464
+ )
465
+ );
466
+ /// Index trait — `list(idx)` returns the element at `idx`. O(n) walk.
467
+ /// `&(node.value)` is a valid heap pointer while `self` keeps the
468
+ /// Rc chain alive — the dispatcher inlines and dereferences this
469
+ /// before any drop runs. Same pattern as `LinkedListIterPtr.next`.
470
+ impl(
471
+ forall(T : Type),
472
+ LinkedList(T),
473
+ Index(usize)(
474
+ Output : T,
475
+ index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))({
476
+ assert(idx < self.length, "LinkedList: index out of bounds");
477
+ (current : Option(Node(T))) = self.head;
478
+ i := usize(0);
479
+ while(runtime(true), {
480
+ match(
481
+ current,
482
+ .Some(node) => {
483
+ if(i == idx, {
484
+ // SAFETY: `node` is held in an Rc-managed chain rooted
485
+ // at `self.head`; while `self` is borrowed (ref(self))
486
+ // every node we've walked stays alive, so `&node.value`
487
+ // is a valid borrow into Rc storage.
488
+ return(unsafe(&(node.value)));
489
+ });
490
+ current = node.next;
491
+ i = (i + usize(1));
492
+ },
493
+ .None => panic("LinkedList: unreachable past length check")
494
+ );
495
+ });
496
+ panic("LinkedList: index loop exited without return")
497
+ })
463
498
  )
464
499
  );
465
500
  export(
@@ -142,7 +142,7 @@ impl(
142
142
  forall(K : Type, V : Type),
143
143
  where(K <: (Eq(K), Hash)),
144
144
  OrderedMapKeys(K, V),
145
- next : (fn(self : *(Self)) -> Option(K))({
145
+ next : (fn(ref(self) : Self) -> Option(K))({
146
146
  cond(
147
147
  (self._index >= self._map._order.len()) => {
148
148
  return(.None);
@@ -171,7 +171,7 @@ impl(
171
171
  forall(K : Type, V : Type),
172
172
  where(K <: (Eq(K), Hash)),
173
173
  OrderedMapValues(K, V),
174
- next : (fn(self : *(Self)) -> Option(V))({
174
+ next : (fn(ref(self) : Self) -> Option(V))({
175
175
  cond(
176
176
  (self._index >= self._map._order.len()) => {
177
177
  return(.None);
@@ -219,7 +219,7 @@ impl(
219
219
  forall(K : Type, V : Type),
220
220
  where(K <: (Eq(K), Hash)),
221
221
  OrderedMapIter(K, V),
222
- next : (fn(self : *(Self)) -> Option(OrderedMapEntry(K, V)))({
222
+ next : (fn(ref(self) : Self) -> Option(OrderedMapEntry(K, V)))({
223
223
  cond(
224
224
  (self._index >= self._map._order.len()) => {
225
225
  return(.None);
@@ -11,6 +11,7 @@
11
11
  //! pq.push(3);
12
12
  //! x := pq.pop().unwrap(); // 1
13
13
  //! ```
14
+ pragma(Pragma.AllowUnsafe);
14
15
  { ArrayList } :: import("./array_list");
15
16
  /// Min-heap backed by an ArrayList.
16
17
  /// Elements are ordered ascending (smallest first). Negate keys for max-heap behavior.
@@ -48,8 +49,8 @@ impl(
48
49
  i := (self._data.len() - usize(1));
49
50
  while(i > usize(0), {
50
51
  parent := ((i - usize(1)) / usize(2));
51
- child_val := self._data.get(i).unwrap();
52
- parent_val := self._data.get(parent).unwrap();
52
+ child_val := self._data(i);
53
+ parent_val := self._data(parent);
53
54
  cond(
54
55
  (child_val < parent_val) => {
55
56
  &(self._data(i)).* = parent_val;
@@ -68,8 +69,8 @@ impl(
68
69
  cond(
69
70
  (n == usize(0)) =>.None,
70
71
  true => {
71
- top := self._data.get(usize(0)).unwrap();
72
- last := self._data.get(n - usize(1)).unwrap();
72
+ top := self._data(usize(0));
73
+ last := self._data(n - usize(1));
73
74
  &(self._data(usize(0))).* = last;
74
75
  self._data.pop();
75
76
  // Sift down
@@ -80,13 +81,13 @@ impl(
80
81
  smallest := i;
81
82
  new_n := self._data.len();
82
83
  cond(
83
- ((left < new_n) && (self._data.get(left).unwrap() < self._data.get(smallest).unwrap())) => {
84
+ ((left < new_n) && (self._data(left) < self._data(smallest))) => {
84
85
  smallest = left;
85
86
  },
86
87
  true => ()
87
88
  );
88
89
  cond(
89
- ((right < new_n) && (self._data.get(right).unwrap() < self._data.get(smallest).unwrap())) => {
90
+ ((right < new_n) && (self._data(right) < self._data(smallest))) => {
90
91
  smallest = right;
91
92
  },
92
93
  true => ()
@@ -96,8 +97,8 @@ impl(
96
97
  break;
97
98
  },
98
99
  true => {
99
- a := self._data.get(i).unwrap();
100
- b := self._data.get(smallest).unwrap();
100
+ a := self._data(i);
101
+ b := self._data(smallest);
101
102
  &(self._data(i)).* = b;
102
103
  &(self._data(smallest)).* = a;
103
104
  i = smallest;
@@ -124,11 +125,11 @@ impl(
124
125
  PriorityQueueIter(T),
125
126
  Iterator(
126
127
  Item : T,
127
- next : (fn(self : *(Self)) -> Option(T))(
128
+ next : (fn(ref(self) : Self) -> Option(T))(
128
129
  cond(
129
130
  (self._index >= self._data.len()) =>.None,
130
131
  true => {
131
- value := self._data.get(self._index).unwrap();
132
+ value := self._data(self._index);
132
133
  self._index = (self._index + usize(1));
133
134
  .Some(value)
134
135
  }
@@ -157,7 +158,7 @@ impl(
157
158
  PriorityQueueIterPtr(T),
158
159
  Iterator(
159
160
  Item : *(T),
160
- next : (fn(self : *(Self)) -> Option(*(T)))(
161
+ next : (fn(ref(self) : Self) -> Option(*(T)))(
161
162
  cond(
162
163
  (self._index >= self._data.len()) =>.None,
163
164
  true =>
@@ -177,8 +178,8 @@ impl(
177
178
  impl(
178
179
  forall(T : Type),
179
180
  PriorityQueue(T),
180
- iter : (fn(self : *(Self)) -> PriorityQueueIterPtr(T))(
181
- PriorityQueueIterPtr(T)(_data : self.*._data, _index : usize(0))
181
+ iter : (fn(ref(self) : Self) -> PriorityQueueIterPtr(T))(
182
+ PriorityQueueIterPtr(T)(_data : self._data, _index : usize(0))
182
183
  )
183
184
  );
184
185
  export(
package/std/crypto/md5.yo CHANGED
@@ -8,6 +8,7 @@
8
8
  //!
9
9
  //! digest := md5_hex(data); // "5d41402abc4b2a76b9719d911017c592"
10
10
  //! ```
11
+ pragma(Pragma.AllowUnsafe);
11
12
  { ArrayList } :: import("../collections/array_list");
12
13
  { hex_encode } :: import("../encoding/hex");
13
14
  open(import("../string"));
@@ -213,7 +214,7 @@ md5 :: (fn(data : ArrayList(u8)) -> Array(u8, usize(16)))({
213
214
  rem := (n - i);
214
215
  j := usize(0);
215
216
  while(j < rem, j = (j + usize(1)), {
216
- (pad_ptr &+ j).* = data.get(i + j).unwrap();
217
+ (pad_ptr &+ j).* = data(i + j);
217
218
  });
218
219
  (pad_ptr &+ rem).* = u8(0x80);
219
220
  cond(
@@ -9,6 +9,7 @@
9
9
  //!
10
10
  //! id := uuid_v4(); // "550e8400-e29b-41d4-a716-446655440000"
11
11
  //! ```
12
+ pragma(Pragma.AllowUnsafe);
12
13
  { ArrayList } :: import("../collections/array_list");
13
14
  { platform, Platform } :: import("../process");
14
15
  open(import("../string"));
@@ -54,13 +55,15 @@ extern(
54
55
  // ============================================================================
55
56
  // Fill a buffer with cryptographically secure random bytes.
56
57
  // ============================================================================
57
- random_bytes :: (fn(buf : *(u8), size : usize, using(exn : Exception)) -> unit)(
58
+ random_bytes :: (fn(buf : Slice(u8), exn : Exception) -> unit)({
59
+ buf_ptr := buf.ptr();
60
+ size := buf.len();
58
61
  cond(
59
62
  (platform == Platform.Macos) => {
60
- __yo_arc4random_buf(buf, size);
63
+ __yo_arc4random_buf(buf_ptr, size);
61
64
  },
62
65
  (platform == Platform.Windows) => {
63
- r := __yo_bcrypt_gen_random(buf, u32(size));
66
+ r := __yo_bcrypt_gen_random(buf_ptr, u32(size));
64
67
  cond(
65
68
  (r == i32(0)) => (),
66
69
  true => {
@@ -77,7 +80,7 @@ random_bytes :: (fn(buf : *(u8), size : usize, using(exn : Exception)) -> unit)(
77
80
  (remaining > usize(256)) => usize(256),
78
81
  true => remaining
79
82
  );
80
- ret := __yo_getentropy(buf &+ offset, chunk);
83
+ ret := __yo_getentropy(buf_ptr &+ offset, chunk);
81
84
  cond(
82
85
  (ret < i32(0)) => {
83
86
  exn.throw(dyn(CryptoError.Unavailable));
@@ -90,7 +93,7 @@ random_bytes :: (fn(buf : *(u8), size : usize, using(exn : Exception)) -> unit)(
90
93
  },
91
94
  true => {
92
95
  // Linux: getrandom syscall
93
- ret := __yo_getrandom(buf, size, u32(0));
96
+ ret := __yo_getrandom(buf_ptr, size, u32(0));
94
97
  cond(
95
98
  (ret < isize(0)) => {
96
99
  exn.throw(dyn(CryptoError.Unavailable));
@@ -99,35 +102,34 @@ random_bytes :: (fn(buf : *(u8), size : usize, using(exn : Exception)) -> unit)(
99
102
  );
100
103
  }
101
104
  )
102
- );
105
+ });
103
106
  export(random_bytes);
104
107
  // ============================================================================
105
108
  // Typed helpers
106
109
  // ============================================================================
107
- random_u32 :: (fn(using(exn : Exception)) -> u32)({
110
+ random_u32 :: (fn(exn : Exception) -> u32)({
108
111
  buf := Array(u8, usize(4)).fill(u8(0));
109
- buf_ptr := &(buf(usize(0)));
110
- random_bytes(buf_ptr, usize(4));
112
+ random_bytes(Slice(u8).from_raw_parts(&(buf(usize(0))), usize(4)), exn);
111
113
  u32(buf(usize(0))) |
112
114
  (u32(buf(usize(1))) << u32(8)) |
113
115
  (u32(buf(usize(2))) << u32(16)) |
114
116
  (u32(buf(usize(3))) << u32(24))
115
117
  });
116
- random_u64 :: (fn(using(exn : Exception)) -> u64)({
117
- lo := u64(random_u32());
118
- hi := u64(random_u32());
118
+ random_u64 :: (fn(exn : Exception) -> u64)({
119
+ lo := u64(random_u32(exn));
120
+ hi := u64(random_u32(exn));
119
121
  lo | (hi << u64(32))
120
122
  });
121
- random_f64 :: (fn(using(exn : Exception)) -> f64)(
122
- f64(random_u64()) / f64(18446744073709551615.0)
123
+ random_f64 :: (fn(exn : Exception) -> f64)(
124
+ f64(random_u64(exn)) / f64(18446744073709551615.0)
123
125
  );
124
126
  // Return a random integer in the half-open range [min, max).
125
- random_range :: (fn(min : i64, max : i64, using(exn : Exception)) -> i64)({
127
+ random_range :: (fn(min : i64, max : i64, exn : Exception) -> i64)({
126
128
  span := (max - min);
127
129
  cond(
128
130
  (span <= i64(0)) => min,
129
131
  true => {
130
- r := random_u64();
132
+ r := random_u64(exn);
131
133
  min + i64(r % u64(span))
132
134
  }
133
135
  )
@@ -137,11 +139,10 @@ export(random_u32, random_u64, random_f64, random_range);
137
139
  // UUID v4
138
140
  // ============================================================================
139
141
  // Generate a random UUID v4 string: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
140
- uuid_v4 :: (fn(using(exn : Exception)) -> String)({
142
+ uuid_v4 :: (fn(exn : Exception) -> String)({
141
143
  bytes := ArrayList(u8).with_capacity(usize(16));
142
144
  buf := Array(u8, usize(16)).fill(u8(0));
143
- buf_ptr := &(buf(usize(0)));
144
- random_bytes(buf_ptr, usize(16));
145
+ random_bytes(Slice(u8).from_raw_parts(&(buf(usize(0))), usize(16)), exn);
145
146
  // Set version bits (v4)
146
147
  buf(usize(6)) = ((buf(usize(6)) & u8(0x0F)) | u8(0x40));
147
148
  // Set variant bits
@@ -165,7 +166,7 @@ uuid_v4 :: (fn(using(exn : Exception)) -> String)({
165
166
  },
166
167
  true => ()
167
168
  );
168
- out.push(hex_bytes.get(j).unwrap());
169
+ out.push(hex_bytes(j));
169
170
  });
170
171
  String.from_bytes(out)
171
172
  });
@@ -7,6 +7,7 @@
7
7
  //!
8
8
  //! digest := sha256_hex(data); // "2cf24dba..."
9
9
  //! ```
10
+ pragma(Pragma.AllowUnsafe);
10
11
  { ArrayList } :: import("../collections/array_list");
11
12
  { hex_encode } :: import("../encoding/hex");
12
13
  open(import("../string"));
@@ -176,7 +177,7 @@ impl(
176
177
  update : (fn(self : Self, data : ArrayList(u8)) -> Self)({
177
178
  i := usize(0);
178
179
  while(i < data.len(), i = (i + usize(1)), {
179
- self._buf(self._buflen) = data.get(i).unwrap();
180
+ self._buf(self._buflen) = data(i);
180
181
  self._buflen = (self._buflen + usize(1));
181
182
  self._total = (self._total + u64(1));
182
183
  cond(
@@ -26,9 +26,9 @@ _encode_with :: (fn(data : ArrayList(u8), alpha : str, pad : bool) -> String)({
26
26
  out := ArrayList(u8).with_capacity(((n + usize(2)) / usize(3)) * usize(4));
27
27
  i := usize(0);
28
28
  while(i < n, i = (i + usize(3)), {
29
- b0 := data.get(i).unwrap();
30
- b1 := cond(((i + usize(1)) < n) => data.get(i + usize(1)).unwrap(), true => u8(0));
31
- b2 := cond(((i + usize(2)) < n) => data.get(i + usize(2)).unwrap(), true => u8(0));
29
+ b0 := data(i);
30
+ b1 := cond(((i + usize(1)) < n) => data(i + usize(1)), true => u8(0));
31
+ b2 := cond(((i + usize(2)) < n) => data(i + usize(2)), true => u8(0));
32
32
  out.push(alpha.bytes(usize(b0 >> u8(2))));
33
33
  out.push(alpha.bytes(usize(((b0 & u8(3)) << u8(4)) | (b1 >> u8(4)))));
34
34
  cond(
@@ -64,7 +64,7 @@ export(base64_encode, base64_encode_url);
64
64
  // ============================================================================
65
65
  // Decoding
66
66
  // ============================================================================
67
- _decode_char :: (fn(c : u8, alpha : str, using(exn : Exception)) -> u8)({
67
+ _decode_char :: (fn(c : u8, alpha : str, exn : Exception) -> u8)({
68
68
  i := usize(0);
69
69
  while(i < usize(64), i = (i + usize(1)), {
70
70
  cond(
@@ -76,26 +76,26 @@ _decode_char :: (fn(c : u8, alpha : str, using(exn : Exception)) -> u8)({
76
76
  });
77
77
  exn.throw(dyn(EncodingError.InvalidChar(c)))
78
78
  });
79
- _decode_with :: (fn(s : str, alpha : str, using(exn : Exception)) -> ArrayList(u8))({
79
+ _decode_with :: (fn(s : str, alpha : str, exn : Exception) -> ArrayList(u8))({
80
80
  // Strip trailing padding
81
81
  len := s.len();
82
82
  while((len > usize(0)) && (s.bytes(len - usize(1)) == _PAD), len = (len - usize(1)), ());
83
83
  out := ArrayList(u8).with_capacity((len * usize(3)) / usize(4));
84
84
  i := usize(0);
85
85
  while(i < len, i = (i + usize(4)), {
86
- c0 := _decode_char(s.bytes(i), alpha);
86
+ c0 := _decode_char(s.bytes(i), alpha, exn);
87
87
  c1 := cond(
88
- ((i + usize(1)) < len) => _decode_char(s.bytes(i + usize(1)), alpha),
88
+ ((i + usize(1)) < len) => _decode_char(s.bytes(i + usize(1)), alpha, exn),
89
89
  true => u8(0)
90
90
  );
91
91
  out.push((c0 << u8(2)) | (c1 >> u8(4)));
92
92
  cond(
93
93
  ((i + usize(2)) < len) => {
94
- c2 := _decode_char(s.bytes(i + usize(2)), alpha);
94
+ c2 := _decode_char(s.bytes(i + usize(2)), alpha, exn);
95
95
  out.push(((c1 & u8(15)) << u8(4)) | (c2 >> u8(2)));
96
96
  cond(
97
97
  ((i + usize(3)) < len) => {
98
- c3 := _decode_char(s.bytes(i + usize(3)), alpha);
98
+ c3 := _decode_char(s.bytes(i + usize(3)), alpha, exn);
99
99
  out.push(((c2 & u8(3)) << u8(6)) | c3);
100
100
  },
101
101
  true => ()
@@ -107,12 +107,12 @@ _decode_with :: (fn(s : str, alpha : str, using(exn : Exception)) -> ArrayList(u
107
107
  out
108
108
  });
109
109
  /// Decode a standard base64 string to bytes. Throws via `Exception` on invalid input.
110
- base64_decode :: (fn(s : str, using(exn : Exception)) -> ArrayList(u8))(
111
- _decode_with(s, _STD_ALPHA)
110
+ base64_decode :: (fn(s : str, exn : Exception) -> ArrayList(u8))(
111
+ _decode_with(s, _STD_ALPHA, exn)
112
112
  );
113
113
  /// Decode a URL-safe base64 string to bytes. Throws via `Exception` on invalid input.
114
- base64_decode_url :: (fn(s : str, using(exn : Exception)) -> ArrayList(u8))(
115
- _decode_with(s, _URL_ALPHA)
114
+ base64_decode_url :: (fn(s : str, exn : Exception) -> ArrayList(u8))(
115
+ _decode_with(s, _URL_ALPHA, exn)
116
116
  );
117
117
  export(base64_decode, base64_decode_url);
118
118
  // ============================================================================
@@ -152,11 +152,11 @@ base64_decode_string :: (fn(input : String) -> Result(String, String))({
152
152
  });
153
153
  // Strip trailing padding
154
154
  len := cleaned.len();
155
- while((len > usize(0)) && (cleaned.get(len - usize(1)).unwrap() == u8(61)), len = (len - usize(1)), ());
155
+ while((len > usize(0)) && (cleaned(len - usize(1)) == u8(61)), len = (len - usize(1)), ());
156
156
  out := ArrayList(u8).new();
157
157
  j := usize(0);
158
158
  while(j < len, j = (j + usize(4)), {
159
- v0 := _base64_index(cleaned.get(j).unwrap());
159
+ v0 := _base64_index(cleaned(j));
160
160
  cond(
161
161
  (v0 == i32(-(1))) => {
162
162
  return(.Err(`Invalid base64 input`));
@@ -165,7 +165,7 @@ base64_decode_string :: (fn(input : String) -> Result(String, String))({
165
165
  );
166
166
  v1 := cond(
167
167
  ((j + usize(1)) < len) => {
168
- tmp := _base64_index(cleaned.get(j + usize(1)).unwrap());
168
+ tmp := _base64_index(cleaned(j + usize(1)));
169
169
  cond(
170
170
  (tmp == i32(-(1))) => {
171
171
  return(.Err(`Invalid base64 input`));
@@ -179,7 +179,7 @@ base64_decode_string :: (fn(input : String) -> Result(String, String))({
179
179
  out.push(u8((v0 << i32(2)) | (v1 >> i32(4))));
180
180
  cond(
181
181
  ((j + usize(2)) < len) => {
182
- v2 := _base64_index(cleaned.get(j + usize(2)).unwrap());
182
+ v2 := _base64_index(cleaned(j + usize(2)));
183
183
  cond(
184
184
  (v2 == i32(-(1))) => {
185
185
  return(.Err(`Invalid base64 input`));
@@ -189,7 +189,7 @@ base64_decode_string :: (fn(input : String) -> Result(String, String))({
189
189
  out.push(u8(((v1 & i32(15)) << i32(4)) | (v2 >> i32(2))));
190
190
  cond(
191
191
  ((j + usize(3)) < len) => {
192
- v3 := _base64_index(cleaned.get(j + usize(3)).unwrap());
192
+ v3 := _base64_index(cleaned(j + usize(3)));
193
193
  cond(
194
194
  (v3 == i32(-(1))) => {
195
195
  return(.Err(`Invalid base64 input`));