@shd101wyy/yo 0.1.29 → 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 (174) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +3 -3
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +19 -11
  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/syntax-cheatsheet.md +59 -21
  6. package/README.md +4 -3
  7. package/out/cjs/index.cjs +771 -676
  8. package/out/cjs/yo-cli.cjs +1003 -898
  9. package/out/cjs/yo-lsp.cjs +834 -739
  10. package/out/esm/index.mjs +716 -621
  11. package/out/types/src/codegen/exprs/async.d.ts +2 -0
  12. package/out/types/src/codegen/exprs/await.d.ts +1 -0
  13. package/out/types/src/codegen/exprs/closures.d.ts +4 -0
  14. package/out/types/src/codegen/functions/context.d.ts +6 -0
  15. package/out/types/src/env.d.ts +2 -0
  16. package/out/types/src/evaluator/builtins/pragma.d.ts +9 -0
  17. package/out/types/src/evaluator/builtins/unsafe.d.ts +8 -0
  18. package/out/types/src/evaluator/context.d.ts +2 -0
  19. package/out/types/src/evaluator/index.d.ts +1 -1
  20. package/out/types/src/evaluator/memory-safety.d.ts +14 -0
  21. package/out/types/src/evaluator/types/flowability.d.ts +6 -0
  22. package/out/types/src/expr-traversal.d.ts +1 -0
  23. package/out/types/src/expr.d.ts +4 -1
  24. package/out/types/src/public-safe-report.d.ts +19 -0
  25. package/out/types/src/tests/comptime-ref-gate.test.d.ts +1 -0
  26. package/out/types/src/tests/pragma-validation.test.d.ts +1 -0
  27. package/out/types/src/tests/public-safe-report.test.d.ts +1 -0
  28. package/out/types/src/tests/type-representation-pointer.test.d.ts +1 -0
  29. package/out/types/src/tests/unsafe-gate.test.d.ts +1 -0
  30. package/out/types/src/tests/unsafe-report-classify.test.d.ts +1 -0
  31. package/out/types/src/types/definitions.d.ts +2 -0
  32. package/out/types/src/types/utils.d.ts +4 -0
  33. package/out/types/src/unsafe-report.d.ts +29 -0
  34. package/out/types/src/value.d.ts +1 -0
  35. package/out/types/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +1 -1
  37. package/scripts/add-pragma-for-pointer-decls.ts +134 -0
  38. package/scripts/add-pragma.ts +58 -0
  39. package/scripts/migrate-amp-method-calls.ts +186 -0
  40. package/scripts/migrate-clone-calls.ts +93 -0
  41. package/scripts/migrate-get-unwrap.ts +166 -0
  42. package/scripts/migrate-index-patterns.ts +210 -0
  43. package/scripts/migrate-index-trait.ts +142 -0
  44. package/scripts/migrate-iterator.ts +150 -0
  45. package/scripts/migrate-self-ptr.ts +220 -0
  46. package/scripts/migrate-skip-pragmas.ts +109 -0
  47. package/scripts/migrate-tostring.ts +134 -0
  48. package/scripts/trim-pragma.ts +130 -0
  49. package/scripts/wrap-extern-calls.ts +161 -0
  50. package/std/alg/hash.yo +3 -2
  51. package/std/allocator.yo +6 -5
  52. package/std/async.yo +2 -2
  53. package/std/collections/array_list.yo +59 -40
  54. package/std/collections/btree_map.yo +19 -18
  55. package/std/collections/deque.yo +9 -8
  56. package/std/collections/hash_map.yo +101 -13
  57. package/std/collections/hash_set.yo +5 -4
  58. package/std/collections/linked_list.yo +39 -4
  59. package/std/collections/ordered_map.yo +3 -3
  60. package/std/collections/priority_queue.yo +14 -13
  61. package/std/crypto/md5.yo +2 -1
  62. package/std/crypto/random.yo +16 -15
  63. package/std/crypto/sha256.yo +2 -1
  64. package/std/encoding/base64.yo +14 -14
  65. package/std/encoding/hex.yo +3 -3
  66. package/std/encoding/json.yo +59 -10
  67. package/std/encoding/punycode.yo +24 -23
  68. package/std/encoding/toml.yo +4 -3
  69. package/std/encoding/utf16.yo +2 -2
  70. package/std/env.yo +43 -28
  71. package/std/error.yo +6 -6
  72. package/std/fmt/display.yo +2 -2
  73. package/std/fmt/index.yo +6 -5
  74. package/std/fmt/to_string.yo +39 -38
  75. package/std/fmt/writer.yo +9 -8
  76. package/std/fs/dir.yo +34 -33
  77. package/std/fs/file.yo +52 -51
  78. package/std/fs/metadata.yo +10 -9
  79. package/std/fs/temp.yo +24 -13
  80. package/std/fs/walker.yo +10 -9
  81. package/std/gc.yo +1 -0
  82. package/std/glob.yo +7 -7
  83. package/std/http/client.yo +15 -14
  84. package/std/http/http.yo +6 -6
  85. package/std/http/index.yo +1 -1
  86. package/std/imm/list.yo +33 -0
  87. package/std/imm/map.yo +2 -1
  88. package/std/imm/set.yo +1 -0
  89. package/std/imm/sorted_map.yo +1 -0
  90. package/std/imm/sorted_set.yo +1 -0
  91. package/std/imm/string.yo +27 -23
  92. package/std/imm/vec.yo +18 -2
  93. package/std/io/reader.yo +2 -1
  94. package/std/io/writer.yo +3 -2
  95. package/std/libc/assert.yo +1 -0
  96. package/std/libc/ctype.yo +1 -0
  97. package/std/libc/dirent.yo +1 -0
  98. package/std/libc/errno.yo +1 -0
  99. package/std/libc/fcntl.yo +1 -0
  100. package/std/libc/float.yo +1 -0
  101. package/std/libc/limits.yo +1 -0
  102. package/std/libc/math.yo +1 -0
  103. package/std/libc/signal.yo +1 -0
  104. package/std/libc/stdatomic.yo +1 -0
  105. package/std/libc/stdint.yo +1 -0
  106. package/std/libc/stdio.yo +1 -0
  107. package/std/libc/stdlib.yo +1 -0
  108. package/std/libc/string.yo +1 -0
  109. package/std/libc/sys/stat.yo +1 -0
  110. package/std/libc/time.yo +1 -0
  111. package/std/libc/unistd.yo +1 -0
  112. package/std/libc/wctype.yo +1 -0
  113. package/std/libc/windows.yo +2 -0
  114. package/std/log.yo +7 -6
  115. package/std/net/addr.yo +5 -4
  116. package/std/net/dns.yo +7 -6
  117. package/std/net/errors.yo +8 -8
  118. package/std/net/tcp.yo +19 -18
  119. package/std/net/udp.yo +13 -12
  120. package/std/os/signal.yo +3 -3
  121. package/std/path.yo +1 -0
  122. package/std/prelude.yo +353 -182
  123. package/std/process/command.yo +40 -23
  124. package/std/process/index.yo +2 -1
  125. package/std/regex/compiler.yo +10 -9
  126. package/std/regex/index.yo +41 -41
  127. package/std/regex/match.yo +2 -2
  128. package/std/regex/parser.yo +21 -21
  129. package/std/regex/vm.yo +42 -41
  130. package/std/string/string.yo +95 -40
  131. package/std/string/string_builder.yo +9 -9
  132. package/std/string/unicode.yo +50 -49
  133. package/std/sync/channel.yo +2 -1
  134. package/std/sync/cond.yo +5 -4
  135. package/std/sync/mutex.yo +4 -3
  136. package/std/sys/advise.yo +1 -0
  137. package/std/sys/bufio/buf_reader.yo +17 -16
  138. package/std/sys/bufio/buf_writer.yo +10 -9
  139. package/std/sys/clock.yo +1 -0
  140. package/std/sys/copy.yo +1 -0
  141. package/std/sys/dir.yo +10 -9
  142. package/std/sys/dns.yo +6 -5
  143. package/std/sys/errors.yo +11 -11
  144. package/std/sys/events.yo +1 -0
  145. package/std/sys/externs.yo +38 -37
  146. package/std/sys/file.yo +17 -16
  147. package/std/sys/future.yo +4 -3
  148. package/std/sys/iov.yo +1 -0
  149. package/std/sys/mmap.yo +1 -0
  150. package/std/sys/path.yo +1 -0
  151. package/std/sys/perm.yo +2 -1
  152. package/std/sys/pipe.yo +1 -0
  153. package/std/sys/process.yo +5 -4
  154. package/std/sys/signal.yo +1 -0
  155. package/std/sys/socketpair.yo +1 -0
  156. package/std/sys/sockinfo.yo +1 -0
  157. package/std/sys/statfs.yo +2 -1
  158. package/std/sys/statx.yo +1 -0
  159. package/std/sys/sysinfo.yo +1 -0
  160. package/std/sys/tcp.yo +15 -14
  161. package/std/sys/temp.yo +1 -0
  162. package/std/sys/time.yo +2 -1
  163. package/std/sys/timer.yo +6 -6
  164. package/std/sys/tty.yo +2 -1
  165. package/std/sys/udp.yo +13 -12
  166. package/std/sys/unix.yo +12 -11
  167. package/std/testing/bench.yo +4 -3
  168. package/std/thread.yo +7 -6
  169. package/std/time/datetime.yo +18 -15
  170. package/std/time/duration.yo +11 -10
  171. package/std/time/instant.yo +4 -4
  172. package/std/time/sleep.yo +1 -0
  173. package/std/url/index.yo +3 -3
  174. package/std/worker.yo +4 -3
