@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
@@ -12,6 +12,7 @@
12
12
  //! v := json_parse(`{"x": 1}`);
13
13
  //! println(json_stringify(v));
14
14
  //! ```
15
+ pragma(Pragma.AllowUnsafe);
15
16
  open(import("../string"));
16
17
  { ArrayList } :: import("../collections/array_list");
17
18
  { snprintf } :: import("../libc/stdio");
@@ -90,8 +91,8 @@ impl(
90
91
  i := usize(0);
91
92
  while(i < keys.len(), i = (i + usize(1)), {
92
93
  cond(
93
- (keys.get(i).unwrap() == key) => {
94
- return(.Some(values.get(i).unwrap()));
94
+ (keys(i) == key) => {
95
+ return(.Some(values(i)));
95
96
  },
96
97
  true => ()
97
98
  );
@@ -149,7 +150,7 @@ impl(
149
150
  result := ArrayList(JsonKV).new();
150
151
  i := usize(0);
151
152
  while(i < keys.len(), i = (i + usize(1)), {
152
- result.push(JsonKV(key : keys.get(i).unwrap(), value : values.get(i).unwrap()));
153
+ result.push(JsonKV(key : keys(i), value : values(i)));
153
154
  });
154
155
  .Some(result)
155
156
  },
@@ -157,6 +158,54 @@ impl(
157
158
  )
158
159
  )
159
160
  );
161
+ /// Index trait — `v(key)` returns the child JsonValue for `key`, panicking
162
+ /// if `v` is not an Object or the key is missing.
163
+ impl(
164
+ JsonValue,
165
+ Index(String)(
166
+ Output : JsonValue,
167
+ index : (fn(ref(self) : Self, key : String) -> *(Self.Output))(
168
+ match(
169
+ self,
170
+ .Object(keys, values) => {
171
+ i := usize(0);
172
+ while(i < keys.len(), i = (i + usize(1)), {
173
+ if(keys(i) == key, {
174
+ // SAFETY: `i` is bounded by `keys.len()` and the
175
+ // Object variant invariant says `values.len() ==
176
+ // keys.len()`, so `values.project(i)` yields a valid
177
+ // ref into the Rc-managed values list.
178
+ return(unsafe(&(values.project(i))));
179
+ });
180
+ });
181
+ panic("JsonValue: key not found in Object")
182
+ },
183
+ _ => panic("JsonValue: index by String requires .Object variant")
184
+ )
185
+ )
186
+ )
187
+ );
188
+ /// Index trait — `v(i)` returns the i-th JsonValue, panicking if `v` is
189
+ /// not an Array or `i` is out of bounds.
190
+ impl(
191
+ JsonValue,
192
+ Index(usize)(
193
+ Output : JsonValue,
194
+ index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))(
195
+ match(
196
+ self,
197
+ .Array(items) => {
198
+ assert(idx < items.len(), "JsonValue: Array index out of bounds");
199
+ // SAFETY: assert above bounds `idx`; `items` is the
200
+ // Rc-managed Array list whose storage outlives this call
201
+ // (ref(self) keeps `self` and therefore `items` alive).
202
+ return(unsafe(&(items.project(idx))));
203
+ },
204
+ _ => panic("JsonValue: index by usize requires .Array variant")
205
+ )
206
+ )
207
+ )
208
+ );
160
209
  export(JsonValue, JsonKV);
161
210
  // ============================================================================
162
211
  // Parser state
@@ -364,7 +413,7 @@ impl(
364
413
  num_buf.push(u8(0));
365
414
  num_ptr := *(char)(num_buf.ptr().unwrap());
366
415
  { atof } :: import("../libc/stdlib");
367
- val := atof(num_ptr);
416
+ val := unsafe(atof(num_ptr));
368
417
  .Ok(val)
369
418
  })
370
419
  );
