@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
package/std/glob.yo CHANGED
@@ -17,12 +17,12 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
17
17
  },
18
18
  true => ()
19
19
  );
20
- p := pb.get(pi).unwrap();
20
+ p := pb(pi);
21
21
  // Handle * and **
22
22
  cond(
23
23
  (p == u8(42)) => {
24
24
  is_dbl := cond(
25
- ((pi + usize(1)) < pb.len()) => (pb.get(pi + usize(1)).unwrap() == u8(42)),
25
+ ((pi + usize(1)) < pb.len()) => (pb(pi + usize(1)) == u8(42)),
26
26
  true => false
27
27
  );
28
28
  cond(
@@ -33,7 +33,7 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
33
33
  cond(
34
34
  (npi < pb.len()) => {
35
35
  cond(
36
- (pb.get(npi).unwrap() == u8(47)) => {
36
+ (pb(npi) == u8(47)) => {
37
37
  npi = (npi + usize(1));
38
38
  },
39
39
  true => ()
@@ -70,7 +70,7 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
70
70
  // Try * consuming one non-/ char
71
71
  cond(
72
72
  (ti < tb.len()) => {
73
- tc := tb.get(ti).unwrap();
73
+ tc := tb(ti);
74
74
  cond(
75
75
  (tc != u8(47)) => {
76
76
  return(recur(pb, pi, tb, ti + usize(1)));
@@ -96,7 +96,7 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
96
96
  },
97
97
  true => ()
98
98
  );
99
- t := tb.get(ti).unwrap();
99
+ t := tb(ti);
100
100
  // Handle ?
101
101
  cond(
102
102
  (p == u8(63)) => {
@@ -119,7 +119,7 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
119
119
  // Check for negation: ! or ^
120
120
  cond(
121
121
  (ci < pb.len()) => {
122
- nc := pb.get(ci).unwrap();
122
+ nc := pb(ci);
123
123
  cond(
124
124
  ((nc == u8(33)) || (nc == u8(94))) => {
125
125
  neg = true;
@@ -134,7 +134,7 @@ _glob_match_impl :: (fn(pb : ArrayList(u8), pi : usize, tb : ArrayList(u8), ti :
134
134
  found := false;
135
135
  cdone := false;
136
136
  while((ci < pb.len()) && (!(cdone)), ci = (ci + usize(1)), {
137
- ch := pb.get(ci).unwrap();
137
+ ch := pb(ci);
138
138
  cond(
139
139
  (ch == u8(93)) => {
140
140
  cdone = true;
@@ -8,16 +8,17 @@
8
8
  // { fetch, HttpResponse } :: import "std/http";
9
9
  // { Exception } :: import "std/error";
10
10
  //
11
- // main :: (fn(io : IO, exn : Exception) -> unit)({
11
+ // main :: (fn(io : Io, exn : Exception) -> unit)({
12
12
  // resp := io.await(fetch(`http://example.com/api/data`, io), { io, exn });
13
13
  // println(resp.body);
14
14
  // });
15
+ pragma(Pragma.AllowUnsafe);
15
16
  open(import("../string"));
16
17
  { ArrayList } :: import("../collections/array_list");
17
18
  { GlobalAllocator } :: import("../allocator");
18
19
  { malloc, free } :: GlobalAllocator;
19
20
  open(import("../fmt"));
20
- { Error, AnyError, Exception, IOErr } :: import("../error");
21
+ { Error, AnyError, Exception, IoExn } :: import("../error");
21
22
  { TcpStream } :: import("../net/tcp");
22
23
  { IpAddr, SocketAddr } :: import("../net/addr");
23
24
  { lookup_host } :: import("../net/dns");
@@ -116,12 +117,12 @@ _find_header_end :: (fn(data : ArrayList(u8)) -> usize)({
116
117
  while(runtime(i < limit), {
117
118
  cond(
118
119
  (
119
- (data.get(i).unwrap() == u8(13)) &&
120
+ (data(i) == u8(13)) &&
120
121
  (
121
- (data.get(i + usize(1)).unwrap() == u8(10)) &&
122
+ (data(i + usize(1)) == u8(10)) &&
122
123
  (
123
- (data.get(i + usize(2)).unwrap() == u8(13)) &&
124
- (data.get(i + usize(3)).unwrap() == u8(10))
124
+ (data(i + usize(2)) == u8(13)) &&
125
+ (data(i + usize(3)) == u8(10))
125
126
  )
126
127
  )
127
128
  ) => {
@@ -139,7 +140,7 @@ _find_content_length :: (fn(data : ArrayList(u8), header_end : usize) -> i32)({
139
140
  header_bytes := ArrayList(u8).new();
140
141
  i := usize(0);
141
142
  while(runtime(i < header_end), {
142
- header_bytes.push(data.get(i).unwrap());
143
+ header_bytes.push(data(i));
143
144
  i = (i + usize(1));
144
145
  });
145
146
  header_str := String.from_bytes(header_bytes).to_lowercase();
@@ -175,7 +176,7 @@ _find_content_length :: (fn(data : ArrayList(u8), header_end : usize) -> i32)({
175
176
  // ============================================================================
176
177
  // Internal: read full HTTP response from a TCP stream
177
178
  // ============================================================================
178
- _read_http_response :: (fn(stream : TcpStream, e : IOErr) -> String)({
179
+ _read_http_response :: (fn(stream : TcpStream, e : IoExn) -> String)({
179
180
  buf_size := usize(8192);
180
181
  buf := *(u8)(malloc(buf_size).unwrap());
181
182
  result := ArrayList(u8).new();
@@ -242,8 +243,8 @@ _read_http_response :: (fn(stream : TcpStream, e : IOErr) -> String)({
242
243
  /// resp := io.await(fetch_with(`http://example.com/api`, opts, io), { io, exn });
243
244
  /// ```
244
245
  fetch_with :: (
245
- fn(url_str : String, opts : FetchOptions, io : IO) ->
246
- Impl(Future(HttpResponse, IOErr))
246
+ fn(url_str : String, opts : FetchOptions, io : Io) ->
247
+ Impl(Future(HttpResponse, IoExn))
247
248
  )(
248
249
  io.async((e) => {
249
250
  // Parse URL
@@ -284,7 +285,7 @@ fetch_with :: (
284
285
  },
285
286
  true => ()
286
287
  );
287
- ip := addrs.get(usize(0)).unwrap();
288
+ ip := addrs(usize(0));
288
289
  addr := SocketAddr.new(ip, port);
289
290
  // Connect
290
291
  stream := e.io.await(TcpStream.connect(addr, e.io), e);
@@ -309,7 +310,7 @@ fetch_with :: (
309
310
  // Add user-provided headers
310
311
  hi := usize(0);
311
312
  while(runtime(hi < opts.headers.len()), {
312
- h := opts.headers.get(hi).unwrap();
313
+ h := opts.headers(hi);
313
314
  req.set_header(h.name, h.value);
314
315
  hi = (hi + usize(1));
315
316
  });
@@ -352,8 +353,8 @@ export(fetch_with);
352
353
  /// cond(resp.is_ok() => println(resp.body), true => println(`Error`));
353
354
  /// ```
354
355
  fetch :: (
355
- fn(url_str : String, io : IO) ->
356
- Impl(Future(HttpResponse, IOErr))
356
+ fn(url_str : String, io : Io) ->
357
+ Impl(Future(HttpResponse, IoExn))
357
358
  )(
358
359
  io.async((e) => {
359
360
  return(e.io.await(fetch_with(url_str, FetchOptions.new(), e.io), e));
package/std/http/http.yo CHANGED
@@ -71,7 +71,7 @@ impl(
71
71
  result := `${self.method.to_string()} ${self.path} HTTP/1.1\r\n`;
72
72
  i := usize(0);
73
73
  while(i < self.headers.len(), i = (i + usize(1)), {
74
- h := self.headers.get(i).unwrap();
74
+ h := self.headers(i);
75
75
  result = `${result}${h.name}: ${h.value}\r\n`;
76
76
  });
77
77
  result = `${result}\r\n`;
@@ -102,7 +102,7 @@ impl(
102
102
  lower_name := name.to_lowercase();
103
103
  i := usize(0);
104
104
  while(i < self.headers.len(), i = (i + usize(1)), {
105
- h := self.headers.get(i).unwrap();
105
+ h := self.headers(i);
106
106
  cond(
107
107
  (h.name.to_lowercase() == lower_name) => {
108
108
  return(.Some(h.value));
@@ -134,7 +134,7 @@ parse_response :: (fn(raw : String) -> Result(HttpResponse, String))({
134
134
  },
135
135
  true => ()
136
136
  );
137
- status_line := lines.get(usize(0)).unwrap();
137
+ status_line := lines(usize(0));
138
138
  cond(
139
139
  (!(status_line.starts_with(`HTTP/`))) => {
140
140
  return(.Err(`Invalid status line`));
@@ -172,7 +172,7 @@ parse_response :: (fn(raw : String) -> Result(HttpResponse, String))({
172
172
  j := usize(1);
173
173
  body_start := lines.len();
174
174
  while(j < lines.len(), j = (j + usize(1)), {
175
- hline := lines.get(j).unwrap();
175
+ hline := lines(j);
176
176
  cond(
177
177
  hline.is_empty() => {
178
178
  body_start = (j + usize(1));
@@ -194,10 +194,10 @@ parse_response :: (fn(raw : String) -> Result(HttpResponse, String))({
194
194
  });
195
195
  cond(
196
196
  (body_start < lines.len()) => {
197
- resp.body = lines.get(body_start).unwrap();
197
+ resp.body = lines(body_start);
198
198
  m := (body_start + usize(1));
199
199
  while(m < lines.len(), m = (m + usize(1)), {
200
- resp.body = `${resp.body}\r\n${lines.get(m).unwrap()}`;
200
+ resp.body = `${resp.body}\r\n${lines(m)}`;
201
201
  });
202
202
  },
203
203
  true => ()
package/std/http/index.yo CHANGED
@@ -5,7 +5,7 @@
5
5
  // { HttpRequest, HttpResponse, fetch } :: import "std/http";
6
6
  // { Exception } :: import "std/error";
7
7
  //
8
- // main :: (fn(io : IO) -> unit)({
8
+ // main :: (fn(io : Io) -> unit)({
9
9
  // exn := Exception(throw : ((err) -> {
10
10
  // println(err.message());
11
11
  // unwind ();
package/std/imm/list.yo CHANGED
@@ -15,6 +15,7 @@
15
15
  //! assert((xs.head().unwrap() == i32(1)), "head is 1");
16
16
  //! assert((xs.len() == usize(3)), "length is 3");
17
17
  //! ```
18
+ pragma(Pragma.AllowUnsafe);
18
19
  { GlobalAllocator } :: import("../allocator.yo");
19
20
  { malloc, free } :: GlobalAllocator;
20
21
  { memcpy } :: import("../libc/string.yo");
@@ -243,6 +244,38 @@ impl(
243
244
  })
244
245
  )
245
246
  );
247
+ /// Index trait — `list(idx)` walks the chain and returns the element at
248
+ /// `idx`, panicking on out-of-bounds. O(n). The Rc-managed `ListNode`
249
+ /// keeps the value field on the heap, so `&(node._value)` is a valid
250
+ /// pointer for the immediate read; the dispatcher inlines and
251
+ /// dereferences before any drop runs.
252
+ impl(
253
+ forall(T : Type),
254
+ where(T <: Send),
255
+ List(T),
256
+ Index(usize)(
257
+ Output : T,
258
+ index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))({
259
+ assert(idx < self._len, "imm.List: index out of bounds");
260
+ (current : Option(ListNode(T))) = self._head;
261
+ i := usize(0);
262
+ while(runtime(true), {
263
+ match(
264
+ current,
265
+ .Some(node) => {
266
+ if(i == idx, {
267
+ return(unsafe(&(node._value)));
268
+ });
269
+ current = node._next;
270
+ i = (i + usize(1));
271
+ },
272
+ .None => panic("imm.List: unreachable past length check")
273
+ );
274
+ });
275
+ panic("imm.List: index loop exited without return")
276
+ })
277
+ )
278
+ );
246
279
  export(
247
280
  List,
248
281
  ListNode
package/std/imm/map.yo CHANGED
@@ -14,9 +14,10 @@
14
14
  //! m := Map(i32, i32).new();
15
15
  //! m = m.insert(i32(1), i32(100));
16
16
  //! m = m.insert(i32(2), i32(200));
17
- //! assert((m.get(i32(1)).unwrap() == i32(100)), "key 1 maps to 100");
17
+ //! assert((m(i32(1)) == i32(100)), "key 1 maps to 100");
18
18
  //! assert((m.len() == usize(2)), "two entries");
19
19
  //! ```
20
+ pragma(Pragma.AllowUnsafe);
20
21
  { GlobalAllocator } :: import("../allocator.yo");
21
22
  { malloc, free } :: GlobalAllocator;
22
23
  /// Number of bits per HAMT level.
package/std/imm/set.yo CHANGED
@@ -17,6 +17,7 @@
17
17
  //! assert(s.contains(i32(1)), "set contains 1");
18
18
  //! assert((s.len() == usize(2)), "two elements");
19
19
  //! ```
20
+ pragma(Pragma.AllowUnsafe);
20
21
  { Map } :: import("./map.yo");
21
22
  { List } :: import("./list.yo");
22
23
  /// Persistent immutable hash set backed by a HAMT.
@@ -17,6 +17,7 @@
17
17
  //! m = m.insert(i32(2), i32(20));
18
18
  //! // keys are always sorted: 1, 2, 3
19
19
  //! ```
20
+ pragma(Pragma.AllowUnsafe);
20
21
  { List } :: import("./list.yo");
21
22
  { Pair } :: import("./map.yo");
22
23
  /// Color of a red-black tree node.
@@ -17,6 +17,7 @@
17
17
  //! s = s.insert(i32(2));
18
18
  //! // elements are always sorted: 1, 2, 3
19
19
  //! ```
20
+ pragma(Pragma.AllowUnsafe);
20
21
  { SortedMap } :: import("./sorted_map.yo");
21
22
  { List } :: import("./list.yo");
22
23
  /// Persistent immutable sorted set backed by a left-leaning red-black tree.
package/std/imm/string.yo CHANGED
@@ -2,6 +2,7 @@
2
2
  //!
3
3
  //! Uses atomic reference counting for safe sharing across threads.
4
4
  //! All "modification" operations return a new string; the original is unchanged.
5
+ pragma(Pragma.AllowUnsafe);
5
6
  { GlobalAllocator } :: import("../allocator.yo");
6
7
  { malloc, free } :: GlobalAllocator;
7
8
  { memcpy, memcmp } :: import("../libc/string.yo");
@@ -57,7 +58,7 @@ impl(
57
58
  return(Self(_ptr :.None, _len : usize(0), _capacity : usize(0)));
58
59
  });
59
60
  ptr := _alloc_bytes(slen);
60
- memcpy(*(void)(ptr), *(void)(s.ptr()), slen);
61
+ unsafe(memcpy(*(void)(ptr), *(void)(s.ptr()), slen));
61
62
  return(Self(_ptr :.Some(ptr), _len : slen, _capacity : slen));
62
63
  }),
63
64
  /// Create a string from a standard (mutable) String by copying its bytes.
@@ -68,7 +69,7 @@ impl(
68
69
  });
69
70
  ptr := _alloc_bytes(slen);
70
71
  (as_str : str) = s.as_str();
71
- memcpy(*(void)(ptr), *(void)(as_str.ptr()), slen);
72
+ unsafe(memcpy(*(void)(ptr), *(void)(as_str.ptr()), slen));
72
73
  return(Self(_ptr :.Some(ptr), _len : slen, _capacity : slen));
73
74
  }),
74
75
  /// Byte length of the string.
@@ -138,7 +139,7 @@ impl(
138
139
  .Some(op) => match(
139
140
  self._ptr,
140
141
  .Some(sp) => {
141
- memcpy(*(void)(sp &+ self._len), *(void)(op), other._len);
142
+ unsafe(memcpy(*(void)(sp &+ self._len), *(void)(op), other._len));
142
143
  },
143
144
  .None => ()
144
145
  ),
@@ -155,7 +156,7 @@ impl(
155
156
  match(
156
157
  self._ptr,
157
158
  .Some(sp) => {
158
- memcpy(*(void)(ptr), *(void)(sp), self._len);
159
+ unsafe(memcpy(*(void)(ptr), *(void)(sp), self._len));
159
160
  free(.Some(*(void)(sp)));
160
161
  },
161
162
  .None => ()
@@ -163,7 +164,7 @@ impl(
163
164
  match(
164
165
  other._ptr,
165
166
  .Some(op) => {
166
- memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len);
167
+ unsafe(memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len));
167
168
  },
168
169
  .None => ()
169
170
  );
@@ -176,14 +177,14 @@ impl(
176
177
  match(
177
178
  self._ptr,
178
179
  .Some(sp) => {
179
- memcpy(*(void)(ptr), *(void)(sp), self._len);
180
+ unsafe(memcpy(*(void)(ptr), *(void)(sp), self._len));
180
181
  },
181
182
  .None => ()
182
183
  );
183
184
  match(
184
185
  other._ptr,
185
186
  .Some(op) => {
186
- memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len);
187
+ unsafe(memcpy(*(void)(ptr &+ self._len), *(void)(op), other._len));
187
188
  },
188
189
  .None => ()
189
190
  );
@@ -203,7 +204,7 @@ impl(
203
204
  match(
204
205
  self._ptr,
205
206
  .Some(sp) => {
206
- memcpy(*(void)(ptr), *(void)(sp &+ clamped_start), new_len);
207
+ unsafe(memcpy(*(void)(ptr), *(void)(sp &+ clamped_start), new_len));
207
208
  },
208
209
  .None => ()
209
210
  );
@@ -221,7 +222,7 @@ impl(
221
222
  self._ptr,
222
223
  .Some(sp) => match(
223
224
  prefix._ptr,
224
- .Some(pp) => (memcmp(*(void)(sp), *(void)(pp), prefix._len) == int(0)),
225
+ .Some(pp) => (unsafe(memcmp(*(void)(sp), *(void)(pp), prefix._len)) == int(0)),
225
226
  .None => true
226
227
  ),
227
228
  .None => (prefix._len == usize(0))
@@ -240,7 +241,7 @@ impl(
240
241
  self._ptr,
241
242
  .Some(sp) => match(
242
243
  suffix._ptr,
243
- .Some(xp) => (memcmp(*(void)(sp &+ offset), *(void)(xp), suffix._len) == int(0)),
244
+ .Some(xp) => (unsafe(memcmp(*(void)(sp &+ offset), *(void)(xp), suffix._len)) == int(0)),
244
245
  .None => true
245
246
  ),
246
247
  .None => (suffix._len == usize(0))
@@ -269,7 +270,7 @@ impl(
269
270
  i := from_index;
270
271
  limit := ((self._len - needle._len) + usize(1));
271
272
  while(i < limit, i = (i + usize(1)), {
272
- if(memcmp(*(void)(sp &+ i), *(void)(np), needle._len) == int(0), {
273
+ if(unsafe(memcmp(*(void)(sp &+ i), *(void)(np), needle._len)) == int(0), {
273
274
  return(.Some(i));
274
275
  });
275
276
  });
@@ -410,7 +411,7 @@ impl(
410
411
  return(self);
411
412
  });
412
413
  ptr := _alloc_bytes(self._len);
413
- memcpy(*(void)(ptr), *(void)(sp), self._len);
414
+ unsafe(memcpy(*(void)(ptr), *(void)(sp), self._len));
414
415
  i := usize(0);
415
416
  while(i < self._len, i = (i + usize(1)), {
416
417
  (b : u8) = (ptr &+ i).*;
@@ -447,7 +448,7 @@ impl(
447
448
  return(self);
448
449
  });
449
450
  ptr := _alloc_bytes(self._len);
450
- memcpy(*(void)(ptr), *(void)(sp), self._len);
451
+ unsafe(memcpy(*(void)(ptr), *(void)(sp), self._len));
451
452
  i := usize(0);
452
453
  while(i < self._len, i = (i + usize(1)), {
453
454
  (b : u8) = (ptr &+ i).*;
@@ -516,7 +517,7 @@ impl(
516
517
  .Some(sp) => {
517
518
  i := usize(0);
518
519
  while(i < n, i = (i + usize(1)), {
519
- memcpy(*(void)(ptr &+ (i * self._len)), *(void)(sp), self._len);
520
+ unsafe(memcpy(*(void)(ptr &+ (i * self._len)), *(void)(sp), self._len));
520
521
  });
521
522
  },
522
523
  .None => ()
@@ -623,7 +624,7 @@ impl(
623
624
  self._ptr,
624
625
  .Some(sp) => match(
625
626
  other._ptr,
626
- .Some(op) => (memcmp(*(void)(sp), *(void)(op), self._len) == int(0)),
627
+ .Some(op) => (unsafe(memcmp(*(void)(sp), *(void)(op), self._len)) == int(0)),
627
628
  .None => false
628
629
  ),
629
630
  .None => match(
@@ -653,7 +654,7 @@ impl(
653
654
  });
654
655
  match(
655
656
  self._ptr,
656
- .Some(sp) => (memcmp(*(void)(sp), *(void)(other.ptr()), self._len) == int(0)),
657
+ .Some(sp) => (unsafe(memcmp(*(void)(sp), *(void)(other.ptr()), self._len)) == int(0)),
657
658
  .None => (other_len == usize(0))
658
659
  )
659
660
  })
@@ -670,7 +671,7 @@ impl(
670
671
  .Some(sp) => match(
671
672
  other._ptr,
672
673
  .Some(op) => {
673
- (cmp_result : int) = memcmp(*(void)(sp), *(void)(op), min_len);
674
+ (cmp_result : int) = unsafe(memcmp(*(void)(sp), *(void)(op), min_len));
674
675
  if(cmp_result != int(0), {
675
676
  return(cmp_result < int(0));
676
677
  });
@@ -697,15 +698,18 @@ impl(
697
698
  impl(
698
699
  String,
699
700
  Hash(
700
- (hash) : (fn(self : *(Self)) -> u64)({
701
+ (hash) : (fn(ref(self) : Self) -> u64)({
701
702
  h := u64(14695981039346656037);
702
703
  match(
703
- self.*._ptr,
704
+ self._ptr,
704
705
  .None => (),
705
706
  .Some(p) => {
706
707
  i := usize(0);
707
- while(i < self.*._len, i = (i + usize(1)), {
708
- h = (h ^ u64((p &+ i).*));
708
+ while(i < self._len, i = (i + usize(1)), {
709
+ // SAFETY: `p` points at the Rc-managed UTF-8 byte
710
+ // buffer of length `self._len`; the loop guard
711
+ // `i < self._len` keeps `p &+ i` inside the allocation.
712
+ h = (h ^ u64(unsafe((p &+ i).*)));
709
713
  h = (h * u64(1099511628211));
710
714
  });
711
715
  }
@@ -718,8 +722,8 @@ impl(
718
722
  impl(
719
723
  String,
720
724
  ToString(
721
- to_string : (fn(self : *(Self)) -> std_string.String)(
722
- std_string.String.from(self.*.as_str())
725
+ to_string : (fn(ref(self) : Self) -> std_string.String)(
726
+ std_string.String.from(self.as_str())
723
727
  )
724
728
  )
725
729
  );
package/std/imm/vec.yo CHANGED
@@ -13,9 +13,10 @@
13
13
  //!
14
14
  //! v := Vec(i32).new();
15
15
  //! v = v.push(i32(1)).push(i32(2)).push(i32(3));
16
- //! assert((v.get(usize(0)).unwrap() == i32(1)), "first element");
16
+ //! assert((v(usize(0)) == i32(1)), "first element");
17
17
  //! assert((v.len() == usize(3)), "length is 3");
18
18
  //! ```
19
+ pragma(Pragma.AllowUnsafe);
19
20
  { GlobalAllocator } :: import("../allocator.yo");
20
21
  { malloc, free } :: GlobalAllocator;
21
22
  /// Persistent immutable vector.
@@ -406,7 +407,7 @@ impl(
406
407
  new_ptr := Vec(V)._raw_alloc(min_len);
407
408
  i := usize(0);
408
409
  while(i < min_len, i = (i + usize(1)), {
409
- (new_ptr &+ i).* = f((self._ptr &+ i).*, other.get(i).unwrap());
410
+ (new_ptr &+ i).* = f((self._ptr &+ i).*, other(i));
410
411
  });
411
412
  Vec(V)(_ptr : new_ptr, _len : min_len, _cap : min_len)
412
413
  }),
@@ -445,4 +446,19 @@ impl(
445
446
  })
446
447
  )
447
448
  );
449
+ /// Index trait — `vec(idx)` returns the element at `idx`, panicking if
450
+ /// out of bounds. Body takes `&(self)` so the dispatcher's inlined call
451
+ /// passes the right C-ABI shape. See plans/ITERATOR_REDESIGN.md.
452
+ impl(
453
+ forall(T : Type),
454
+ where(T <: Send),
455
+ Vec(T),
456
+ Index(usize)(
457
+ Output : T,
458
+ index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))({
459
+ assert(idx < self._len, "imm.Vec: index out of bounds");
460
+ self._ptr &+ idx
461
+ })
462
+ )
463
+ );
448
464
  export(Vec, PopResult);
package/std/io/reader.yo CHANGED
@@ -1,10 +1,11 @@
1
1
  //! Reader trait for byte-level input.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { Exception } :: import("../error");
3
4
  /// Common interface for reading bytes from various sources.
4
5
  Reader :: trait(
5
6
  /// Read up to `size` bytes into buffer `buf`.
6
7
  /// Returns the number of bytes actually read (0 at end-of-stream).
7
8
  read :
8
- fn(self : *(Self), buf : *(u8), size : usize, exn : Exception) -> usize
9
+ fn(ref(self) : Self, buf : *(u8), size : usize, exn : Exception) -> usize
9
10
  );
10
11
  export(Reader);
package/std/io/writer.yo CHANGED
@@ -1,12 +1,13 @@
1
1
  //! Writer trait for byte-level output.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { Exception } :: import("../error");
3
4
  /// Common interface for writing bytes to a destination.
4
5
  Writer :: trait(
5
6
  /// Write bytes from buffer. Returns number of bytes written.
6
7
  write :
7
- fn(self : *(Self), buf : *(u8), size : usize, exn : Exception) -> usize,
8
+ fn(ref(self) : Self, buf : *(u8), size : usize, exn : Exception) -> usize,
8
9
  /// Flush any buffered data to the underlying destination.
9
10
  flush :
10
- fn(self : *(Self), exn : Exception) -> unit
11
+ fn(ref(self) : Self, exn : Exception) -> unit
11
12
  );
12
13
  export(Writer);
@@ -1,5 +1,6 @@
1
1
  //! C11 `<assert.h>` — assertion debugging facility.
2
2
  //! Provides runtime assertion checking for debugging.
3
+ pragma(Pragma.AllowUnsafe);
3
4
  c_include(
4
5
  "<assert.h>",
5
6
  // The actual assertion function called by the assert macro
package/std/libc/ctype.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! C11 `<ctype.h>` — character classification and conversion functions.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<ctype.h>",
4
5
  // Character classification functions
@@ -1,4 +1,5 @@
1
1
  //! C11 `<dirent.h>` — directory entry operations.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<dirent.h>",
4
5
  // Types
package/std/libc/errno.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! C11 `<errno.h>` — error handling constants and `errno` variable.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<errno.h>",
4
5
  // The errno variable - global error indicator
package/std/libc/fcntl.yo CHANGED
@@ -1,5 +1,6 @@
1
1
  //! POSIX `<fcntl.h>` — file control options.
2
2
  //! Provides open flags and file control operations.
3
+ pragma(Pragma.AllowUnsafe);
3
4
  c_include(
4
5
  "<fcntl.h>",
5
6
  // File access modes (for open)
package/std/libc/float.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! C11 `<float.h>` — floating-point implementation limits.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<float.h>",
4
5
  // Floating-point model parameters
@@ -1,4 +1,5 @@
1
1
  //! C11 `<limits.h>` — implementation-defined limits for integer types.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<limits.h>",
4
5
  // Character limits
package/std/libc/math.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! C11 `<math.h>` — mathematical functions and constants.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<math.h>",
4
5
  // Mathematical constants (implementation-defined)
@@ -1,4 +1,5 @@
1
1
  //! C11 `<signal.h>` — signal handling functions and constants.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<signal.h>",
4
5
  // Signal handler type
@@ -1,4 +1,5 @@
1
1
  //! C11 `<stdatomic.h>` — atomic operations and types.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<stdatomic.h>",
4
5
  // Atomic types
@@ -3,6 +3,7 @@
3
3
  //! Note: Yo already has `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`.
4
4
  //! This file provides C-compatible aliases and additional types/constants.
5
5
  // Type aliases for C compatibility (mapping Yo types to C stdint names)
6
+ pragma(Pragma.AllowUnsafe);
6
7
  int8_t :: i8;
7
8
  int16_t :: i16;
8
9
  int32_t :: i32;
package/std/libc/stdio.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! C11 `<stdio.h>` — standard I/O functions.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<stdio.h>",
4
5
  // Types
@@ -1,4 +1,5 @@
1
1
  //! C11 `<stdlib.h>` — general utility functions.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<stdlib.h>",
4
5
  // Types for div functions
@@ -1,4 +1,5 @@
1
1
  //! C11 `<string.h>` — string and memory functions.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<string.h>",
4
5
  // Memory functions
@@ -1,4 +1,5 @@
1
1
  //! POSIX `<sys/stat.h>` — file status and mode operations.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  c_include(
3
4
  "<sys/stat.h>",
4
5
  // Types