@@ -1,4 +1,5 @@
1
1
  //! Immutable UTF-8 string type with comprehensive operations.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { ArrayList } :: import("../collections/array_list.yo");
3
4
  { rune } :: import("./rune.yo");
4
5
  { memcpy, memcmp, strlen } :: import("../libc/string.yo");
@@ -65,7 +66,12 @@ impl(
65
66
  * Note: We manually search for the null terminator by iterating
66
67
  */
67
68
  from_cstr : (fn(cstr : *(u8)) -> Result(Self, StringError))({
68
- len := strlen((*(char))(cstr));
69
+ // SAFETY: caller's contract — `cstr` must point at a null-terminated byte
70
+ // sequence (the standard C string invariant). `strlen` walks forward until
71
+ // it hits the null byte and returns the count not including it. If the
72
+ // caller passes a non-null-terminated buffer, the read walks past the end;
73
+ // this is the same trust boundary as `<string.h>`'s `strlen`.
74
+ len := unsafe(strlen((*(char))(cstr)));
69
75
  if(len == usize(0), {
70
76
  return(.Ok(Self(_bytes :.None)));
71
77
  });
@@ -321,7 +327,7 @@ impl(
321
327
  return(Self(_bytes :.Some(new_bytes)));
322
328
  }),
323
329
  /// Append another `String` to this string in-place (mutates `self`).
324
- push_string : (fn(self : *(Self), other : Self) -> unit)({
330
+ push_string : (fn(ref(self) : Self, other : Self) -> unit)({
325
331
  (olen : usize) = match(other._bytes,.Some(b) => b.len(),.None => usize(0));
326
332
  if(olen > usize(0), {
327
333
  match(
@@ -330,11 +336,11 @@ impl(
330
336
  ob.ptr(),
331
337
  .Some(p) => {
332
338
  match(
333
- self.*._bytes,
339
+ self._bytes,
334
340
  .None => {
335
341
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(olen);
336
342
  new_al.extend_from_ptr(p, olen);
337
- self.*._bytes =.Some(new_al);
343
+ self._bytes =.Some(new_al);
338
344
  },
339
345
  .Some(al) => {
340
346
  al.extend_from_ptr(p, olen);
@@ -348,15 +354,15 @@ impl(
348
354
  });
349
355
  }),
350
356
  /// Append a `str` slice to this string in-place (mutates `self`).
351
- push_str : (fn(self : *(Self), s : str) -> unit)({
357
+ push_str : (fn(ref(self) : Self, s : str) -> unit)({
352
358
  (slen : usize) = s.len();
353
359
  if(slen > usize(0), {
354
360
  match(
355
- self.*._bytes,
361
+ self._bytes,
356
362
  .None => {
357
363
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(slen);
358
364
  new_al.extend_from_ptr(s.ptr(), slen);
359
- self.*._bytes =.Some(new_al);
365
+ self._bytes =.Some(new_al);
360
366
  },
361
367
  .Some(al) => {
362
368
  al.extend_from_ptr(s.ptr(), slen);
@@ -366,13 +372,13 @@ impl(
366
372
  }),
367
373
  /// Append a single byte to this string in-place (mutates `self`).
368
374
  /// The caller must ensure the byte maintains valid UTF-8.
369
- push_byte : (fn(self : *(Self), b : u8) -> unit)({
375
+ push_byte : (fn(ref(self) : Self, b : u8) -> unit)({
370
376
  match(
371
- self.*._bytes,
377
+ self._bytes,
372
378
  .None => {
373
379
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(usize(8));
374
380
  new_al.push(b);
375
- self.*._bytes =.Some(new_al);
381
+ self._bytes =.Some(new_al);
376
382
  },
377
383
  .Some(al) => {
378
384
  al.push(b);
@@ -381,11 +387,11 @@ impl(
381
387
  }),
382
388
  /// Reserve capacity for at least `additional` more bytes.
383
389
  /// If the string is empty, creates a new buffer with the given capacity.
384
- reserve : (fn(self : *(Self), additional : usize) -> unit)({
390
+ reserve : (fn(ref(self) : Self, additional : usize) -> unit)({
385
391
  match(
386
- self.*._bytes,
392
+ self._bytes,
387
393
  .None => {
388
- self.*._bytes =.Some(ArrayList(u8).with_capacity(additional));
394
+ self._bytes =.Some(ArrayList(u8).with_capacity(additional));
389
395
  },
390
396
  .Some(al) => {
391
397
  (current_len : usize) = al.len();
@@ -394,29 +400,16 @@ impl(
394
400
  );
395
401
  }),
396
402
  /// Clear the string content but keep the allocated buffer for reuse.
397
- clear : (fn(self : *(Self)) -> unit)(
403
+ clear : (fn(ref(self) : Self) -> unit)(
398
404
  match(
399
- self.*._bytes,
405
+ self._bytes,
400
406
  .Some(al) => al.clear(),
401
407
  .None => ()
402
408
  )
403
409
  ),
404
- /// Create a deep copy of this string with its own buffer.
405
- clone : (fn(self : Self) -> Self)(
406
- match(
407
- self._bytes,
408
- .None => Self(_bytes :.None),
409
- .Some(al) => {
410
- (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(al.len());
411
- match(
412
- al.ptr(),
413
- .Some(p) => new_al.extend_from_ptr(p, al.len()),
414
- .None => ()
415
- );
416
- Self(_bytes :.Some(new_al))
417
- }
418
- )
419
- ),
410
+ // (Inherent `clone` removed; the Clone trait impl below provides
411
+ // the same semantics via ref(self) : Self after the Phase D
412
+ // migration. Calling `s.clone()` resolves to the trait method.)
420
413
  /// Get the number of bytes in the string (not Unicode characters).
421
414
  /// Use `len()` for Unicode character count.
422
415
  bytes_len : (fn(self : Self) -> usize)(
@@ -1399,8 +1392,13 @@ impl(
1399
1392
  .Some(self_ptr) =>
1400
1393
  match(
1401
1394
  other_al.ptr(),
1395
+ // SAFETY: self_len equals other_len (checked
1396
+ // above) and both equal each ArrayList's
1397
+ // .len() (the inner Option's ptr is Some only
1398
+ // when len > 0); memcmp reads exactly that many
1399
+ // bytes from each Rc-managed buffer.
1402
1400
  .Some(other_ptr) =>
1403
- (memcmp((*(void))(self_ptr), (*(void))(other_ptr), self_len) == int(0)),
1401
+ (unsafe(memcmp((*(void))(self_ptr), (*(void))(other_ptr), self_len)) == int(0)),
1404
1402
  .None => false
1405
1403
  ),
1406
1404
  .None => false
@@ -1420,10 +1418,10 @@ impl(
1420
1418
  impl(
1421
1419
  String,
1422
1420
  Hash(
1423
- (hash) : (fn(self : *(Self)) -> u64)({
1421
+ (hash) : (fn(ref(self) : Self) -> u64)({
1424
1422
  h := u64(14695981039346656037);
1425
1423
  match(
1426
- self.*._bytes,
1424
+ self._bytes,
1427
1425
  .None => (),
1428
1426
  .Some(al) => {
1429
1427
  i := usize(0);
@@ -1457,7 +1455,7 @@ impl(
1457
1455
  StringChars,
1458
1456
  Iterator(
1459
1457
  Item : rune,
1460
- next : (fn(self : *(Self)) -> Option(rune))(
1458
+ next : (fn(ref(self) : Self) -> Option(rune))(
1461
1459
  match(
1462
1460
  self._string._bytes,
1463
1461
  .None =>.None,
@@ -1499,7 +1497,7 @@ impl(
1499
1497
  StringBytes,
1500
1498
  Iterator(
1501
1499
  Item : u8,
1502
- next : (fn(self : *(Self)) -> Option(u8))(
1500
+ next : (fn(ref(self) : Self) -> Option(u8))(
1503
1501
  match(
1504
1502
  self._string._bytes,
1505
1503
  .None =>.None,
@@ -1515,6 +1513,31 @@ impl(
1515
1513
  )
1516
1514
  )
1517
1515
  );
1516
+ /// Byte-position iterator for `String` — yields `usize` byte indices.
1517
+ /// Used by `String.iter()`; the for-macro pairs each yielded position
1518
+ /// with `String.project(pos)` (Indexable from Phase C) to bind the
1519
+ /// body's `ref`-name to a byte in `self._bytes.Some`. See
1520
+ /// plans/ITERATOR_REDESIGN.md.
1521
+ _StringPosIter :: struct(
1522
+ _index : usize,
1523
+ _len : usize
1524
+ );
1525
+ impl(
1526
+ _StringPosIter,
1527
+ Iterator(
1528
+ Item : usize,
1529
+ next : (fn(ref(self) : Self) -> Option(usize))(
1530
+ cond(
1531
+ (self._index >= self._len) =>.None,
1532
+ true => {
1533
+ out := self._index;
1534
+ self._index = (self._index + usize(1));
1535
+ .Some(out)
1536
+ }
1537
+ )
1538
+ )
1539
+ )
1540
+ );
1518
1541
  impl(
1519
1542
  String,
1520
1543
  /**
@@ -1529,6 +1552,17 @@ impl(
1529
1552
  bytes : (fn(self : Self) -> StringBytes)(
1530
1553
  StringBytes(_string : self, _index : usize(0))
1531
1554
  ),
1555
+ /// Byte-position iterator for `for(s, ref(b) => body)`. Yields
1556
+ /// `usize` byte indices; the for-macro pairs each with
1557
+ /// `s.project(pos)` (Indexable) so the body sees `ref(u8)` bound
1558
+ /// to each byte. Iteration is byte-level, not rune-level — for
1559
+ /// codepoint iteration use `chars()` explicitly.
1560
+ iter : (fn(ref(self) : Self) -> _StringPosIter)(
1561
+ _StringPosIter(
1562
+ _index : usize(0),
1563
+ _len : match(self._bytes,.Some(b) => b.len(),.None => usize(0))
1564
+ )
1565
+ ),
1532
1566
  /**
1533
1567
  * Consume the string and return a rune iterator (default iteration)
1534
1568
  */
@@ -1550,7 +1584,7 @@ impl(
1550
1584
  StringLines,
1551
1585
  Iterator(
1552
1586
  Item : String,
1553
- next : (fn(self : *(Self)) -> Option(String))(
1587
+ next : (fn(ref(self) : Self) -> Option(String))(
1554
1588
  match(
1555
1589
  self._string._bytes,
1556
1590
  .None =>.None,
@@ -2114,20 +2148,41 @@ impl(
2114
2148
  String,
2115
2149
  Index(usize)(
2116
2150
  Output : u8,
2117
- index : (fn(self : *(Self), idx : usize) -> *(Self.Output))(
2151
+ index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))(
2118
2152
  match(
2119
- self.*._bytes,
2153
+ self._bytes,
2120
2154
  .Some(bytes) => &(bytes(idx)),
2121
2155
  .None => panic("String: index on empty string")
2122
2156
  )
2123
2157
  )
2124
2158
  )
2125
2159
  );
2160
+ /// String Indexable impl — projection-style byte access yielding
2161
+ /// `ref(u8)`. Body uses `unsafe(...)` because `&(bytes(pos))` produces
2162
+ /// a raw `*(u8)` borrow into `self._bytes.Some.bytes` storage; the
2163
+ /// `unsafe` wrap is the trusted escape from the flowability rule
2164
+ /// (privileged code only). See plans/ITERATOR_REDESIGN.md.
2165
+ impl(
2166
+ String,
2167
+ Indexable(usize)(
2168
+ Element : u8,
2169
+ project : (fn(ref(self) : Self, pos : usize) -> ref(u8))(
2170
+ match(
2171
+ self._bytes,
2172
+ // SAFETY: `pos < self.len()` is the precondition; the `_bytes` is the
2173
+ // String's own owned ArrayList whose `data[pos]` lives as long as the
2174
+ // ref-bound `self`. `bytes(pos)` is auto-bounds-checked by ArrayList.project.
2175
+ .Some(bytes) => unsafe(&(bytes(pos))),
2176
+ .None => panic("String: project on empty string")
2177
+ )
2178
+ )
2179
+ )
2180
+ );
2126
2181
  /// Clone implementation — produces an independent byte-level copy.
2127
2182
  impl(
2128
2183
  String,
2129
2184
  Clone(
2130
- clone : (fn(self : *(Self)) -> Self)(
2185
+ clone : (fn(ref(self) : Self) -> Self)(
2131
2186
  match(
2132
2187
  self._bytes,
2133
2188
  .None => Self(_bytes :.None),
@@ -40,19 +40,19 @@ impl(
40
40
  /**
41
41
  * Returns the current number of bytes in the buffer.
42
42
  */
43
- len : (fn(self : *(Self)) -> usize)(
43
+ len : (fn(self : Self) -> usize)(
44
44
  self._buf.len()
45
45
  ),
46
46
  /**
47
47
  * Returns true if the buffer is empty.
48
48
  */
49
- is_empty : (fn(self : *(Self)) -> bool)(
49
+ is_empty : (fn(self : Self) -> bool)(
50
50
  self._buf.len() == usize(0)
51
51
  ),
52
52
  /**
53
53
  * Append a `str` (raw byte slice) to the buffer.
54
54
  */
55
- write_str : (fn(self : *(Self), s : str) -> unit)({
55
+ write_str : (fn(self : Self, s : str) -> unit)({
56
56
  byte_len := s.len();
57
57
  if(byte_len > usize(0), {
58
58
  self._buf.extend_from_ptr(s.ptr(), byte_len);
@@ -61,7 +61,7 @@ impl(
61
61
  /**
62
62
  * Append a `String` to the buffer.
63
63
  */
64
- write_string : (fn(self : *(Self), s : String) -> unit)(
64
+ write_string : (fn(self : Self, s : String) -> unit)(
65
65
  match(
66
66
  s._bytes,
67
67
  .None => (),
@@ -84,7 +84,7 @@ impl(
84
84
  /**
85
85
  * Append a single byte to the buffer.
86
86
  */
87
- write_byte : (fn(self : *(Self), b : u8) -> unit)({
87
+ write_byte : (fn(self : Self, b : u8) -> unit)({
88
88
  self._buf.push(b);
89
89
  }),
90
90
  /**
@@ -97,7 +97,7 @@ impl(
97
97
  * sb.write_rune(rune(0x41)); // 'A'
98
98
  * ```
99
99
  */
100
- write_rune : (fn(self : *(Self), r : rune) -> unit)({
100
+ write_rune : (fn(self : Self, r : rune) -> unit)({
101
101
  cp := r.char;
102
102
  cond(
103
103
  (cp < u32(0x80)) => {
@@ -123,7 +123,7 @@ impl(
123
123
  /**
124
124
  * Append a `String` followed by a newline byte (`\n`).
125
125
  */
126
- write_line : (fn(self : *(Self), s : String) -> unit)({
126
+ write_line : (fn(self : Self, s : String) -> unit)({
127
127
  self.write_string(s);
128
128
  self._buf.push(u8(10));
129
129
  }),
@@ -131,7 +131,7 @@ impl(
131
131
  * Consume the builder and return the accumulated `String`.
132
132
  * The builder is left empty after this call.
133
133
  */
134
- to_string : (fn(self : *(Self)) -> String)({
134
+ to_string : (fn(self : Self) -> String)({
135
135
  n := self._buf.len();
136
136
  cond(
137
137
  (n == usize(0)) => String(_bytes :.None),
@@ -156,7 +156,7 @@ impl(
156
156
  /**
157
157
  * Clear the buffer without freeing memory.
158
158
  */
159
- clear : (fn(self : *(Self)) -> unit)({
159
+ clear : (fn(self : Self) -> unit)({
160
160
  self._buf = ArrayList(u8).new();
161
161
  })
162
162
  );
@@ -8,6 +8,7 @@
8
8
  //! lower := unicode_to_lowercase(`HELLO WÖRLD`); // "hello wörld"
9
9
  //! upper := unicode_to_uppercase(`hello wörld`); // "HELLO WÖRLD"
10
10
  //! ```
11
+ pragma(Pragma.AllowUnsafe);
11
12
  open(import("../string"));
12
13
  { ArrayList } :: import("../collections/array_list");
13
14
  // Declare towlower/towupper directly with i32 to avoid wint_t cast issues.
@@ -26,70 +27,70 @@ _DecodeResult :: struct(
26
27
  );
27
28
  // Decode a single UTF-8 codepoint from bytes at position i.
28
29
  _decode_utf8 :: (fn(bytes : ArrayList(u8), i : usize) -> _DecodeResult)({
29
- (b0 : i32) = i32(bytes.get(i).unwrap());
30
+ (b0 : i32) = i32(bytes(i));
30
31
  cond(
31
32
  // 1-byte ASCII
32
33
  ((b0 & i32(0x80)) == i32(0)) =>
33
34
  _DecodeResult(codepoint : b0, bytes_consumed : usize(1)),
34
35
  // 2-byte
35
36
  ((b0 & i32(0xE0)) == i32(0xC0)) => {
36
- (b1 : i32) = i32(bytes.get(i + usize(1)).unwrap());
37
+ (b1 : i32) = i32(bytes(i + usize(1)));
37
38
  (cp : i32) = (((b0 & i32(0x1F)) << i32(6)) | (b1 & i32(0x3F)));
38
39
  _DecodeResult(codepoint : cp, bytes_consumed : usize(2))
39
40
  },
40
41
  // 3-byte
41
42
  ((b0 & i32(0xF0)) == i32(0xE0)) => {
42
- (b1 : i32) = i32(bytes.get(i + usize(1)).unwrap());
43
- (b2 : i32) = i32(bytes.get(i + usize(2)).unwrap());
43
+ (b1 : i32) = i32(bytes(i + usize(1)));
44
+ (b2 : i32) = i32(bytes(i + usize(2)));
44
45
  (cp : i32) = ((((b0 & i32(0x0F)) << i32(12)) | ((b1 & i32(0x3F)) << i32(6))) | (b2 & i32(0x3F)));
45
46
  _DecodeResult(codepoint : cp, bytes_consumed : usize(3))
46
47
  },
47
48
  // 4-byte
48
49
  true => {
49
- (b1 : i32) = i32(bytes.get(i + usize(1)).unwrap());
50
- (b2 : i32) = i32(bytes.get(i + usize(2)).unwrap());
51
- (b3 : i32) = i32(bytes.get(i + usize(3)).unwrap());
50
+ (b1 : i32) = i32(bytes(i + usize(1)));
51
+ (b2 : i32) = i32(bytes(i + usize(2)));
52
+ (b3 : i32) = i32(bytes(i + usize(3)));
52
53
  (cp : i32) = (((((b0 & i32(0x07)) << i32(18)) | ((b1 & i32(0x3F)) << i32(12))) | ((b2 & i32(0x3F)) << i32(6))) | (b3 & i32(0x3F)));
53
54
  _DecodeResult(codepoint : cp, bytes_consumed : usize(4))
54
55
  }
55
56
  )
56
57
  });
57
58
  // Encode a Unicode codepoint as UTF-8 bytes into an ArrayList.
58
- _encode_utf8 :: (fn(cp : i32, out : *(ArrayList(u8))) -> unit)({
59
+ _encode_utf8 :: (fn(cp : i32, out : ArrayList(u8)) -> unit)({
59
60
  cond(
60
61
  (cp < i32(0x80)) => {
61
- out.*.push(u8(cp));
62
+ out.push(u8(cp));
62
63
  },
63
64
  (cp < i32(0x800)) => {
64
- out.*.push(u8(i32(0xC0) | (cp >> i32(6))));
65
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
65
+ out.push(u8(i32(0xC0) | (cp >> i32(6))));
66
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
66
67
  },
67
68
  (cp < i32(0x10000)) => {
68
- out.*.push(u8(i32(0xE0) | (cp >> i32(12))));
69
- out.*.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
70
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
69
+ out.push(u8(i32(0xE0) | (cp >> i32(12))));
70
+ out.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
71
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
71
72
  },
72
73
  true => {
73
- out.*.push(u8(i32(0xF0) | (cp >> i32(18))));
74
- out.*.push(u8(i32(0x80) | ((cp >> i32(12)) & i32(0x3F))));
75
- out.*.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
76
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
74
+ out.push(u8(i32(0xF0) | (cp >> i32(18))));
75
+ out.push(u8(i32(0x80) | ((cp >> i32(12)) & i32(0x3F))));
76
+ out.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
77
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
77
78
  }
78
79
  );
79
80
  });
80
81
  // Special case folding: codepoints that expand to multiple codepoints
81
82
  // when lowercased. These are Unicode case folding entries of type 'F' (full).
82
- _special_to_lower :: (fn(cp : i32, out : *(ArrayList(u8))) -> bool)(
83
+ _special_to_lower :: (fn(cp : i32, out : ArrayList(u8)) -> bool)(
83
84
  cond(
84
85
  // ẞ (U+1E9E LATIN CAPITAL LETTER SHARP S) → ss
85
86
  (cp == i32(0x1E9E)) => {
86
- out.*.push(u8(0x73)); // s
87
- out.*.push(u8(0x73)); // s
87
+ out.push(u8(0x73)); // s
88
+ out.push(u8(0x73)); // s
88
89
  true
89
90
  },
90
91
  // İ (U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE) → i + combining dot above
91
92
  (cp == i32(0x0130)) => {
92
- out.*.push(u8(0x69)); // i
93
+ out.push(u8(0x69)); // i
93
94
  // U+0307 COMBINING DOT ABOVE
94
95
  _encode_utf8(i32(0x0307), out);
95
96
  true
@@ -99,56 +100,56 @@ _special_to_lower :: (fn(cp : i32, out : *(ArrayList(u8))) -> bool)(
99
100
  );
100
101
  // Special case folding: codepoints that expand to multiple codepoints
101
102
  // when uppercased.
102
- _special_to_upper :: (fn(cp : i32, out : *(ArrayList(u8))) -> bool)(
103
+ _special_to_upper :: (fn(cp : i32, out : ArrayList(u8)) -> bool)(
103
104
  cond(
104
105
  // ß (U+00DF LATIN SMALL LETTER SHARP S) → SS
105
106
  (cp == i32(0x00DF)) => {
106
- out.*.push(u8(0x53)); // S
107
- out.*.push(u8(0x53)); // S
107
+ out.push(u8(0x53)); // S
108
+ out.push(u8(0x53)); // S
108
109
  true
109
110
  },
110
111
  // ff (U+FB00 LATIN SMALL LIGATURE FF) → FF
111
112
  (cp == i32(0xFB00)) => {
112
- out.*.push(u8(0x46)); // F
113
- out.*.push(u8(0x46)); // F
113
+ out.push(u8(0x46)); // F
114
+ out.push(u8(0x46)); // F
114
115
  true
115
116
  },
116
117
  // fi (U+FB01 LATIN SMALL LIGATURE FI) → FI
117
118
  (cp == i32(0xFB01)) => {
118
- out.*.push(u8(0x46)); // F
119
- out.*.push(u8(0x49)); // I
119
+ out.push(u8(0x46)); // F
120
+ out.push(u8(0x49)); // I
120
121
  true
121
122
  },
122
123
  // fl (U+FB02 LATIN SMALL LIGATURE FL) → FL
123
124
  (cp == i32(0xFB02)) => {
124
- out.*.push(u8(0x46)); // F
125
- out.*.push(u8(0x4C)); // L
125
+ out.push(u8(0x46)); // F
126
+ out.push(u8(0x4C)); // L
126
127
  true
127
128
  },
128
129
  // ffi (U+FB03 LATIN SMALL LIGATURE FFI) → FFI
129
130
  (cp == i32(0xFB03)) => {
130
- out.*.push(u8(0x46)); // F
131
- out.*.push(u8(0x46)); // F
132
- out.*.push(u8(0x49)); // I
131
+ out.push(u8(0x46)); // F
132
+ out.push(u8(0x46)); // F
133
+ out.push(u8(0x49)); // I
133
134
  true
134
135
  },
135
136
  // ffl (U+FB04 LATIN SMALL LIGATURE FFL) → FFL
136
137
  (cp == i32(0xFB04)) => {
137
- out.*.push(u8(0x46)); // F
138
- out.*.push(u8(0x46)); // F
139
- out.*.push(u8(0x4C)); // L
138
+ out.push(u8(0x46)); // F
139
+ out.push(u8(0x46)); // F
140
+ out.push(u8(0x4C)); // L
140
141
  true
141
142
  },
142
143
  // ſt (U+FB05 LATIN SMALL LIGATURE LONG S T) → ST
143
144
  (cp == i32(0xFB05)) => {
144
- out.*.push(u8(0x53)); // S
145
- out.*.push(u8(0x54)); // T
145
+ out.push(u8(0x53)); // S
146
+ out.push(u8(0x54)); // T
146
147
  true
147
148
  },
148
149
  // st (U+FB06 LATIN SMALL LIGATURE ST) → ST
149
150
  (cp == i32(0xFB06)) => {
150
- out.*.push(u8(0x53)); // S
151
- out.*.push(u8(0x54)); // T
151
+ out.push(u8(0x53)); // S
152
+ out.push(u8(0x54)); // T
152
153
  true
153
154
  },
154
155
  true => false
@@ -162,7 +163,7 @@ unicode_to_lowercase :: (fn(input : String) -> String)({
162
163
  (out : ArrayList(u8)) = ArrayList(u8).with_capacity(bytes.len());
163
164
  (i : usize) = usize(0);
164
165
  while(i < bytes.len(), {
165
- (b0 : i32) = i32(bytes.get(i).unwrap());
166
+ (b0 : i32) = i32(bytes(i));
166
167
  // Fast path for ASCII
167
168
  if((b0 & i32(0x80)) == i32(0), {
168
169
  if((b0 >= i32(0x41)) && (b0 <= i32(0x5A)), {
@@ -177,10 +178,10 @@ unicode_to_lowercase :: (fn(input : String) -> String)({
177
178
  (cp : i32) = result.codepoint;
178
179
  (len : usize) = result.bytes_consumed;
179
180
  // Try special case folding first
180
- if(!(_special_to_lower(cp, &(out))), {
181
+ if(!(_special_to_lower(cp, out)), {
181
182
  // Use C towlower for standard Unicode lowercase
182
- (lower : i32) = i32(towlower(cp));
183
- _encode_utf8(lower, &(out));
183
+ (lower : i32) = i32(unsafe(towlower(cp)));
184
+ _encode_utf8(lower, out);
184
185
  });
185
186
  i = (i + len);
186
187
  });
@@ -195,7 +196,7 @@ unicode_to_uppercase :: (fn(input : String) -> String)({
195
196
  (out : ArrayList(u8)) = ArrayList(u8).with_capacity(bytes.len());
196
197
  (i : usize) = usize(0);
197
198
  while(i < bytes.len(), {
198
- (b0 : i32) = i32(bytes.get(i).unwrap());
199
+ (b0 : i32) = i32(bytes(i));
199
200
  // Fast path for ASCII
200
201
  if((b0 & i32(0x80)) == i32(0), {
201
202
  if((b0 >= i32(0x61)) && (b0 <= i32(0x7A)), {
@@ -210,10 +211,10 @@ unicode_to_uppercase :: (fn(input : String) -> String)({
210
211
  (cp : i32) = result.codepoint;
211
212
  (len : usize) = result.bytes_consumed;
212
213
  // Try special case folding first
213
- if(!(_special_to_upper(cp, &(out))), {
214
+ if(!(_special_to_upper(cp, out)), {
214
215
  // Use C towupper for standard Unicode uppercase
215
- (upper : i32) = i32(towupper(cp));
216
- _encode_utf8(upper, &(out));
216
+ (upper : i32) = i32(unsafe(towupper(cp)));
217
+ _encode_utf8(upper, out);
217
218
  });
218
219
  i = (i + len);
219
220
  });
@@ -1,5 +1,5 @@
1
1
  //! Bounded multi-producer multi-consumer (MPMC) channel.
2
- //! Uses blocking send/recv via condition variables — does not require IO.
2
+ //! Uses blocking send/recv via condition variables — does not require Io.
3
3
  //!
4
4
  //! Channel uses `atomic object` with atomic reference counting, so it can be
5
5
  //! safely shared across threads without `Arc` wrapping.
@@ -18,6 +18,7 @@
18
18
  //! assert((val.unwrap() == i32(42)), "received value");
19
19
  //! t.join();
20
20
  //! ```
21
+ pragma(Pragma.AllowUnsafe);
21
22
  { GlobalAllocator } :: import("../allocator");
22
23
  { malloc, free } :: GlobalAllocator;
23
24
  { Mutex } :: import("./mutex");
package/std/sync/cond.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! Condition variable for thread synchronization.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { __YO_THREAD_SYNC_TYPE, mutex_t, Mutex } :: import("./mutex");
3
4
  extern(
4
5
  "Yo",
@@ -20,16 +21,16 @@ impl(
20
21
  new : (fn() -> Self)({
21
22
  return(Self(__yo_cond_create()));
22
23
  }),
23
- wait : (fn(self : *(Self), mutex : *(mutex_t)) -> unit)({
24
+ wait : (fn(ref(self) : Self, ref(mutex) : mutex_t) -> unit)({
24
25
  return(__yo_cond_wait(&(self.cv), &(mutex.mutex)));
25
26
  }),
26
- signal : (fn(self : *(Self)) -> unit)({
27
+ signal : (fn(ref(self) : Self) -> unit)({
27
28
  return(__yo_cond_signal(&(self.cv)));
28
29
  }),
29
- broadcast : (fn(self : *(Self)) -> unit)({
30
+ broadcast : (fn(ref(self) : Self) -> unit)({
30
31
  return(__yo_cond_broadcast(&(self.cv)));
31
32
  }),
32
- destroy : (fn(self : *(Self)) -> unit)({
33
+ destroy : (fn(ref(self) : Self) -> unit)({
33
34
  return(__yo_cond_destroy(&(self.cv)));
34
35
  })
35
36
  );
package/std/sync/mutex.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! Mutual exclusion lock primitives.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  extern(
3
4
  "Yo",
4
5
  __YO_THREAD_SYNC_TYPE : Type,
@@ -18,13 +19,13 @@ impl(
18
19
  new : (fn() -> Self)({
19
20
  return(Self(__yo_mutex_create()));
20
21
  }),
21
- lock : (fn(self : *(Self)) -> unit)({
22
+ lock : (fn(ref(self) : Self) -> unit)({
22
23
  return(__yo_mutex_lock(&(self.mutex)));
23
24
  }),
24
- unlock : (fn(self : *(Self)) -> unit)({
25
+ unlock : (fn(ref(self) : Self) -> unit)({
25
26
  return(__yo_mutex_unlock(&(self.mutex)));
26
27
  }),
27
- destroy : (fn(self : *(Self)) -> unit)({
28
+ destroy : (fn(ref(self) : Self) -> unit)({
28
29
  return(__yo_mutex_destroy(&(self.mutex)));
29
30
  })
30
31
  );
package/std/sys/advise.yo CHANGED
@@ -2,6 +2,7 @@
2
2
  //!
3
3
  //! Advisory wrappers for file and memory access pattern hints.
4
4
  //! Returns 0 on success, -errno / negative platform error on failure.
5
+ pragma(Pragma.AllowUnsafe);
5
6
  { __yo_sync_fadvise, __yo_sync_madvise } :: import("./externs.yo");
6
7
  POSIX_FADV_NORMAL :: i32(0);
7
8
  POSIX_FADV_RANDOM :: i32(1);