@@ -570,7 +619,7 @@ _write_str_escaped :: (fn(s : String, out : ArrayList(u8)) -> unit)({
570
619
  bytes := s.as_bytes();
571
620
  i := usize(0);
572
621
  while(i < bytes.len(), i = (i + usize(1)), {
573
- b := bytes.get(i).unwrap();
622
+ b := bytes(i);
574
623
  cond(
575
624
  (b == u8(34)) => {
576
625
  out.push(u8(92));
@@ -628,12 +677,12 @@ _stringify_into :: (fn(value : JsonValue, out : ArrayList(u8)) -> unit)({
628
677
  .Number(n) => {
629
678
  buf := Array(u8, usize(32)).fill(u8(0));
630
679
  buf_ptr := &(buf(usize(0)));
631
- snprintf(*(char)(buf_ptr), usize(32), "%g", n);
680
+ unsafe(snprintf(*(char)(buf_ptr), usize(32), "%g", n));
632
681
  s2 := String.from_cstr(buf_ptr).unwrap();
633
682
  bytes := s2.as_bytes();
634
683
  i := usize(0);
635
684
  while(i < bytes.len(), i = (i + usize(1)), {
636
- out.push(bytes.get(i).unwrap());
685
+ out.push(bytes(i));
637
686
  });
638
687
  },
639
688
  .Str(s) => {
@@ -649,7 +698,7 @@ _stringify_into :: (fn(value : JsonValue, out : ArrayList(u8)) -> unit)({
649
698
  },
650
699
  true => ()
651
700
  );
652
- recur(items.get(i).unwrap(), out);
701
+ recur(items(i), out);
653
702
  });
654
703
  out.push(u8(93)); // ']'
655
704
  },
@@ -663,9 +712,9 @@ _stringify_into :: (fn(value : JsonValue, out : ArrayList(u8)) -> unit)({
663
712
  },
664
713
  true => ()
665
714
  );
666
- _write_str_escaped(keys.get(i).unwrap(), out);
715
+ _write_str_escaped(keys(i), out);
667
716
  out.push(u8(58)); // ':'
668
- recur(values.get(i).unwrap(), out);
717
+ recur(values(i), out);
669
718
  });
670
719
  out.push(u8(125)); // '}'
671
720
  }
@@ -12,6 +12,7 @@
12
12
  //! ascii_domain := to_ascii(`münchen.de`); // "xn--mnchen-3ya.de"
13
13
  //! unicode_domain := to_unicode(ascii_domain); // "münchen.de"
14
14
  //! ```
15
+ pragma(Pragma.AllowUnsafe);
15
16
  open(import("../string"));
16
17
  { ArrayList } :: import("../collections/array_list");
17
18
  // Punycode constants (RFC 3492 section 5)
@@ -53,25 +54,25 @@ _adapt :: (fn(delta_val : i32, num_points : i32, first_time : bool) -> i32)({
53
54
  k + ((((_BASE - _TMIN) + i32(1)) * d) / (d + _SKEW))
54
55
  });
55
56
  // Encode a single Unicode code point as UTF-8 bytes.
56
- _encode_codepoint :: (fn(cp : i32, out : *(ArrayList(u8))) -> unit)(
57
+ _encode_codepoint :: (fn(cp : i32, out : ArrayList(u8)) -> unit)(
57
58
  cond(
58
59
  (cp < i32(0x80)) => {
59
- out.*.push(u8(cp));
60
+ out.push(u8(cp));
60
61
  },
61
62
  (cp < i32(0x800)) => {
62
- out.*.push(u8(i32(0xC0) | (cp >> i32(6))));
63
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
63
+ out.push(u8(i32(0xC0) | (cp >> i32(6))));
64
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
64
65
  },
65
66
  (cp < i32(0x10000)) => {
66
- out.*.push(u8(i32(0xE0) | (cp >> i32(12))));
67
- out.*.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
68
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
67
+ out.push(u8(i32(0xE0) | (cp >> i32(12))));
68
+ out.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
69
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
69
70
  },
70
71
  true => {
71
- out.*.push(u8(i32(0xF0) | (cp >> i32(18))));
72
- out.*.push(u8(i32(0x80) | ((cp >> i32(12)) & i32(0x3F))));
73
- out.*.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
74
- out.*.push(u8(i32(0x80) | (cp & i32(0x3F))));
72
+ out.push(u8(i32(0xF0) | (cp >> i32(18))));
73
+ out.push(u8(i32(0x80) | ((cp >> i32(12)) & i32(0x3F))));
74
+ out.push(u8(i32(0x80) | ((cp >> i32(6)) & i32(0x3F))));
75
+ out.push(u8(i32(0x80) | (cp & i32(0x3F))));
75
76
  }
76
77
  )
77
78
  );
@@ -82,7 +83,7 @@ _string_to_codepoints :: (fn(s : String) -> ArrayList(i32))({
82
83
  (i : usize) = usize(0);
83
84
  (blen : usize) = bytes.len();
84
85
  while(i < blen, {
85
- (b : i32) = i32(bytes.get(i).unwrap());
86
+ (b : i32) = i32(bytes(i));
86
87
  (cp : i32) = i32(0);
87
88
  (size : usize) = usize(1);
88
89
  cond(
@@ -108,7 +109,7 @@ _string_to_codepoints :: (fn(s : String) -> ArrayList(i32))({
108
109
  (j : usize) = usize(1);
109
110
  while(j < size, {
110
111
  if((i + j) < blen, {
111
- cp = ((cp << i32(6)) | (i32(bytes.get(i + j).unwrap()) & i32(0x3F)));
112
+ cp = ((cp << i32(6)) | (i32(bytes(i + j)) & i32(0x3F)));
112
113
  });
113
114
  j = (j + usize(1));
114
115
  });
@@ -127,7 +128,7 @@ punycode_decode :: (fn(input : String) -> Option(String))({
127
128
  (basic_end : i32) = i32(-(1));
128
129
  (j : i32) = (input_len - i32(1));
129
130
  while((j >= i32(0)) && (basic_end < i32(0)), {
130
- if(i32(bytes.get(usize(j)).unwrap()) == i32(0x2D), {
131
+ if(i32(bytes(usize(j))) == i32(0x2D), {
131
132
  basic_end = j;
132
133
  });
133
134
  j = (j - i32(1));
@@ -139,7 +140,7 @@ punycode_decode :: (fn(input : String) -> Option(String))({
139
140
  );
140
141
  (bi : i32) = i32(0);
141
142
  while(bi < basic_length, {
142
- (cp : i32) = i32(bytes.get(usize(bi)).unwrap());
143
+ (cp : i32) = i32(bytes(usize(bi)));
143
144
  if(cp >= i32(0x80), {
144
145
  return(.None);
145
146
  });
@@ -162,7 +163,7 @@ punycode_decode :: (fn(input : String) -> Option(String))({
162
163
  if(idx >= input_len, {
163
164
  return(.None);
164
165
  });
165
- (digit : i32) = _decode_digit(i32(bytes.get(usize(idx)).unwrap()));
166
+ (digit : i32) = _decode_digit(i32(bytes(usize(idx))));
166
167
  idx = (idx + i32(1));
167
168
  if(digit < i32(0), {
168
169
  return(.None);
@@ -198,7 +199,7 @@ punycode_decode :: (fn(input : String) -> Option(String))({
198
199
  (result_bytes : ArrayList(u8)) = ArrayList(u8).new();
199
200
  (ri : usize) = usize(0);
200
201
  while(ri < output.len(), {
201
- _encode_codepoint(output.get(ri).unwrap(), &(result_bytes));
202
+ _encode_codepoint(output(ri), result_bytes);
202
203
  ri = (ri + usize(1));
203
204
  });
204
205
  .Some(String.from_bytes(result_bytes))
@@ -212,7 +213,7 @@ punycode_encode :: (fn(input : String) -> String)({
212
213
  (basic_count : i32) = i32(0);
213
214
  (ci : i32) = i32(0);
214
215
  while(ci < cp_count, {
215
- (cp : i32) = cps.get(usize(ci)).unwrap();
216
+ (cp : i32) = cps(usize(ci));
216
217
  if(cp < i32(0x80), {
217
218
  out.push(u8(cp));
218
219
  basic_count = (basic_count + i32(1));
@@ -231,7 +232,7 @@ punycode_encode :: (fn(input : String) -> String)({
231
232
  (m : i32) = i32(0x7FFFFFFF);
232
233
  (mi : i32) = i32(0);
233
234
  while(mi < cp_count, {
234
- (cp : i32) = cps.get(usize(mi)).unwrap();
235
+ (cp : i32) = cps(usize(mi));
235
236
  if((cp >= n) && (cp < m), {
236
237
  m = cp;
237
238
  });
@@ -241,7 +242,7 @@ punycode_encode :: (fn(input : String) -> String)({
241
242
  n = m;
242
243
  (ei : i32) = i32(0);
243
244
  while(ei < cp_count, {
244
- (cp : i32) = cps.get(usize(ei)).unwrap();
245
+ (cp : i32) = cps(usize(ei));
245
246
  if(cp < n, {
246
247
  delta = (delta + i32(1));
247
248
  });
@@ -283,7 +284,7 @@ to_unicode :: (fn(hostname : String) -> String)({
283
284
  (result : String) = ``;
284
285
  (pi : usize) = usize(0);
285
286
  while(pi < parts.len(), {
286
- (part : String) = parts.get(pi).unwrap();
287
+ (part : String) = parts(pi);
287
288
  if(pi > usize(0), {
288
289
  result = `${result}.`;
289
290
  });
@@ -315,7 +316,7 @@ to_ascii :: (fn(hostname : String) -> String)({
315
316
  (result : String) = ``;
316
317
  (pi : usize) = usize(0);
317
318
  while(pi < parts.len(), {
318
- (part : String) = parts.get(pi).unwrap();
319
+ (part : String) = parts(pi);
319
320
  if(pi > usize(0), {
320
321
  result = `${result}.`;
321
322
  });
@@ -324,7 +325,7 @@ to_ascii :: (fn(hostname : String) -> String)({
324
325
  (bytes : ArrayList(u8)) = part.as_bytes();
325
326
  (bi : usize) = usize(0);
326
327
  while(bi < bytes.len(), {
327
- if(i32(bytes.get(bi).unwrap()) >= i32(0x80), {
328
+ if(i32(bytes(bi)) >= i32(0x80), {
328
329
  has_non_ascii = true;
329
330
  });
330
331
  bi = (bi + usize(1));
@@ -10,6 +10,7 @@
10
10
  //! // Or via the encoding index:
11
11
  //! { toml_parse, TomlValue } :: import "std/encoding";
12
12
  //! ```
13
+ pragma(Pragma.AllowUnsafe);
13
14
  open(import("../string"));
14
15
  { ArrayList } :: import("../collections/array_list");
15
16
  /// TOML value type — the result of parsing a TOML document.
@@ -37,8 +38,8 @@ impl(
37
38
  i := usize(0);
38
39
  while(i < keys.len(), i = (i + usize(1)), {
39
40
  cond(
40
- (keys.get(i).unwrap() == key) => {
41
- return(.Some(values.get(i).unwrap()));
41
+ (keys(i) == key) => {
42
+ return(.Some(values(i)));
42
43
  },
43
44
  true => ()
44
45
  );
@@ -62,7 +63,7 @@ impl(
62
63
  found := false;
63
64
  while(i < len, i = (i + usize(1)), {
64
65
  cond(
65
- (keys.get(i).unwrap() == key) => {
66
+ (keys(i) == key) => {
66
67
  &(values(i)).* = value;
67
68
  found = true;
68
69
  },
@@ -72,7 +72,7 @@ utf16_to_utf8 :: (fn(data : ArrayList(u16), exn : Exception) -> String)({
72
72
  out := ArrayList(u8).new();
73
73
  i := usize(0);
74
74
  while(i < data.len(), {
75
- w := u32(data.get(i).unwrap());
75
+ w := u32(data(i));
76
76
  cond(
77
77
  // Surrogate pair: high surrogate 0xD800-0xDBFF
78
78
  ((w >= u32(0xD800)) && (w <= u32(0xDBFF))) => {
@@ -82,7 +82,7 @@ utf16_to_utf8 :: (fn(data : ArrayList(u16), exn : Exception) -> String)({
82
82
  },
83
83
  true => ()
84
84
  );
85
- w2 := u32(data.get(i + usize(1)).unwrap());
85
+ w2 := u32(data(i + usize(1)));
86
86
  cond(
87
87
  ((w2 < u32(0xDC00)) || (w2 > u32(0xDFFF))) => {
88
88
  exn.throw(dyn(EncodingError.InvalidChar(u8(0))));
package/std/env.yo CHANGED
@@ -3,6 +3,7 @@
3
3
  //!
4
4
  //! Mirrors the layout of Rust's `std::env`. Platform/architecture detection
5
5
  //! and child-process spawning live in `std/process`.
6
+ pragma(Pragma.AllowUnsafe);
6
7
  open(import("./collections/array_list"));
7
8
  open(import("./string"));
8
9
  open(import("./path"));
@@ -57,7 +58,7 @@ env :: impl({
57
58
  /// Returns `.None` if the variable is not set.
58
59
  get :: (fn(name : String) -> Option(String))({
59
60
  name_cstr := name.to_cstr().ptr().unwrap();
60
- val_ptr := getenv(*(char)(name_cstr));
61
+ val_ptr := unsafe(getenv(*(char)(name_cstr)));
61
62
  match(
62
63
  val_ptr,
63
64
  .None =>.None,
@@ -75,13 +76,13 @@ env :: impl({
75
76
  { _putenv_s } :: import("./libc/windows");
76
77
  cond(
77
78
  overwrite =>
78
- _putenv_s(*(char)(name_cstr), *(char)(value_cstr)),
79
+ unsafe(_putenv_s(*(char)(name_cstr), *(char)(value_cstr))),
79
80
  true => {
80
- existing := getenv(*(char)(name_cstr));
81
+ existing := unsafe(getenv(*(char)(name_cstr)));
81
82
  match(
82
83
  existing,
83
84
  .Some(_) => int(0),
84
- .None => _putenv_s(*(char)(name_cstr), *(char)(value_cstr))
85
+ .None => unsafe(_putenv_s(*(char)(name_cstr), *(char)(value_cstr)))
85
86
  )
86
87
  }
87
88
  )
@@ -91,7 +92,7 @@ env :: impl({
91
92
  overwrite => int(1),
92
93
  true => int(0)
93
94
  );
94
- setenv(*(char)(name_cstr), *(char)(value_cstr), overwrite_int)
95
+ unsafe(setenv(*(char)(name_cstr), *(char)(value_cstr), overwrite_int))
95
96
  }
96
97
  );
97
98
  return(result == int(0));
@@ -105,27 +106,29 @@ cwd :: (fn() -> Result(Path, String))(
105
106
  cond(
106
107
  (platform == Platform.Windows) => {
107
108
  { GetCurrentDirectoryW, WideCharToMultiByte, CP_UTF8, WCHAR, DWORD } :: import("./libc/windows");
108
- required_size := GetCurrentDirectoryW(ulong(0),.None);
109
+ required_size := unsafe(GetCurrentDirectoryW(ulong(0),.None));
109
110
  cond(
110
111
  (required_size == ulong(0)) =>.Err(`Failed to get current working directory on Windows`),
111
112
  true => {
112
113
  wbuf := *(WCHAR)(malloc(usize(required_size) * usize(2)).unwrap());
113
- actual_size := GetCurrentDirectoryW(required_size,.Some(wbuf));
114
+ actual_size := unsafe(GetCurrentDirectoryW(required_size,.Some(wbuf)));
114
115
  cond(
115
116
  (actual_size == ulong(0)) => {
116
117
  free(.Some(*(void)(wbuf)));
117
118
  .Err(`Failed to get current working directory on Windows`)
118
119
  },
119
120
  true => {
120
- utf8_size := WideCharToMultiByte(
121
- CP_UTF8,
122
- ulong(0),
123
- .Some(wbuf),
124
- i32(actual_size),
125
- .None,
126
- i32(0),
127
- .None,
128
- .None
121
+ utf8_size := unsafe(
122
+ WideCharToMultiByte(
123
+ CP_UTF8,
124
+ ulong(0),
125
+ .Some(wbuf),
126
+ i32(actual_size),
127
+ .None,
128
+ i32(0),
129
+ .None,
130
+ .None
131
+ )
129
132
  );
130
133
  cond(
131
134
  (utf8_size <= i32(0)) => {
@@ -134,15 +137,17 @@ cwd :: (fn() -> Result(Path, String))(
134
137
  },
135
138
  true => {
136
139
  utf8_buf := *(u8)(malloc(usize(utf8_size) + usize(1)).unwrap());
137
- result := WideCharToMultiByte(
138
- CP_UTF8,
139
- ulong(0),
140
- .Some(wbuf),
141
- i32(actual_size),
142
- .Some(utf8_buf),
143
- utf8_size,
144
- .None,
145
- .None
140
+ result := unsafe(
141
+ WideCharToMultiByte(
142
+ CP_UTF8,
143
+ ulong(0),
144
+ .Some(wbuf),
145
+ i32(actual_size),
146
+ .Some(utf8_buf),
147
+ utf8_size,
148
+ .None,
149
+ .None
150
+ )
146
151
  );
147
152
  free(.Some(*(void)(wbuf)));
148
153
  cond(
@@ -166,9 +171,16 @@ cwd :: (fn() -> Result(Path, String))(
166
171
  },
167
172
  true => {
168
173
  { getcwd } :: import("./libc/unistd");
174
+ // 4096 is PATH_MAX on Linux/macOS and exceeds MAX_PATH (260) on Windows;
175
+ // the few systems with longer paths fail gracefully via the .None branch
176
+ // below (getcwd returns NULL and sets errno=ERANGE).
169
177
  buf_size := usize(4096);
170
178
  buf := *(char)(malloc(buf_size).unwrap());
171
- result_ptr := getcwd(buf, buf_size);
179
+ // SAFETY: `buf` points at a fresh malloc'd `buf_size`-byte buffer and
180
+ // is freed in both branches below. `getcwd(buf, buf_size)` writes at
181
+ // most `buf_size - 1` bytes plus a terminating NUL, then returns either
182
+ // `buf` (success) or NULL (failure — buffer too small / cwd unlinked).
183
+ result_ptr := unsafe(getcwd(buf, buf_size));
172
184
  match(
173
185
  result_ptr,
174
186
  .None => {
@@ -193,7 +205,7 @@ chdir :: (fn(path : Path) -> Result(unit, String))(
193
205
  { SetCurrentDirectoryA, BOOL } :: import("./libc/windows");
194
206
  path_str := path.to_string();
195
207
  path_cstr := path_str.to_cstr().ptr().unwrap();
196
- result := SetCurrentDirectoryA(*(char)(path_cstr));
208
+ result := unsafe(SetCurrentDirectoryA(*(char)(path_cstr)));
197
209
  cond(
198
210
  (result == int(0)) =>.Err(`Failed to change directory to: ${path_str}`),
199
211
  true =>.Ok(())
@@ -203,7 +215,10 @@ chdir :: (fn(path : Path) -> Result(unit, String))(
203
215
  { chdir : unix_chdir } :: import("./libc/unistd");
204
216
  path_str := path.to_string();
205
217
  path_cstr := path_str.to_cstr().ptr().unwrap();
206
- result := unix_chdir(*(char)(path_cstr));
218
+ // SAFETY: `unix_chdir` is libc `chdir` aliased on import;
219
+ // `path_cstr` is the null-terminated buffer that `to_cstr()`
220
+ // just produced and `path_str` keeps alive across this call.
221
+ result := unsafe(unix_chdir(*(char)(path_cstr)));
207
222
  cond(
208
223
  (result != int(0)) =>.Err(`Failed to change directory to: ${path_str}`),
209
224
  true =>.Ok(())
package/std/error.yo CHANGED
@@ -4,7 +4,7 @@ open(import("./fmt"));
4
4
  /// Standard error trait for typed error propagation.
5
5
  /// All error types should implement this trait along with `ToString`.
6
6
  Error :: trait(
7
- (source : (fn(self : *(Self)) -> Option(Dyn(SelfTrait)))) ?= ((self) ->.None),
7
+ (source : (fn(ref(self) : Self) -> Option(Dyn(SelfTrait)))) ?= ((self) ->.None),
8
8
  where(Self <: ToString)
9
9
  );
10
10
  export(Error);
@@ -31,11 +31,11 @@ ResumableException :: (fn(comptime(ResumeType) : Type) -> comptime(Type))(
31
31
  )
32
32
  );
33
33
  export(ResumableException);
34
- /// Common effect bundle: IO + Exception.
35
- /// Used as the effect parameter for Futures that perform IO and may throw.
34
+ /// Common effect bundle: Io + Exception.
35
+ /// Used as the effect parameter for Futures that perform Io and may throw.
36
36
  /// Construct with `{ io, exn }`; project with `e.io` or `e.exn`.
37
- IOErr :: struct(
38
- io : IO,
37
+ IoExn :: struct(
38
+ io : Io,
39
39
  exn : Exception
40
40
  );
41
- export(IOErr);
41
+ export(IoExn);
@@ -4,7 +4,7 @@
4
4
  //!
5
5
  //! ```rust
6
6
  //! impl(MyType, Display(
7
- //! display : (fn(self: *(Self), writer: Writer) -> Writer)(
7
+ //! display : (fn(ref(self) : Self, writer : Writer) -> Writer)(
8
8
  //! writer.write_str("MyType(").write_i64(i64(self.value)).write_str(")")
9
9
  //! )
10
10
  //! ));
@@ -14,7 +14,7 @@
14
14
  /// Complement to `ToString` for streaming output into an existing buffer.
15
15
  Display :: (fn(comptime(T) : Type) -> comptime(Trait))(
16
16
  trait(
17
- display : (fn(self : *(T), writer : Writer) -> Writer)
17
+ display : (fn(ref(self) : T, writer : Writer) -> Writer)
18
18
  )
19
19
  );
20
20
  export(Display);
package/std/fmt/index.yo CHANGED
@@ -1,4 +1,5 @@
1
1
  //! Formatted output to stdout and stderr.
2
+ pragma(Pragma.AllowUnsafe);
2
3
  { fwrite, stdout, stderr } :: import("../libc/stdio");
3
4
  { String } :: import("../string");
4
5
  { ToString } :: import("./to_string.yo");
@@ -11,11 +12,11 @@ println :: (fn(forall(T : Type), v : T, where(T <: ToString)) -> unit)({
11
12
  cond(
12
13
  (str_bytes_len > usize(0)) => {
13
14
  str_bytes_ptr := str_bytes.ptr().unwrap();
14
- fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stdout);
15
+ unsafe(fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stdout));
15
16
  },
16
17
  true => ()
17
18
  );
18
- fwrite(*(void)(*(u8)("\n")), usize(1), usize(1), stdout);
19
+ unsafe(fwrite(*(void)(*(u8)("\n")), usize(1), usize(1), stdout));
19
20
  });
20
21
  export(println);
21
22
  /// Print a value that implements `ToString` to stdout, without a trailing newline.
@@ -26,7 +27,7 @@ print :: (fn(forall(T : Type), v : T, where(T <: ToString)) -> unit)({
26
27
  cond(
27
28
  (str_bytes_len > usize(0)) => {
28
29
  str_bytes_ptr := str_bytes.ptr().unwrap();
29
- fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stdout);
30
+ unsafe(fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stdout));
30
31
  },
31
32
  true => ()
32
33
  );
@@ -40,11 +41,11 @@ eprintln :: (fn(forall(T : Type), v : T, where(T <: ToString)) -> unit)({
40
41
  cond(
41
42
  (str_bytes_len > usize(0)) => {
42
43
  str_bytes_ptr := str_bytes.ptr().unwrap();
43
- fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stderr);
44
+ unsafe(fwrite(*(void)(str_bytes_ptr), usize(1), str_bytes_len, stderr));
44
45
  },
45
46
  true => ()
46
47
  );
47
- fwrite(*(void)(*(u8)("\n")), usize(1), usize(1), stderr);
48
+ unsafe(fwrite(*(void)(*(u8)("\n")), usize(1), usize(1), stderr));
48
49
  });
49
50
  export(eprintln);
50
51
  /// Print a value that implements `ToString` to stderr, without a trailing newline.