@shd101wyy/yo 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/skills/yo-async-effects/SKILL.md +15 -15
- package/.github/skills/yo-async-effects/async-effects-recipes.md +118 -121
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +33 -13
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +1 -1
- package/.github/skills/yo-syntax/SKILL.md +2 -2
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +108 -96
- package/README.md +6 -3
- package/out/cjs/index.cjs +812 -706
- package/out/cjs/yo-cli.cjs +1023 -907
- package/out/cjs/yo-lsp.cjs +836 -730
- package/out/esm/index.mjs +757 -651
- package/out/types/src/codegen/exprs/async.d.ts +2 -0
- package/out/types/src/codegen/exprs/await.d.ts +1 -0
- package/out/types/src/codegen/exprs/closures.d.ts +4 -0
- package/out/types/src/codegen/functions/context.d.ts +6 -0
- package/out/types/src/codegen/functions/declarations.d.ts +1 -1
- package/out/types/src/doc/model.d.ts +0 -1
- package/out/types/src/env.d.ts +2 -2
- package/out/types/src/evaluator/builtins/pragma.d.ts +9 -0
- package/out/types/src/evaluator/builtins/unsafe.d.ts +8 -0
- package/out/types/src/evaluator/context.d.ts +3 -1
- package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
- package/out/types/src/evaluator/index.d.ts +1 -1
- package/out/types/src/evaluator/memory-safety.d.ts +14 -0
- package/out/types/src/evaluator/types/flowability.d.ts +6 -0
- package/out/types/src/evaluator/types/function.d.ts +1 -2
- package/out/types/src/evaluator/utils.d.ts +0 -1
- package/out/types/src/expr-traversal.d.ts +1 -0
- package/out/types/src/expr.d.ts +9 -7
- package/out/types/src/public-safe-report.d.ts +19 -0
- package/out/types/src/tests/comptime-ref-gate.test.d.ts +1 -0
- package/out/types/src/tests/pragma-validation.test.d.ts +1 -0
- package/out/types/src/tests/public-safe-report.test.d.ts +1 -0
- package/out/types/src/tests/type-representation-pointer.test.d.ts +1 -0
- package/out/types/src/tests/unsafe-gate.test.d.ts +1 -0
- package/out/types/src/tests/unsafe-report-classify.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +4 -6
- package/out/types/src/types/definitions.d.ts +9 -16
- package/out/types/src/types/guards.d.ts +1 -2
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +5 -0
- package/out/types/src/unsafe-report.d.ts +29 -0
- package/out/types/src/value.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/scripts/add-pragma-for-pointer-decls.ts +134 -0
- package/scripts/add-pragma.ts +58 -0
- package/scripts/migrate-amp-method-calls.ts +186 -0
- package/scripts/migrate-clone-calls.ts +93 -0
- package/scripts/migrate-get-unwrap.ts +166 -0
- package/scripts/migrate-index-patterns.ts +210 -0
- package/scripts/migrate-index-trait.ts +142 -0
- package/scripts/migrate-iterator.ts +150 -0
- package/scripts/migrate-self-ptr.ts +220 -0
- package/scripts/migrate-skip-pragmas.ts +109 -0
- package/scripts/migrate-tostring.ts +134 -0
- package/scripts/trim-pragma.ts +130 -0
- package/scripts/wrap-extern-calls.ts +161 -0
- package/std/alg/hash.yo +3 -2
- package/std/allocator.yo +6 -5
- package/std/async.yo +2 -2
- package/std/collections/array_list.yo +59 -40
- package/std/collections/btree_map.yo +19 -18
- package/std/collections/deque.yo +9 -8
- package/std/collections/hash_map.yo +101 -13
- package/std/collections/hash_set.yo +5 -4
- package/std/collections/linked_list.yo +39 -4
- package/std/collections/ordered_map.yo +3 -3
- package/std/collections/priority_queue.yo +14 -13
- package/std/crypto/md5.yo +2 -1
- package/std/crypto/random.yo +21 -20
- package/std/crypto/sha256.yo +2 -1
- package/std/encoding/base64.yo +18 -18
- package/std/encoding/hex.yo +5 -5
- package/std/encoding/json.yo +62 -13
- package/std/encoding/punycode.yo +24 -23
- package/std/encoding/toml.yo +4 -3
- package/std/encoding/utf16.yo +3 -3
- package/std/env.yo +43 -28
- package/std/error.yo +15 -3
- package/std/fmt/display.yo +2 -2
- package/std/fmt/index.yo +6 -5
- package/std/fmt/to_string.yo +39 -38
- package/std/fmt/writer.yo +9 -8
- package/std/fs/dir.yo +61 -66
- package/std/fs/file.yo +121 -126
- package/std/fs/metadata.yo +13 -18
- package/std/fs/temp.yo +35 -30
- package/std/fs/walker.yo +14 -19
- package/std/gc.yo +1 -0
- package/std/glob.yo +7 -7
- package/std/http/client.yo +33 -36
- package/std/http/http.yo +6 -6
- package/std/http/index.yo +4 -4
- package/std/imm/list.yo +33 -0
- package/std/imm/map.yo +2 -1
- package/std/imm/set.yo +1 -0
- package/std/imm/sorted_map.yo +1 -0
- package/std/imm/sorted_set.yo +1 -0
- package/std/imm/string.yo +27 -23
- package/std/imm/vec.yo +18 -2
- package/std/io/reader.yo +2 -1
- package/std/io/writer.yo +3 -2
- package/std/libc/assert.yo +1 -0
- package/std/libc/ctype.yo +1 -0
- package/std/libc/dirent.yo +1 -0
- package/std/libc/errno.yo +1 -0
- package/std/libc/fcntl.yo +1 -0
- package/std/libc/float.yo +1 -0
- package/std/libc/limits.yo +1 -0
- package/std/libc/math.yo +1 -0
- package/std/libc/signal.yo +1 -0
- package/std/libc/stdatomic.yo +1 -0
- package/std/libc/stdint.yo +1 -0
- package/std/libc/stdio.yo +1 -0
- package/std/libc/stdlib.yo +1 -0
- package/std/libc/string.yo +1 -0
- package/std/libc/sys/stat.yo +1 -0
- package/std/libc/time.yo +1 -0
- package/std/libc/unistd.yo +1 -0
- package/std/libc/wctype.yo +1 -0
- package/std/libc/windows.yo +2 -0
- package/std/log.yo +7 -6
- package/std/net/addr.yo +6 -5
- package/std/net/dns.yo +13 -16
- package/std/net/errors.yo +9 -9
- package/std/net/tcp.yo +71 -74
- package/std/net/udp.yo +40 -43
- package/std/os/signal.yo +5 -5
- package/std/path.yo +1 -0
- package/std/prelude.yo +377 -200
- package/std/process/command.yo +57 -46
- package/std/process/index.yo +2 -1
- package/std/regex/compiler.yo +10 -9
- package/std/regex/index.yo +41 -41
- package/std/regex/match.yo +2 -2
- package/std/regex/parser.yo +31 -31
- package/std/regex/vm.yo +42 -41
- package/std/string/string.yo +95 -40
- package/std/string/string_builder.yo +9 -9
- package/std/string/unicode.yo +50 -49
- package/std/sync/channel.yo +2 -1
- package/std/sync/cond.yo +5 -4
- package/std/sync/mutex.yo +4 -3
- package/std/sys/advise.yo +1 -0
- package/std/sys/bufio/buf_reader.yo +27 -26
- package/std/sys/bufio/buf_writer.yo +22 -21
- package/std/sys/clock.yo +1 -0
- package/std/sys/copy.yo +1 -0
- package/std/sys/dir.yo +10 -9
- package/std/sys/dns.yo +6 -5
- package/std/sys/errors.yo +12 -12
- package/std/sys/events.yo +1 -0
- package/std/sys/externs.yo +38 -37
- package/std/sys/file.yo +17 -16
- package/std/sys/future.yo +4 -3
- package/std/sys/iov.yo +1 -0
- package/std/sys/mmap.yo +1 -0
- package/std/sys/path.yo +1 -0
- package/std/sys/perm.yo +2 -1
- package/std/sys/pipe.yo +1 -0
- package/std/sys/process.yo +5 -4
- package/std/sys/signal.yo +1 -0
- package/std/sys/socketpair.yo +1 -0
- package/std/sys/sockinfo.yo +1 -0
- package/std/sys/statfs.yo +2 -1
- package/std/sys/statx.yo +1 -0
- package/std/sys/sysinfo.yo +1 -0
- package/std/sys/tcp.yo +15 -14
- package/std/sys/temp.yo +1 -0
- package/std/sys/time.yo +2 -1
- package/std/sys/timer.yo +6 -6
- package/std/sys/tty.yo +2 -1
- package/std/sys/udp.yo +13 -12
- package/std/sys/unix.yo +12 -11
- package/std/testing/bench.yo +4 -3
- package/std/thread.yo +7 -6
- package/std/time/datetime.yo +18 -15
- package/std/time/duration.yo +11 -10
- package/std/time/instant.yo +4 -4
- package/std/time/sleep.yo +1 -0
- package/std/url/index.yo +5 -5
- package/std/worker.yo +4 -3
package/std/string/string.yo
CHANGED
|
@@ -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
|
-
|
|
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 :
|
|
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
|
|
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
|
|
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 :
|
|
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
|
|
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
|
|
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 :
|
|
375
|
+
push_byte : (fn(ref(self) : Self, b : u8) -> unit)({
|
|
370
376
|
match(
|
|
371
|
-
self
|
|
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
|
|
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 :
|
|
390
|
+
reserve : (fn(ref(self) : Self, additional : usize) -> unit)({
|
|
385
391
|
match(
|
|
386
|
-
self
|
|
392
|
+
self._bytes,
|
|
387
393
|
.None => {
|
|
388
|
-
self
|
|
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 :
|
|
403
|
+
clear : (fn(ref(self) : Self) -> unit)(
|
|
398
404
|
match(
|
|
399
|
-
self
|
|
405
|
+
self._bytes,
|
|
400
406
|
.Some(al) => al.clear(),
|
|
401
407
|
.None => ()
|
|
402
408
|
)
|
|
403
409
|
),
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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 :
|
|
1421
|
+
(hash) : (fn(ref(self) : Self) -> u64)({
|
|
1424
1422
|
h := u64(14695981039346656037);
|
|
1425
1423
|
match(
|
|
1426
|
-
self
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
2151
|
+
index : (fn(ref(self) : Self, idx : usize) -> *(Self.Output))(
|
|
2118
2152
|
match(
|
|
2119
|
-
self
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
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 :
|
|
159
|
+
clear : (fn(self : Self) -> unit)({
|
|
160
160
|
self._buf = ArrayList(u8).new();
|
|
161
161
|
})
|
|
162
162
|
);
|
package/std/string/unicode.yo
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
43
|
-
(b2 : i32) = i32(bytes
|
|
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
|
|
50
|
-
(b2 : i32) = i32(bytes
|
|
51
|
-
(b3 : i32) = i32(bytes
|
|
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 :
|
|
59
|
+
_encode_utf8 :: (fn(cp : i32, out : ArrayList(u8)) -> unit)({
|
|
59
60
|
cond(
|
|
60
61
|
(cp < i32(0x80)) => {
|
|
61
|
-
out
|
|
62
|
+
out.push(u8(cp));
|
|
62
63
|
},
|
|
63
64
|
(cp < i32(0x800)) => {
|
|
64
|
-
out
|
|
65
|
-
out
|
|
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
|
|
69
|
-
out
|
|
70
|
-
out
|
|
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
|
|
74
|
-
out
|
|
75
|
-
out
|
|
76
|
-
out
|
|
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 :
|
|
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
|
|
87
|
-
out
|
|
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
|
|
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 :
|
|
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
|
|
107
|
-
out
|
|
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
|
|
113
|
-
out
|
|
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
|
|
119
|
-
out
|
|
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
|
|
125
|
-
out
|
|
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
|
|
131
|
-
out
|
|
132
|
-
out
|
|
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
|
|
138
|
-
out
|
|
139
|
-
out
|
|
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
|
|
145
|
-
out
|
|
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
|
|
151
|
-
out
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
216
|
+
(upper : i32) = i32(unsafe(towupper(cp)));
|
|
217
|
+
_encode_utf8(upper, out);
|
|
217
218
|
});
|
|
218
219
|
i = (i + len);
|
|
219
220
|
});
|
package/std/sync/channel.yo
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//! Bounded multi-producer multi-consumer (MPMC) channel.
|
|
2
|
-
//! Uses blocking send/recv via condition variables — does not require
|
|
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 :
|
|
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 :
|
|
27
|
+
signal : (fn(ref(self) : Self) -> unit)({
|
|
27
28
|
return(__yo_cond_signal(&(self.cv)));
|
|
28
29
|
}),
|
|
29
|
-
broadcast : (fn(self :
|
|
30
|
+
broadcast : (fn(ref(self) : Self) -> unit)({
|
|
30
31
|
return(__yo_cond_broadcast(&(self.cv)));
|
|
31
32
|
}),
|
|
32
|
-
destroy : (fn(self :
|
|
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 :
|
|
22
|
+
lock : (fn(ref(self) : Self) -> unit)({
|
|
22
23
|
return(__yo_mutex_lock(&(self.mutex)));
|
|
23
24
|
}),
|
|
24
|
-
unlock : (fn(self :
|
|
25
|
+
unlock : (fn(ref(self) : Self) -> unit)({
|
|
25
26
|
return(__yo_mutex_unlock(&(self.mutex)));
|
|
26
27
|
}),
|
|
27
|
-
destroy : (fn(self :
|
|
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);
|