@shd101wyy/yo 0.1.30 → 0.1.32
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.
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +38 -0
- package/out/cjs/index.cjs +800 -633
- package/out/cjs/yo-cli.cjs +1007 -840
- package/out/cjs/yo-lsp.cjs +890 -723
- package/out/esm/index.mjs +804 -637
- package/out/types/src/codegen/index.d.ts +1 -1
- package/out/types/src/compiler-utils.d.ts +1 -1
- package/out/types/src/evaluator/builtins/contracts.d.ts +35 -0
- package/out/types/src/evaluator/memory-safety.d.ts +1 -1
- package/out/types/src/evaluator/types/function.d.ts +2 -0
- package/out/types/src/evaluator/utils/closure.d.ts +2 -1
- package/out/types/src/evaluator/utils.d.ts +3 -0
- package/out/types/src/evaluator/values/impl.d.ts +14 -0
- package/out/types/src/expr.d.ts +6 -0
- package/out/types/src/tests/contracts-comptime-violation.test.d.ts +1 -0
- package/out/types/src/tests/contracts-runtime-violation.test.d.ts +1 -0
- package/out/types/src/tests/thread-safety-codegen.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +3 -1
- package/out/types/src/types/definitions.d.ts +2 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/build.yo +5 -2
- package/std/imm/list.yo +1 -1
- package/std/imm/sorted_map.yo +1 -1
- package/std/libc/stdatomic.yo +285 -1
- package/std/prelude.yo +56 -3
- package/std/spec/numeric.yo +30 -0
- package/std/spec/refine.yo +43 -0
- package/std/string/rune.yo +4 -0
- package/std/sync/atomic.yo +557 -0
- package/std/sync/channel.yo +57 -42
- package/std/sync/cond.yo +7 -3
- package/std/sync/mutex.yo +75 -15
- package/std/sync/once.yo +25 -19
- package/std/sync/rwlock.yo +18 -15
- package/std/sync/waitgroup.yo +25 -16
package/package.json
CHANGED
package/std/build.yo
CHANGED
|
@@ -47,7 +47,9 @@ Sanitize :: enum(
|
|
|
47
47
|
/// AddressSanitizer — detects memory errors and leaks.
|
|
48
48
|
Address,
|
|
49
49
|
/// LeakSanitizer — detects memory leaks only.
|
|
50
|
-
Leak
|
|
50
|
+
Leak,
|
|
51
|
+
/// ThreadSanitizer — detects data races in multi-threaded code.
|
|
52
|
+
Thread
|
|
51
53
|
);
|
|
52
54
|
export(Sanitize);
|
|
53
55
|
// ── Step kinds ───────────────────────────────────────────────────────
|
|
@@ -281,7 +283,8 @@ executable :: (fn(comptime(config) : Executable) -> comptime(Step))({
|
|
|
281
283
|
config.sanitize,
|
|
282
284
|
.None => "none",
|
|
283
285
|
.Address => "address",
|
|
284
|
-
.Leak => "leak"
|
|
286
|
+
.Leak => "leak",
|
|
287
|
+
.Thread => "thread"
|
|
285
288
|
);
|
|
286
289
|
__yo_build_executable(config.name, config.root, config.target, opt_str, alloc_str, san_str);
|
|
287
290
|
Step(name : config.name, kind : StepKind.Executable)
|
package/std/imm/list.yo
CHANGED
|
@@ -28,7 +28,7 @@ ListNode :: (fn(comptime(T) : Type, where(T <: Send)) -> comptime(Type))(
|
|
|
28
28
|
)
|
|
29
29
|
)
|
|
30
30
|
);
|
|
31
|
-
// Manual Acyclic impl — ListNode is self-referential, so auto-derivation skips it.
|
|
31
|
+
// SAFETY: Manual Acyclic impl — ListNode is self-referential, so auto-derivation skips it.
|
|
32
32
|
// This is safe because ListNode is immutable: all operations create new nodes and never
|
|
33
33
|
// mutate existing ones, making it impossible to form cycles at runtime.
|
|
34
34
|
impl(forall(T : Type), where(T <: Send), ListNode(T), Acyclic());
|
package/std/imm/sorted_map.yo
CHANGED
|
@@ -40,7 +40,7 @@ RBNode :: (
|
|
|
40
40
|
)
|
|
41
41
|
)
|
|
42
42
|
);
|
|
43
|
-
// Manual Acyclic impl — RBNode is self-referential, so auto-derivation skips it.
|
|
43
|
+
// SAFETY: Manual Acyclic impl — RBNode is self-referential, so auto-derivation skips it.
|
|
44
44
|
// This is safe because RBNode is immutable: all tree operations create new nodes
|
|
45
45
|
// and never mutate existing ones, making it impossible to form cycles at runtime.
|
|
46
46
|
impl(forall(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send), V <: Send), RBNode(K, V), Acyclic());
|
package/std/libc/stdatomic.yo
CHANGED
|
@@ -138,6 +138,244 @@ c_include(
|
|
|
138
138
|
ATOMIC_LLONG_LOCK_FREE : i32,
|
|
139
139
|
ATOMIC_POINTER_LOCK_FREE : i32
|
|
140
140
|
);
|
|
141
|
+
// SAFETY: C11 atomic typedefs (atomic_bool, atomic_int, etc.) are opaque C
|
|
142
|
+
// types backed by _Atomic-qualified primitives. They contain no heap
|
|
143
|
+
// allocations or thread-local state — they are trivially safe to send
|
|
144
|
+
// across threads. They are Acyclic because they don't participate in Yo's
|
|
145
|
+
// ARC reference-counting cycle analysis.
|
|
146
|
+
impl(atomic_bool, Send());
|
|
147
|
+
impl(atomic_bool, Acyclic());
|
|
148
|
+
impl(atomic_char, Send());
|
|
149
|
+
impl(atomic_char, Acyclic());
|
|
150
|
+
impl(atomic_schar, Send());
|
|
151
|
+
impl(atomic_schar, Acyclic());
|
|
152
|
+
impl(atomic_uchar, Send());
|
|
153
|
+
impl(atomic_uchar, Acyclic());
|
|
154
|
+
impl(atomic_short, Send());
|
|
155
|
+
impl(atomic_short, Acyclic());
|
|
156
|
+
impl(atomic_ushort, Send());
|
|
157
|
+
impl(atomic_ushort, Acyclic());
|
|
158
|
+
impl(atomic_int, Send());
|
|
159
|
+
impl(atomic_int, Acyclic());
|
|
160
|
+
impl(atomic_uint, Send());
|
|
161
|
+
impl(atomic_uint, Acyclic());
|
|
162
|
+
impl(atomic_long, Send());
|
|
163
|
+
impl(atomic_long, Acyclic());
|
|
164
|
+
impl(atomic_ulong, Send());
|
|
165
|
+
impl(atomic_ulong, Acyclic());
|
|
166
|
+
impl(atomic_llong, Send());
|
|
167
|
+
impl(atomic_llong, Acyclic());
|
|
168
|
+
impl(atomic_ullong, Send());
|
|
169
|
+
impl(atomic_ullong, Acyclic());
|
|
170
|
+
impl(atomic_char16_t, Send());
|
|
171
|
+
impl(atomic_char16_t, Acyclic());
|
|
172
|
+
impl(atomic_char32_t, Send());
|
|
173
|
+
impl(atomic_char32_t, Acyclic());
|
|
174
|
+
impl(atomic_wchar_t, Send());
|
|
175
|
+
impl(atomic_wchar_t, Acyclic());
|
|
176
|
+
impl(atomic_int_least8_t, Send());
|
|
177
|
+
impl(atomic_int_least8_t, Acyclic());
|
|
178
|
+
impl(atomic_uint_least8_t, Send());
|
|
179
|
+
impl(atomic_uint_least8_t, Acyclic());
|
|
180
|
+
impl(atomic_int_least16_t, Send());
|
|
181
|
+
impl(atomic_int_least16_t, Acyclic());
|
|
182
|
+
impl(atomic_uint_least16_t, Send());
|
|
183
|
+
impl(atomic_uint_least16_t, Acyclic());
|
|
184
|
+
impl(atomic_int_least32_t, Send());
|
|
185
|
+
impl(atomic_int_least32_t, Acyclic());
|
|
186
|
+
impl(atomic_uint_least32_t, Send());
|
|
187
|
+
impl(atomic_uint_least32_t, Acyclic());
|
|
188
|
+
impl(atomic_int_least64_t, Send());
|
|
189
|
+
impl(atomic_int_least64_t, Acyclic());
|
|
190
|
+
impl(atomic_uint_least64_t, Send());
|
|
191
|
+
impl(atomic_uint_least64_t, Acyclic());
|
|
192
|
+
impl(atomic_int_fast8_t, Send());
|
|
193
|
+
impl(atomic_int_fast8_t, Acyclic());
|
|
194
|
+
impl(atomic_uint_fast8_t, Send());
|
|
195
|
+
impl(atomic_uint_fast8_t, Acyclic());
|
|
196
|
+
impl(atomic_int_fast16_t, Send());
|
|
197
|
+
impl(atomic_int_fast16_t, Acyclic());
|
|
198
|
+
impl(atomic_uint_fast16_t, Send());
|
|
199
|
+
impl(atomic_uint_fast16_t, Acyclic());
|
|
200
|
+
impl(atomic_int_fast32_t, Send());
|
|
201
|
+
impl(atomic_int_fast32_t, Acyclic());
|
|
202
|
+
impl(atomic_uint_fast32_t, Send());
|
|
203
|
+
impl(atomic_uint_fast32_t, Acyclic());
|
|
204
|
+
impl(atomic_int_fast64_t, Send());
|
|
205
|
+
impl(atomic_int_fast64_t, Acyclic());
|
|
206
|
+
impl(atomic_uint_fast64_t, Send());
|
|
207
|
+
impl(atomic_uint_fast64_t, Acyclic());
|
|
208
|
+
impl(atomic_intptr_t, Send());
|
|
209
|
+
impl(atomic_intptr_t, Acyclic());
|
|
210
|
+
impl(atomic_uintptr_t, Send());
|
|
211
|
+
impl(atomic_uintptr_t, Acyclic());
|
|
212
|
+
impl(atomic_size_t, Send());
|
|
213
|
+
impl(atomic_size_t, Acyclic());
|
|
214
|
+
impl(atomic_ptrdiff_t, Send());
|
|
215
|
+
impl(atomic_ptrdiff_t, Acyclic());
|
|
216
|
+
impl(atomic_intmax_t, Send());
|
|
217
|
+
impl(atomic_intmax_t, Acyclic());
|
|
218
|
+
impl(atomic_uintmax_t, Send());
|
|
219
|
+
impl(atomic_uintmax_t, Acyclic());
|
|
220
|
+
// Phase C (THREAD_SAFETY): int-specific atomic operations. The c_include
|
|
221
|
+
// block only declares load/store/exchange for atomic_bool. These Yo-runtime
|
|
222
|
+
// wrappers forward to the C11 _Generic macros in <stdatomic.h> so AtomicI32
|
|
223
|
+
// can use the full atomic API.
|
|
224
|
+
extern(
|
|
225
|
+
"Yo",
|
|
226
|
+
__yo_atomic_load_int :
|
|
227
|
+
fn(obj : *(atomic_int), order : memory_order) -> i32,
|
|
228
|
+
__yo_atomic_store_int :
|
|
229
|
+
fn(obj : *(atomic_int), desired : i32, order : memory_order) -> unit,
|
|
230
|
+
__yo_atomic_exchange_int :
|
|
231
|
+
fn(obj : *(atomic_int), desired : i32, order : memory_order) -> i32,
|
|
232
|
+
__yo_atomic_compare_exchange_int :
|
|
233
|
+
fn(
|
|
234
|
+
obj : *(atomic_int),
|
|
235
|
+
expected : *(i32),
|
|
236
|
+
desired : i32,
|
|
237
|
+
success : memory_order,
|
|
238
|
+
failure : memory_order
|
|
239
|
+
) -> bool
|
|
240
|
+
);
|
|
241
|
+
// Phase C: size_t-specific atomic operations (for AtomicUsize)
|
|
242
|
+
extern(
|
|
243
|
+
"Yo",
|
|
244
|
+
__yo_atomic_load_size_t :
|
|
245
|
+
fn(obj : *(atomic_size_t), order : memory_order) -> usize,
|
|
246
|
+
__yo_atomic_store_size_t :
|
|
247
|
+
fn(obj : *(atomic_size_t), desired : usize, order : memory_order) -> unit,
|
|
248
|
+
__yo_atomic_exchange_size_t :
|
|
249
|
+
fn(obj : *(atomic_size_t), desired : usize, order : memory_order) -> usize,
|
|
250
|
+
__yo_atomic_compare_exchange_size_t :
|
|
251
|
+
fn(
|
|
252
|
+
obj : *(atomic_size_t),
|
|
253
|
+
expected : *(usize),
|
|
254
|
+
desired : usize,
|
|
255
|
+
success : memory_order,
|
|
256
|
+
failure : memory_order
|
|
257
|
+
) -> bool
|
|
258
|
+
);
|
|
259
|
+
// Phase C: long-long-specific atomic operations (for AtomicI64)
|
|
260
|
+
extern(
|
|
261
|
+
"Yo",
|
|
262
|
+
__yo_atomic_load_llong :
|
|
263
|
+
fn(obj : *(atomic_llong), order : memory_order) -> i64,
|
|
264
|
+
__yo_atomic_store_llong :
|
|
265
|
+
fn(obj : *(atomic_llong), desired : i64, order : memory_order) -> unit,
|
|
266
|
+
__yo_atomic_exchange_llong :
|
|
267
|
+
fn(obj : *(atomic_llong), desired : i64, order : memory_order) -> i64,
|
|
268
|
+
__yo_atomic_compare_exchange_llong :
|
|
269
|
+
fn(
|
|
270
|
+
obj : *(atomic_llong),
|
|
271
|
+
expected : *(i64),
|
|
272
|
+
desired : i64,
|
|
273
|
+
success : memory_order,
|
|
274
|
+
failure : memory_order
|
|
275
|
+
) -> bool
|
|
276
|
+
);
|
|
277
|
+
// Phase C: remaining atomic type wrappers
|
|
278
|
+
extern(
|
|
279
|
+
"Yo",
|
|
280
|
+
__yo_atomic_load_schar :
|
|
281
|
+
fn(obj : *(atomic_schar), order : memory_order) -> i8,
|
|
282
|
+
__yo_atomic_store_schar :
|
|
283
|
+
fn(obj : *(atomic_schar), desired : i8, order : memory_order) -> unit,
|
|
284
|
+
__yo_atomic_exchange_schar :
|
|
285
|
+
fn(obj : *(atomic_schar), desired : i8, order : memory_order) -> i8,
|
|
286
|
+
__yo_atomic_compare_exchange_schar :
|
|
287
|
+
fn(
|
|
288
|
+
obj : *(atomic_schar),
|
|
289
|
+
expected : *(i8),
|
|
290
|
+
desired : i8,
|
|
291
|
+
success : memory_order,
|
|
292
|
+
failure : memory_order
|
|
293
|
+
) -> bool,
|
|
294
|
+
__yo_atomic_load_short :
|
|
295
|
+
fn(obj : *(atomic_short), order : memory_order) -> i16,
|
|
296
|
+
__yo_atomic_store_short :
|
|
297
|
+
fn(obj : *(atomic_short), desired : i16, order : memory_order) -> unit,
|
|
298
|
+
__yo_atomic_exchange_short :
|
|
299
|
+
fn(obj : *(atomic_short), desired : i16, order : memory_order) -> i16,
|
|
300
|
+
__yo_atomic_compare_exchange_short :
|
|
301
|
+
fn(
|
|
302
|
+
obj : *(atomic_short),
|
|
303
|
+
expected : *(i16),
|
|
304
|
+
desired : i16,
|
|
305
|
+
success : memory_order,
|
|
306
|
+
failure : memory_order
|
|
307
|
+
) -> bool,
|
|
308
|
+
__yo_atomic_load_uchar :
|
|
309
|
+
fn(obj : *(atomic_uchar), order : memory_order) -> u8,
|
|
310
|
+
__yo_atomic_store_uchar :
|
|
311
|
+
fn(obj : *(atomic_uchar), desired : u8, order : memory_order) -> unit,
|
|
312
|
+
__yo_atomic_exchange_uchar :
|
|
313
|
+
fn(obj : *(atomic_uchar), desired : u8, order : memory_order) -> u8,
|
|
314
|
+
__yo_atomic_compare_exchange_uchar :
|
|
315
|
+
fn(
|
|
316
|
+
obj : *(atomic_uchar),
|
|
317
|
+
expected : *(u8),
|
|
318
|
+
desired : u8,
|
|
319
|
+
success : memory_order,
|
|
320
|
+
failure : memory_order
|
|
321
|
+
) -> bool,
|
|
322
|
+
__yo_atomic_load_ushort :
|
|
323
|
+
fn(obj : *(atomic_ushort), order : memory_order) -> u16,
|
|
324
|
+
__yo_atomic_store_ushort :
|
|
325
|
+
fn(obj : *(atomic_ushort), desired : u16, order : memory_order) -> unit,
|
|
326
|
+
__yo_atomic_exchange_ushort :
|
|
327
|
+
fn(obj : *(atomic_ushort), desired : u16, order : memory_order) -> u16,
|
|
328
|
+
__yo_atomic_compare_exchange_ushort :
|
|
329
|
+
fn(
|
|
330
|
+
obj : *(atomic_ushort),
|
|
331
|
+
expected : *(u16),
|
|
332
|
+
desired : u16,
|
|
333
|
+
success : memory_order,
|
|
334
|
+
failure : memory_order
|
|
335
|
+
) -> bool,
|
|
336
|
+
__yo_atomic_load_uint :
|
|
337
|
+
fn(obj : *(atomic_uint), order : memory_order) -> u32,
|
|
338
|
+
__yo_atomic_store_uint :
|
|
339
|
+
fn(obj : *(atomic_uint), desired : u32, order : memory_order) -> unit,
|
|
340
|
+
__yo_atomic_exchange_uint :
|
|
341
|
+
fn(obj : *(atomic_uint), desired : u32, order : memory_order) -> u32,
|
|
342
|
+
__yo_atomic_compare_exchange_uint :
|
|
343
|
+
fn(
|
|
344
|
+
obj : *(atomic_uint),
|
|
345
|
+
expected : *(u32),
|
|
346
|
+
desired : u32,
|
|
347
|
+
success : memory_order,
|
|
348
|
+
failure : memory_order
|
|
349
|
+
) -> bool,
|
|
350
|
+
__yo_atomic_load_ullong :
|
|
351
|
+
fn(obj : *(atomic_ullong), order : memory_order) -> u64,
|
|
352
|
+
__yo_atomic_store_ullong :
|
|
353
|
+
fn(obj : *(atomic_ullong), desired : u64, order : memory_order) -> unit,
|
|
354
|
+
__yo_atomic_exchange_ullong :
|
|
355
|
+
fn(obj : *(atomic_ullong), desired : u64, order : memory_order) -> u64,
|
|
356
|
+
__yo_atomic_compare_exchange_ullong :
|
|
357
|
+
fn(
|
|
358
|
+
obj : *(atomic_ullong),
|
|
359
|
+
expected : *(u64),
|
|
360
|
+
desired : u64,
|
|
361
|
+
success : memory_order,
|
|
362
|
+
failure : memory_order
|
|
363
|
+
) -> bool,
|
|
364
|
+
__yo_atomic_load_ptrdiff :
|
|
365
|
+
fn(obj : *(atomic_ptrdiff_t), order : memory_order) -> isize,
|
|
366
|
+
__yo_atomic_store_ptrdiff :
|
|
367
|
+
fn(obj : *(atomic_ptrdiff_t), desired : isize, order : memory_order) -> unit,
|
|
368
|
+
__yo_atomic_exchange_ptrdiff :
|
|
369
|
+
fn(obj : *(atomic_ptrdiff_t), desired : isize, order : memory_order) -> isize,
|
|
370
|
+
__yo_atomic_compare_exchange_ptrdiff :
|
|
371
|
+
fn(
|
|
372
|
+
obj : *(atomic_ptrdiff_t),
|
|
373
|
+
expected : *(isize),
|
|
374
|
+
desired : isize,
|
|
375
|
+
success : memory_order,
|
|
376
|
+
failure : memory_order
|
|
377
|
+
) -> bool
|
|
378
|
+
);
|
|
141
379
|
export(
|
|
142
380
|
// Atomic types
|
|
143
381
|
atomic_bool,
|
|
@@ -238,5 +476,51 @@ export(
|
|
|
238
476
|
ATOMIC_LLONG_LOCK_FREE,
|
|
239
477
|
ATOMIC_POINTER_LOCK_FREE,
|
|
240
478
|
// Kill dependency
|
|
241
|
-
kill_dependency
|
|
479
|
+
kill_dependency,
|
|
480
|
+
// Phase C (THREAD_SAFETY): int-specific atomic wrappers
|
|
481
|
+
__yo_atomic_load_int,
|
|
482
|
+
__yo_atomic_store_int,
|
|
483
|
+
__yo_atomic_exchange_int,
|
|
484
|
+
__yo_atomic_compare_exchange_int,
|
|
485
|
+
// Phase C: size_t atomic wrappers
|
|
486
|
+
__yo_atomic_load_size_t,
|
|
487
|
+
__yo_atomic_store_size_t,
|
|
488
|
+
__yo_atomic_exchange_size_t,
|
|
489
|
+
__yo_atomic_compare_exchange_size_t,
|
|
490
|
+
// Phase C: llong atomic wrappers
|
|
491
|
+
__yo_atomic_load_llong,
|
|
492
|
+
__yo_atomic_store_llong,
|
|
493
|
+
__yo_atomic_exchange_llong,
|
|
494
|
+
__yo_atomic_compare_exchange_llong,
|
|
495
|
+
// Phase C: signed narrow atomics
|
|
496
|
+
__yo_atomic_load_schar,
|
|
497
|
+
__yo_atomic_store_schar,
|
|
498
|
+
__yo_atomic_exchange_schar,
|
|
499
|
+
__yo_atomic_compare_exchange_schar,
|
|
500
|
+
__yo_atomic_load_short,
|
|
501
|
+
__yo_atomic_store_short,
|
|
502
|
+
__yo_atomic_exchange_short,
|
|
503
|
+
__yo_atomic_compare_exchange_short,
|
|
504
|
+
// Phase C: unsigned atomics
|
|
505
|
+
__yo_atomic_load_uchar,
|
|
506
|
+
__yo_atomic_store_uchar,
|
|
507
|
+
__yo_atomic_exchange_uchar,
|
|
508
|
+
__yo_atomic_compare_exchange_uchar,
|
|
509
|
+
__yo_atomic_load_ushort,
|
|
510
|
+
__yo_atomic_store_ushort,
|
|
511
|
+
__yo_atomic_exchange_ushort,
|
|
512
|
+
__yo_atomic_compare_exchange_ushort,
|
|
513
|
+
__yo_atomic_load_uint,
|
|
514
|
+
__yo_atomic_store_uint,
|
|
515
|
+
__yo_atomic_exchange_uint,
|
|
516
|
+
__yo_atomic_compare_exchange_uint,
|
|
517
|
+
__yo_atomic_load_ullong,
|
|
518
|
+
__yo_atomic_store_ullong,
|
|
519
|
+
__yo_atomic_exchange_ullong,
|
|
520
|
+
__yo_atomic_compare_exchange_ullong,
|
|
521
|
+
// Phase C: isize
|
|
522
|
+
__yo_atomic_load_ptrdiff,
|
|
523
|
+
__yo_atomic_store_ptrdiff,
|
|
524
|
+
__yo_atomic_exchange_ptrdiff,
|
|
525
|
+
__yo_atomic_compare_exchange_ptrdiff
|
|
242
526
|
);
|
package/std/prelude.yo
CHANGED
|
@@ -59,7 +59,17 @@ Pragma :: enum(
|
|
|
59
59
|
/// Test-runner directive: skip when target is wasm32-emscripten.
|
|
60
60
|
SkipWasm32Emscripten,
|
|
61
61
|
/// Test-runner directive: skip when target is wasm32-wasi.
|
|
62
|
-
SkipWasm32Wasi
|
|
62
|
+
SkipWasm32Wasi,
|
|
63
|
+
/// Formal verification: contracts in this file are proof obligations.
|
|
64
|
+
/// Phase 0 only registers the pragma; later phases will hook in
|
|
65
|
+
/// verification. See plans/FORMAL_VERIFICATION.md.
|
|
66
|
+
Verify,
|
|
67
|
+
/// Formal verification: try to prove, fall back to runtime assert
|
|
68
|
+
/// when proof times out. The production mode for verified code.
|
|
69
|
+
VerifyOrAssert,
|
|
70
|
+
/// Formal verification: erase contract clauses entirely (no proof,
|
|
71
|
+
/// no runtime assert). For release/benchmark builds.
|
|
72
|
+
NoContracts
|
|
63
73
|
);
|
|
64
74
|
export(Pragma);
|
|
65
75
|
|
|
@@ -732,6 +742,13 @@ ComptimeToString :: trait(
|
|
|
732
742
|
to_comptime_string : (fn(comptime(self) : Self) -> comptime(comptime_string)),
|
|
733
743
|
where(Self <: Comptime)
|
|
734
744
|
);
|
|
745
|
+
// SAFETY: All builtin primitive types (unit, void, comptime_int,
|
|
746
|
+
// comptime_float, comptime_string, bool, i8/i16/i32/i64, u8/u16/u32/u64,
|
|
747
|
+
// f32/f64, isize/usize, char/int/uint/short/ushort/long/ulong/longlong/
|
|
748
|
+
// ulonglong/longdouble) are plain value types with no heap allocations
|
|
749
|
+
// or thread-local state. They are trivially safe to send across threads
|
|
750
|
+
// and cannot form reference cycles. For these types, Send and Acyclic are
|
|
751
|
+
// structural properties of the underlying C types.
|
|
735
752
|
// === Builtin types ===
|
|
736
753
|
/// unit
|
|
737
754
|
impl(unit, Acyclic());
|
|
@@ -5475,6 +5492,11 @@ impl(
|
|
|
5475
5492
|
_longdouble :: longdouble;
|
|
5476
5493
|
export(longdouble : _longdouble);
|
|
5477
5494
|
/// Ptr
|
|
5495
|
+
// SAFETY: A raw pointer *(T) is Send only when the pointee T is Send —
|
|
5496
|
+
// the pointer itself is a plain value (an address), and Send implies
|
|
5497
|
+
// that any T reachable through it is safe to access from another thread.
|
|
5498
|
+
// *(T) is unconditionally Acyclic because raw pointers do not participate
|
|
5499
|
+
// in Yo's ARC reference-counting cycle analysis.
|
|
5478
5500
|
impl(forall(T : Type), where(T <: Send), *(T), Send());
|
|
5479
5501
|
impl(forall(T : Type), *(T), Acyclic());
|
|
5480
5502
|
impl(forall(T : Type), where(T <: Comptime), *(T), Comptime());
|
|
@@ -5536,6 +5558,10 @@ impl(
|
|
|
5536
5558
|
)
|
|
5537
5559
|
);
|
|
5538
5560
|
/// Array
|
|
5561
|
+
// SAFETY: Array(T, U) is a fixed-size array value type. It is Send when T
|
|
5562
|
+
// is Send because an array value is copied across threads (each thread
|
|
5563
|
+
// gets an independent copy). It is unconditionally Acyclic because arrays
|
|
5564
|
+
// are value-typed — they do not participate in ARC reference counting.
|
|
5539
5565
|
impl(forall(T : Type, U : usize), where(T <: Send), Array(T, U), Send());
|
|
5540
5566
|
impl(forall(T : Type, U : usize), Array(T, U), Acyclic());
|
|
5541
5567
|
impl(forall(T : Type, U : usize), where(T <: Comptime), Array(T, U), Comptime());
|
|
@@ -5619,6 +5645,12 @@ impl(
|
|
|
5619
5645
|
)
|
|
5620
5646
|
);
|
|
5621
5647
|
/// Slice
|
|
5648
|
+
// SAFETY: Slice(T) is a value-typed view (pointer + length) over a backing
|
|
5649
|
+
// array. Sending a slice across threads copies the header; both threads
|
|
5650
|
+
// can independently read the backing array. The backing array's lifetime
|
|
5651
|
+
// is managed by its owning collection (which must itself be Send to cross
|
|
5652
|
+
// threads). Slice is always Acyclic — it is a value type with no ARC.
|
|
5653
|
+
impl(forall(T : Type), where(T <: Send), Slice(T), Send());
|
|
5622
5654
|
impl(forall(T : Type), Slice(T), Acyclic());
|
|
5623
5655
|
impl(forall(T : Type), where(T <: Comptime), Slice(T), Comptime());
|
|
5624
5656
|
impl(forall(T : Type), where(T <: Runtime), Slice(T), Runtime());
|
|
@@ -7499,13 +7531,21 @@ export(
|
|
|
7499
7531
|
box
|
|
7500
7532
|
);
|
|
7501
7533
|
/// Iso — an isolated reference-counted value that can be sent across threads.
|
|
7534
|
+
// SAFETY: Iso(T) is unconditionally Send (no `T <: Send` bound) because
|
|
7535
|
+
// Iso's public API exposes no operation on the inner T except extract(),
|
|
7536
|
+
// which atomically verifies rc == 1 before returning. If you add any new
|
|
7537
|
+
// method to Iso(T) that touches the inner T (map, peek, read, &self
|
|
7538
|
+
// borrow, etc.), this Send claim becomes unsound and must be revoked.
|
|
7539
|
+
// See plans/THREAD_SAFETY.md "Iso(T) design notes — precedent and known
|
|
7540
|
+
// risks" for the full argument.
|
|
7502
7541
|
impl(forall(T : Type), Iso(T), Send());
|
|
7503
7542
|
impl(forall(T : Type), where(T <: Acyclic), Iso(T), Acyclic());
|
|
7504
7543
|
impl(
|
|
7505
7544
|
forall(T : Type),
|
|
7506
7545
|
Iso(T),
|
|
7507
|
-
///
|
|
7508
|
-
|
|
7546
|
+
/// Extract the inner value if this `Iso` holds the only reference.
|
|
7547
|
+
/// Panics if rc != 1 or if this Iso has already been extracted.
|
|
7548
|
+
extract : (fn(self : Self) -> T)(
|
|
7509
7549
|
__yo_iso_extract(self)
|
|
7510
7550
|
)
|
|
7511
7551
|
);
|
|
@@ -7581,6 +7621,9 @@ Arc :: (fn(comptime(V) : Type, where(V <: (Send, Acyclic))) -> comptime(Type))(
|
|
|
7581
7621
|
);
|
|
7582
7622
|
/// Allocate a value inside an Arc, returning an `Arc(V)`.
|
|
7583
7623
|
arc :: (fn(forall(V : Type), own(value) : V, where(V <: (Send, Acyclic))) -> Arc(V))(Arc(V)(value));
|
|
7624
|
+
// SAFETY: Arc(T) is an atomic reference-counted wrapper. It is Send when
|
|
7625
|
+
// the inner T is Send (all fields of the atomic-object must be Send per
|
|
7626
|
+
// auto-derive) and Acyclic (prevents permanent leaks from Arc cycles).
|
|
7584
7627
|
impl(forall(T : Type), where(T <: (Send, Acyclic)), Arc(T), Send());
|
|
7585
7628
|
export(Arc, arc);
|
|
7586
7629
|
/// === MaybeUninit ===
|
|
@@ -8325,6 +8368,8 @@ FutureState :: enum(
|
|
|
8325
8368
|
/// The future was aborted (e.g., via `unwind`).
|
|
8326
8369
|
Aborted = -(2)
|
|
8327
8370
|
);
|
|
8371
|
+
// SAFETY: FutureState is a plain enum of integer values (Pending, Done,
|
|
8372
|
+
// Aborted) with no heap allocations. It is trivially Send and Acyclic.
|
|
8328
8373
|
impl(FutureState, Acyclic());
|
|
8329
8374
|
impl(FutureState, Runtime());
|
|
8330
8375
|
impl(FutureState, Send());
|
|
@@ -8345,6 +8390,10 @@ JoinHandle :: (fn(comptime(T) : Type) -> comptime(Type))(
|
|
|
8345
8390
|
__future : *(T)
|
|
8346
8391
|
)
|
|
8347
8392
|
);
|
|
8393
|
+
// Phase L (THREAD_SAFETY): JoinHandle is NOT Send — the inner future state
|
|
8394
|
+
// machine lives on the spawner's event-loop thread. Cross-thread result
|
|
8395
|
+
// delivery uses Channel(T).
|
|
8396
|
+
impl(forall(T : Type), JoinHandle(T), !(Send()));
|
|
8348
8397
|
export(JoinHandle);
|
|
8349
8398
|
/// Io module — the async runtime effect.
|
|
8350
8399
|
///
|
|
@@ -8360,6 +8409,10 @@ Io :: struct(
|
|
|
8360
8409
|
/// Spawn a `Future` as an independent task, returning a `JoinHandle`.
|
|
8361
8410
|
spawn : (fn(forall(T : Type, E : Type.Struct), fut : Impl(Future(T, E)), e : E) -> JoinHandle(T))
|
|
8362
8411
|
);
|
|
8412
|
+
// Phase L (THREAD_SAFETY): Io is NOT Send — the async runtime it represents
|
|
8413
|
+
// is per-thread (per AGENTS.md). Sending Io across a thread boundary would
|
|
8414
|
+
// reference a scheduler on the wrong thread.
|
|
8415
|
+
impl(Io, !(Send()));
|
|
8363
8416
|
export(Io);
|
|
8364
8417
|
extern(
|
|
8365
8418
|
"Yo",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Phase 0 of plans/FORMAL_VERIFICATION.md task #7.
|
|
2
|
+
//
|
|
3
|
+
// Numeric refinement aliases. All Phase 0 implementations are
|
|
4
|
+
// type aliases; the verifier (Phase 2+) will attach concrete
|
|
5
|
+
// predicates and enforce them.
|
|
6
|
+
{ Refine } :: import("./refine.yo");
|
|
7
|
+
|
|
8
|
+
/// Even integer.
|
|
9
|
+
Even :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
10
|
+
export(Even);
|
|
11
|
+
|
|
12
|
+
/// Odd integer.
|
|
13
|
+
Odd :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
14
|
+
export(Odd);
|
|
15
|
+
|
|
16
|
+
/// Strictly positive value (> 0).
|
|
17
|
+
Positive :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
18
|
+
export(Positive);
|
|
19
|
+
|
|
20
|
+
/// Strictly negative value (< 0).
|
|
21
|
+
Negative :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
22
|
+
export(Negative);
|
|
23
|
+
|
|
24
|
+
/// Non-negative value (>= 0).
|
|
25
|
+
NonNegative :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
26
|
+
export(NonNegative);
|
|
27
|
+
|
|
28
|
+
/// Non-positive value (<= 0).
|
|
29
|
+
NonPositive :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
30
|
+
export(NonPositive);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Phase 0 of plans/FORMAL_VERIFICATION.md task #7.
|
|
2
|
+
//
|
|
3
|
+
// `Refine`, `NonZero`, `Bounded` are comptime type constructors.
|
|
4
|
+
// In Phase 0 they all return their underlying type unchanged —
|
|
5
|
+
// effectively `Refine(T) = T`. The refinement predicate is
|
|
6
|
+
// documented as a future parameter; the verifier (Phase 2) will
|
|
7
|
+
// extend the surface to `Refine(T, predicate)` and enforce the
|
|
8
|
+
// predicate at construction sites.
|
|
9
|
+
//
|
|
10
|
+
// Even without enforcement, these aliases serve as
|
|
11
|
+
// human-and-LLM-readable signatures that signal intent. A function
|
|
12
|
+
// taking `denom : NonZero(i32)` documents the precondition; callers
|
|
13
|
+
// that want runtime enforcement can pair the alias with a
|
|
14
|
+
// `requires(denom != i32(0))` clause until the verifier lands.
|
|
15
|
+
/// A value of type `T` paired with a (compile-time) refinement
|
|
16
|
+
/// predicate. Phase 0 ignores the predicate; later phases will
|
|
17
|
+
/// require it as a second parameter and enforce it via
|
|
18
|
+
/// the SMT backend.
|
|
19
|
+
Refine :: (fn(comptime(T) : Type) -> comptime(Type))(T);
|
|
20
|
+
export(Refine);
|
|
21
|
+
|
|
22
|
+
/// `NonZero(T)` — values of `T` that are not zero. Phase 0 is a
|
|
23
|
+
/// type alias for `T`; future phases will enforce via verification.
|
|
24
|
+
NonZero :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
25
|
+
export(NonZero);
|
|
26
|
+
|
|
27
|
+
/// `Bounded(T, lo, hi)` — values of `T` in the closed range
|
|
28
|
+
/// `[lo, hi]`. Phase 0 is a type alias for `T`. T must be `Comptime`
|
|
29
|
+
/// so the bounds can be compile-time-known.
|
|
30
|
+
Bounded :: (
|
|
31
|
+
fn(
|
|
32
|
+
comptime(T) : Type,
|
|
33
|
+
comptime(_lo) : T,
|
|
34
|
+
comptime(_hi) : T,
|
|
35
|
+
where(T <: Comptime)
|
|
36
|
+
) -> comptime(Type)
|
|
37
|
+
)(Refine(T));
|
|
38
|
+
export(Bounded);
|
|
39
|
+
|
|
40
|
+
/// `NonEmpty(T)` — collection types with at least one element.
|
|
41
|
+
/// Phase 0 is a type alias for `T`.
|
|
42
|
+
NonEmpty :: (fn(comptime(T) : Type) -> comptime(Type))(Refine(T));
|
|
43
|
+
export(NonEmpty);
|
package/std/string/rune.yo
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//! Unicode code point type (`rune`) for representing individual characters.
|
|
2
|
+
pragma(Pragma.AllowUnsafe);
|
|
2
3
|
/// Unicode code point (U+0000 to U+10FFFF, excluding surrogates).
|
|
3
4
|
/// Similar to Go's `rune` or Rust's `char`.
|
|
4
5
|
rune :: newtype(
|
|
@@ -93,5 +94,8 @@ impl(
|
|
|
93
94
|
(>=) : ((a, b) -> (a.char >= b.char))
|
|
94
95
|
)
|
|
95
96
|
);
|
|
97
|
+
// SAFETY: rune is a newtype over u32. u32 is a plain value type with no
|
|
98
|
+
// internal heap allocations or thread-local state — it is trivially safe
|
|
99
|
+
// to send across threads.
|
|
96
100
|
impl(rune, Send());
|
|
97
101
|
export(rune);
|