@shd101wyy/yo 0.1.26 → 0.1.27
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 +4 -4
- package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
- package/.github/skills/yo-core-patterns/SKILL.md +1 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -26
- package/.github/skills/yo-project-workflow/SKILL.md +6 -3
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
- package/.github/skills/yo-syntax/SKILL.md +7 -6
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +73 -60
- package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
- package/README.md +10 -8
- package/out/cjs/index.cjs +456 -438
- package/out/cjs/yo-cli.cjs +576 -543
- package/out/cjs/yo-lsp.cjs +559 -532
- package/out/esm/index.mjs +281 -263
- package/out/types/src/formatter.d.ts +11 -0
- package/out/types/src/lsp/formatting.d.ts +2 -0
- package/out/types/src/tests/formatter.test.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/alg/hash.yo +13 -21
- package/std/allocator.yo +25 -40
- package/std/async.yo +3 -7
- package/std/build.yo +105 -151
- package/std/cli/arg_parser.yo +184 -169
- package/std/collections/array_list.yo +350 -314
- package/std/collections/btree_map.yo +142 -131
- package/std/collections/deque.yo +132 -128
- package/std/collections/hash_map.yo +542 -566
- package/std/collections/hash_set.yo +623 -687
- package/std/collections/linked_list.yo +275 -293
- package/std/collections/ordered_map.yo +113 -85
- package/std/collections/priority_queue.yo +73 -73
- package/std/crypto/md5.yo +191 -95
- package/std/crypto/random.yo +56 -64
- package/std/crypto/sha256.yo +151 -107
- package/std/encoding/base64.yo +87 -81
- package/std/encoding/hex.yo +43 -50
- package/std/encoding/html.yo +56 -81
- package/std/encoding/html_char_utils.yo +7 -13
- package/std/encoding/html_entities.yo +2248 -2253
- package/std/encoding/json.yo +316 -224
- package/std/encoding/punycode.yo +86 -116
- package/std/encoding/toml.yo +67 -66
- package/std/encoding/utf16.yo +37 -44
- package/std/env.yo +62 -91
- package/std/error.yo +7 -15
- package/std/fmt/display.yo +5 -9
- package/std/fmt/index.yo +8 -14
- package/std/fmt/to_string.yo +330 -315
- package/std/fmt/writer.yo +58 -87
- package/std/fs/dir.yo +83 -102
- package/std/fs/file.yo +147 -180
- package/std/fs/metadata.yo +45 -78
- package/std/fs/temp.yo +55 -65
- package/std/fs/types.yo +27 -40
- package/std/fs/walker.yo +53 -68
- package/std/gc.yo +5 -8
- package/std/glob.yo +30 -43
- package/std/http/client.yo +107 -120
- package/std/http/http.yo +106 -96
- package/std/http/index.yo +4 -6
- package/std/imm/list.yo +88 -93
- package/std/imm/map.yo +528 -464
- package/std/imm/set.yo +52 -57
- package/std/imm/sorted_map.yo +340 -286
- package/std/imm/sorted_set.yo +57 -63
- package/std/imm/string.yo +404 -345
- package/std/imm/vec.yo +173 -181
- package/std/io/reader.yo +3 -6
- package/std/io/writer.yo +4 -8
- package/std/libc/assert.yo +5 -9
- package/std/libc/ctype.yo +32 -22
- package/std/libc/dirent.yo +26 -25
- package/std/libc/errno.yo +164 -90
- package/std/libc/fcntl.yo +52 -45
- package/std/libc/float.yo +66 -44
- package/std/libc/limits.yo +42 -33
- package/std/libc/math.yo +53 -82
- package/std/libc/signal.yo +72 -47
- package/std/libc/stdatomic.yo +217 -188
- package/std/libc/stdint.yo +5 -29
- package/std/libc/stdio.yo +5 -29
- package/std/libc/stdlib.yo +32 -39
- package/std/libc/string.yo +5 -23
- package/std/libc/sys/stat.yo +58 -56
- package/std/libc/time.yo +5 -19
- package/std/libc/unistd.yo +5 -20
- package/std/libc/wctype.yo +6 -9
- package/std/libc/windows.yo +26 -30
- package/std/log.yo +41 -55
- package/std/net/addr.yo +102 -97
- package/std/net/dns.yo +27 -28
- package/std/net/errors.yo +50 -49
- package/std/net/tcp.yo +113 -124
- package/std/net/udp.yo +55 -66
- package/std/os/env.yo +35 -33
- package/std/os/signal.yo +15 -25
- package/std/path.yo +276 -311
- package/std/prelude.yo +6304 -4315
- package/std/process/command.yo +87 -103
- package/std/process/index.yo +12 -31
- package/std/regex/compiler.yo +196 -95
- package/std/regex/flags.yo +58 -39
- package/std/regex/index.yo +157 -173
- package/std/regex/match.yo +20 -31
- package/std/regex/node.yo +134 -152
- package/std/regex/parser.yo +283 -259
- package/std/regex/unicode.yo +172 -202
- package/std/regex/vm.yo +155 -171
- package/std/string/index.yo +5 -7
- package/std/string/rune.yo +45 -55
- package/std/string/string.yo +937 -964
- package/std/string/string_builder.yo +94 -104
- package/std/string/unicode.yo +46 -64
- package/std/sync/channel.yo +72 -73
- package/std/sync/cond.yo +31 -36
- package/std/sync/mutex.yo +30 -32
- package/std/sync/once.yo +13 -16
- package/std/sync/rwlock.yo +26 -31
- package/std/sync/waitgroup.yo +20 -25
- package/std/sys/advise.yo +16 -24
- package/std/sys/bufio/buf_reader.yo +77 -93
- package/std/sys/bufio/buf_writer.yo +52 -65
- package/std/sys/clock.yo +4 -9
- package/std/sys/constants.yo +77 -61
- package/std/sys/copy.yo +4 -10
- package/std/sys/dir.yo +26 -43
- package/std/sys/dns.yo +41 -61
- package/std/sys/errors.yo +95 -103
- package/std/sys/events.yo +45 -57
- package/std/sys/externs.yo +319 -267
- package/std/sys/fallocate.yo +7 -11
- package/std/sys/fcntl.yo +14 -22
- package/std/sys/file.yo +26 -40
- package/std/sys/future.yo +5 -8
- package/std/sys/iov.yo +12 -25
- package/std/sys/lock.yo +12 -13
- package/std/sys/mmap.yo +38 -43
- package/std/sys/path.yo +3 -8
- package/std/sys/perm.yo +7 -21
- package/std/sys/pipe.yo +5 -12
- package/std/sys/process.yo +23 -29
- package/std/sys/seek.yo +10 -12
- package/std/sys/signal.yo +7 -13
- package/std/sys/signals.yo +52 -35
- package/std/sys/socket.yo +63 -58
- package/std/sys/socketpair.yo +3 -6
- package/std/sys/sockinfo.yo +11 -20
- package/std/sys/statfs.yo +11 -34
- package/std/sys/statx.yo +25 -52
- package/std/sys/sysinfo.yo +15 -20
- package/std/sys/tcp.yo +62 -92
- package/std/sys/temp.yo +5 -9
- package/std/sys/time.yo +5 -15
- package/std/sys/timer.yo +6 -11
- package/std/sys/tty.yo +10 -18
- package/std/sys/udp.yo +22 -39
- package/std/sys/umask.yo +3 -6
- package/std/sys/unix.yo +33 -52
- package/std/testing/bench.yo +49 -52
- package/std/thread.yo +10 -15
- package/std/time/datetime.yo +105 -89
- package/std/time/duration.yo +43 -56
- package/std/time/instant.yo +13 -18
- package/std/time/sleep.yo +5 -9
- package/std/url/index.yo +184 -209
- package/std/worker.yo +6 -10
package/std/sys/unix.yo
CHANGED
|
@@ -3,132 +3,113 @@
|
|
|
3
3
|
//! Provides Unix domain socket wrappers around the low-level C runtime externs.
|
|
4
4
|
//! Reuses the socket ops (bind/listen/accept/connect/send/recv/close) from the
|
|
5
5
|
//! generic socket externs. Uses `sockaddr_un` helpers to build address buffers.
|
|
6
|
-
|
|
7
|
-
{ GlobalAllocator } :: import "../allocator.yo";
|
|
6
|
+
{ GlobalAllocator } :: import("../allocator.yo");
|
|
8
7
|
{ malloc, free } :: GlobalAllocator;
|
|
9
|
-
{ IOFuture } :: import
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
__yo_async_listen_start, __yo_async_accept_start,
|
|
13
|
-
__yo_async_connect_start, __yo_async_send_start,
|
|
14
|
-
__yo_async_recv_start, __yo_async_close_start,
|
|
15
|
-
__yo_sockaddr_un_set_path,
|
|
16
|
-
__yo_sockaddr_un_get_path, __yo_sockaddr_set_family
|
|
17
|
-
} :: import "./externs.yo";
|
|
18
|
-
{
|
|
19
|
-
AF_UNIX, SOCK_STREAM, SOCK_DGRAM,
|
|
20
|
-
sockaddr_un_size
|
|
21
|
-
} :: import "./socket.yo";
|
|
22
|
-
|
|
8
|
+
{ IOFuture } :: import("./future.yo");
|
|
9
|
+
{ __yo_async_socket_start, __yo_async_bind_start, __yo_async_listen_start, __yo_async_accept_start, __yo_async_connect_start, __yo_async_send_start, __yo_async_recv_start, __yo_async_close_start, __yo_sockaddr_un_set_path, __yo_sockaddr_un_get_path, __yo_sockaddr_set_family } :: import("./externs.yo");
|
|
10
|
+
{ AF_UNIX, SOCK_STREAM, SOCK_DGRAM, sockaddr_un_size } :: import("./socket.yo");
|
|
23
11
|
// ============================================================================
|
|
24
12
|
// UnixAddr - sockaddr_un buffer with pointer and length
|
|
25
13
|
// ============================================================================
|
|
26
|
-
|
|
27
14
|
UnixAddr :: struct(
|
|
28
15
|
buf : ?*(u8),
|
|
29
16
|
len : u32
|
|
30
17
|
);
|
|
31
|
-
export
|
|
32
|
-
|
|
18
|
+
export(UnixAddr);
|
|
33
19
|
// ============================================================================
|
|
34
20
|
// Core Unix Socket Operations (return IOFuture, use with await)
|
|
35
21
|
// ============================================================================
|
|
36
|
-
|
|
37
22
|
// Create a Unix domain socket (SOCK_STREAM).
|
|
38
23
|
// Returns fd on success, -errno on failure.
|
|
39
24
|
socket_stream :: (fn() -> IOFuture)(
|
|
40
25
|
__yo_async_socket_start(AF_UNIX, SOCK_STREAM, i32(0))
|
|
41
26
|
);
|
|
42
|
-
|
|
43
27
|
// Create a Unix domain socket (SOCK_DGRAM).
|
|
44
28
|
// Returns fd on success, -errno on failure.
|
|
45
29
|
socket_dgram :: (fn() -> IOFuture)(
|
|
46
30
|
__yo_async_socket_start(AF_UNIX, SOCK_DGRAM, i32(0))
|
|
47
31
|
);
|
|
48
|
-
|
|
49
32
|
// Bind a socket to a local Unix address.
|
|
50
33
|
// Returns 0 on success, -errno on failure.
|
|
51
|
-
bind :: (fn(sockfd: i32, addr: *(u8), addrlen: u32) -> IOFuture)(
|
|
34
|
+
bind :: (fn(sockfd : i32, addr : *(u8), addrlen : u32) -> IOFuture)(
|
|
52
35
|
__yo_async_bind_start(sockfd, addr, addrlen)
|
|
53
36
|
);
|
|
54
|
-
|
|
55
37
|
// Listen for incoming connections on a Unix socket.
|
|
56
38
|
// Returns 0 on success, -errno on failure.
|
|
57
|
-
listen :: (fn(sockfd: i32, backlog: i32) -> IOFuture)(
|
|
39
|
+
listen :: (fn(sockfd : i32, backlog : i32) -> IOFuture)(
|
|
58
40
|
__yo_async_listen_start(sockfd, backlog)
|
|
59
41
|
);
|
|
60
|
-
|
|
61
42
|
// Accept an incoming connection.
|
|
62
43
|
// Returns fd on success, -errno on failure.
|
|
63
|
-
accept :: (fn(sockfd: i32, addr: *(u8), addrlen: *(u32)) -> IOFuture)(
|
|
44
|
+
accept :: (fn(sockfd : i32, addr : *(u8), addrlen : *(u32)) -> IOFuture)(
|
|
64
45
|
__yo_async_accept_start(sockfd, addr, addrlen)
|
|
65
46
|
);
|
|
66
|
-
|
|
67
47
|
// Connect to a Unix socket address.
|
|
68
48
|
// Returns 0 on success, -errno on failure.
|
|
69
|
-
connect :: (fn(sockfd: i32, addr: *(u8), addrlen: u32) -> IOFuture)(
|
|
49
|
+
connect :: (fn(sockfd : i32, addr : *(u8), addrlen : u32) -> IOFuture)(
|
|
70
50
|
__yo_async_connect_start(sockfd, addr, addrlen)
|
|
71
51
|
);
|
|
72
|
-
|
|
73
52
|
// Send data on a connected Unix socket.
|
|
74
53
|
// Returns number of bytes sent on success, -errno on failure.
|
|
75
|
-
send :: (fn(sockfd: i32, buf: *(u8), len: usize, flags: i32) -> IOFuture)(
|
|
54
|
+
send :: (fn(sockfd : i32, buf : *(u8), len : usize, flags : i32) -> IOFuture)(
|
|
76
55
|
__yo_async_send_start(sockfd, buf, len, flags)
|
|
77
56
|
);
|
|
78
|
-
|
|
79
57
|
// Receive data from a connected Unix socket.
|
|
80
58
|
// Returns number of bytes received on success, -errno on failure.
|
|
81
|
-
recv :: (fn(sockfd: i32, buf: *(u8), len: usize, flags: i32) -> IOFuture)(
|
|
59
|
+
recv :: (fn(sockfd : i32, buf : *(u8), len : usize, flags : i32) -> IOFuture)(
|
|
82
60
|
__yo_async_recv_start(sockfd, buf, len, flags)
|
|
83
61
|
);
|
|
84
|
-
|
|
85
62
|
// Close a Unix socket file descriptor.
|
|
86
63
|
// Returns 0 on success, -errno on failure.
|
|
87
|
-
close :: (fn(fd: i32) -> IOFuture)(
|
|
64
|
+
close :: (fn(fd : i32) -> IOFuture)(
|
|
88
65
|
__yo_async_close_start(fd)
|
|
89
66
|
);
|
|
90
|
-
|
|
91
67
|
// ============================================================================
|
|
92
68
|
// Unix Socket Address Helpers
|
|
93
69
|
// ============================================================================
|
|
94
|
-
|
|
95
70
|
// Create a sockaddr_un from a filesystem path.
|
|
96
71
|
// The path must be a null-terminated C string.
|
|
97
72
|
// Returns a UnixAddr with allocated buffer. Caller must free the buffer.
|
|
98
|
-
make_sockaddr_un :: (fn(path: *(u8)) -> UnixAddr)({
|
|
73
|
+
make_sockaddr_un :: (fn(path : *(u8)) -> UnixAddr)({
|
|
99
74
|
size := sockaddr_un_size();
|
|
100
75
|
cond(
|
|
101
76
|
(size == usize(0)) => UnixAddr(.None, u32(0)),
|
|
102
77
|
true => {
|
|
103
78
|
buf := *(u8)(malloc(size).unwrap());
|
|
104
79
|
i := usize(0);
|
|
105
|
-
while
|
|
80
|
+
while(runtime(i < size), {
|
|
106
81
|
(buf &+ i).* = u8(0);
|
|
107
82
|
i = (i + usize(1));
|
|
108
|
-
};
|
|
83
|
+
});
|
|
109
84
|
__yo_sockaddr_set_family(buf, u16(AF_UNIX));
|
|
110
85
|
__yo_sockaddr_un_set_path(buf, path);
|
|
111
86
|
UnixAddr(.Some(buf), u32(size))
|
|
112
87
|
}
|
|
113
88
|
)
|
|
114
89
|
});
|
|
115
|
-
|
|
116
90
|
// Extract the path from a sockaddr_un buffer.
|
|
117
|
-
get_path :: (fn(addr_buf: *(u8)) -> *(u8))(
|
|
91
|
+
get_path :: (fn(addr_buf : *(u8)) -> *(u8))(
|
|
118
92
|
__yo_sockaddr_un_get_path(addr_buf)
|
|
119
93
|
);
|
|
120
|
-
|
|
121
94
|
// Free a UnixAddr buffer.
|
|
122
|
-
free_addr :: (fn(addr: UnixAddr) -> unit)(
|
|
123
|
-
match(
|
|
95
|
+
free_addr :: (fn(addr : UnixAddr) -> unit)(
|
|
96
|
+
match(
|
|
97
|
+
addr.buf,
|
|
124
98
|
.Some(p) => free(.Some(*(void)(p))),
|
|
125
99
|
.None => ()
|
|
126
100
|
)
|
|
127
101
|
);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
bind,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
102
|
+
export(
|
|
103
|
+
socket_stream,
|
|
104
|
+
socket_dgram,
|
|
105
|
+
bind,
|
|
106
|
+
listen,
|
|
107
|
+
accept,
|
|
108
|
+
connect,
|
|
109
|
+
send,
|
|
110
|
+
recv,
|
|
111
|
+
close,
|
|
112
|
+
make_sockaddr_un,
|
|
113
|
+
get_path,
|
|
114
|
+
free_addr
|
|
115
|
+
);
|
package/std/testing/bench.yo
CHANGED
|
@@ -11,100 +11,97 @@
|
|
|
11
11
|
//! result := bench(`sort`, u64(1000), () => { /* work */ });
|
|
12
12
|
//! println(result.to_string());
|
|
13
13
|
//! ```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
{
|
|
18
|
-
{ Instant } :: import "../time/instant";
|
|
19
|
-
|
|
14
|
+
open(import("../string"));
|
|
15
|
+
{ ToString } :: import("../fmt");
|
|
16
|
+
{ snprintf } :: import("../libc/stdio");
|
|
17
|
+
{ Instant } :: import("../time/instant");
|
|
20
18
|
// ============================================================================
|
|
21
19
|
// BenchResult
|
|
22
20
|
// ============================================================================
|
|
23
|
-
|
|
24
21
|
/// Timing statistics returned by `bench`.
|
|
25
22
|
BenchResult :: struct(
|
|
26
23
|
/// Benchmark name.
|
|
27
|
-
name
|
|
24
|
+
name : String,
|
|
28
25
|
/// Total number of iterations executed.
|
|
29
26
|
iterations : u64,
|
|
30
27
|
/// Total elapsed nanoseconds across all iterations.
|
|
31
|
-
total_ns
|
|
28
|
+
total_ns : i64,
|
|
32
29
|
/// Average nanoseconds per iteration.
|
|
33
|
-
avg_ns
|
|
30
|
+
avg_ns : i64,
|
|
34
31
|
/// Minimum nanoseconds for a single iteration.
|
|
35
|
-
min_ns
|
|
32
|
+
min_ns : i64,
|
|
36
33
|
/// Maximum nanoseconds for a single iteration.
|
|
37
|
-
max_ns
|
|
34
|
+
max_ns : i64
|
|
38
35
|
);
|
|
39
|
-
|
|
40
|
-
_i64_to_string :: (fn(v: i64) -> String)({
|
|
36
|
+
_i64_to_string :: (fn(v : i64) -> String)({
|
|
41
37
|
buf := Array(u8, usize(32)).fill(u8(0));
|
|
42
38
|
buf_ptr := &(buf(usize(0)));
|
|
43
39
|
snprintf(*(char)(buf_ptr), usize(32), "%lld", v);
|
|
44
40
|
String.from_cstr(buf_ptr).unwrap()
|
|
45
41
|
});
|
|
46
|
-
|
|
47
|
-
_u64_to_string :: (fn(v: u64) -> String)({
|
|
42
|
+
_u64_to_string :: (fn(v : u64) -> String)({
|
|
48
43
|
buf := Array(u8, usize(32)).fill(u8(0));
|
|
49
44
|
buf_ptr := &(buf(usize(0)));
|
|
50
45
|
snprintf(*(char)(buf_ptr), usize(32), "%llu", v);
|
|
51
46
|
String.from_cstr(buf_ptr).unwrap()
|
|
52
47
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
48
|
+
impl(
|
|
49
|
+
BenchResult,
|
|
50
|
+
ToString(
|
|
51
|
+
to_string : (fn(self : *(Self)) -> String)({
|
|
52
|
+
prefix := String.from("bench '");
|
|
53
|
+
part1 := prefix.concat(self.name);
|
|
54
|
+
part2 := part1.concat(String.from("': iters="));
|
|
55
|
+
part3 := part2.concat(_u64_to_string(self.iterations));
|
|
56
|
+
part4 := part3.concat(String.from(" avg_ns="));
|
|
57
|
+
part5 := part4.concat(_i64_to_string(self.avg_ns));
|
|
58
|
+
part6 := part5.concat(String.from(" min="));
|
|
59
|
+
part7 := part6.concat(_i64_to_string(self.min_ns));
|
|
60
|
+
part8 := part7.concat(String.from(" max="));
|
|
61
|
+
part8.concat(_i64_to_string(self.max_ns))
|
|
62
|
+
})
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
export(BenchResult);
|
|
71
66
|
// ============================================================================
|
|
72
67
|
// bench
|
|
73
68
|
// ============================================================================
|
|
74
|
-
|
|
75
69
|
/// Run `body` for `iterations` times and return timing statistics.
|
|
76
|
-
bench :: (fn(name: String, iterations: u64, body: Impl(Fn() -> unit)) -> BenchResult)({
|
|
70
|
+
bench :: (fn(name : String, iterations : u64, body : Impl(Fn() -> unit)) -> BenchResult)({
|
|
77
71
|
total_ns := i64(0);
|
|
78
|
-
min_ns
|
|
79
|
-
max_ns
|
|
80
|
-
i
|
|
81
|
-
while
|
|
72
|
+
min_ns := i64(9223372036854775807); // i64::MAX
|
|
73
|
+
max_ns := i64(0);
|
|
74
|
+
i := u64(0);
|
|
75
|
+
while(i < iterations, i = (i + u64(1)), {
|
|
82
76
|
t_start := Instant.now();
|
|
83
77
|
body();
|
|
84
|
-
t_end
|
|
78
|
+
t_end := Instant.now();
|
|
85
79
|
elapsed := t_end.duration_since(t_start).as_nanos();
|
|
86
80
|
total_ns = (total_ns + elapsed);
|
|
87
81
|
cond(
|
|
88
|
-
(elapsed < min_ns) => {
|
|
82
|
+
(elapsed < min_ns) => {
|
|
83
|
+
min_ns = elapsed;
|
|
84
|
+
},
|
|
89
85
|
true => ()
|
|
90
86
|
);
|
|
91
87
|
cond(
|
|
92
|
-
(elapsed > max_ns) => {
|
|
88
|
+
(elapsed > max_ns) => {
|
|
89
|
+
max_ns = elapsed;
|
|
90
|
+
},
|
|
93
91
|
true => ()
|
|
94
92
|
);
|
|
95
|
-
};
|
|
93
|
+
});
|
|
96
94
|
avg_ns := cond(
|
|
97
95
|
(iterations > u64(0)) => (total_ns / i64(iterations)),
|
|
98
96
|
true => i64(0)
|
|
99
97
|
);
|
|
100
98
|
BenchResult(
|
|
101
|
-
name:
|
|
102
|
-
iterations: iterations,
|
|
103
|
-
total_ns:
|
|
104
|
-
avg_ns:
|
|
105
|
-
min_ns:
|
|
106
|
-
max_ns:
|
|
99
|
+
name : name,
|
|
100
|
+
iterations : iterations,
|
|
101
|
+
total_ns : total_ns,
|
|
102
|
+
avg_ns : avg_ns,
|
|
103
|
+
min_ns : min_ns,
|
|
104
|
+
max_ns : max_ns
|
|
107
105
|
)
|
|
108
106
|
});
|
|
109
|
-
|
|
110
|
-
export bench;
|
|
107
|
+
export(bench);
|
package/std/thread.yo
CHANGED
|
@@ -1,47 +1,42 @@
|
|
|
1
1
|
//! OS thread creation and management with per-thread IO event loops.
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
extern(
|
|
3
|
+
"Yo",
|
|
4
4
|
__yo_thread_get_hardware_threads : (fn() -> usize),
|
|
5
5
|
__yo_get_thread_id : (fn() -> usize),
|
|
6
6
|
__yo_get_cpu_id : (fn() -> i32)
|
|
7
|
-
;
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
);
|
|
8
|
+
extern(
|
|
9
|
+
"Yo",
|
|
10
10
|
__yo_thread_t : Type,
|
|
11
11
|
__yo_thread_spawn : (fn(cb : Impl(Fn(using(io : IO)) -> unit, Send)) -> __yo_thread_t),
|
|
12
12
|
__yo_thread_join : (fn(t : __yo_thread_t) -> unit)
|
|
13
|
-
;
|
|
14
|
-
|
|
13
|
+
);
|
|
15
14
|
/// OS thread handle. Each spawned thread gets its own IO event loop.
|
|
16
15
|
Thread :: struct(
|
|
17
16
|
handle : __yo_thread_t
|
|
18
17
|
);
|
|
19
|
-
impl(
|
|
18
|
+
impl(
|
|
19
|
+
Thread,
|
|
20
20
|
/// Spawn a new OS thread running the given closure.
|
|
21
21
|
/// The closure receives its own per-thread IO event loop.
|
|
22
22
|
spawn : (fn(cb : Impl(Fn(using(io : IO)) -> unit, Send)) -> Self)({
|
|
23
23
|
raw := __yo_thread_spawn(cb);
|
|
24
24
|
Self(raw)
|
|
25
25
|
}),
|
|
26
|
-
|
|
27
26
|
/// Block the current thread until this thread completes.
|
|
28
27
|
join : (fn(self : *(Self)) -> unit)(
|
|
29
28
|
__yo_thread_join(self.handle)
|
|
30
29
|
)
|
|
31
30
|
);
|
|
32
|
-
|
|
33
31
|
/// Get the number of hardware threads (CPU cores) available.
|
|
34
32
|
get_hardware_threads :: __yo_thread_get_hardware_threads;
|
|
35
|
-
|
|
36
33
|
/// Get the current OS thread ID.
|
|
37
34
|
get_thread_id :: __yo_get_thread_id;
|
|
38
|
-
|
|
39
35
|
/// Get the current CPU core ID.
|
|
40
36
|
get_cpu_id :: __yo_get_cpu_id;
|
|
41
|
-
|
|
42
|
-
export
|
|
37
|
+
export(
|
|
43
38
|
get_hardware_threads,
|
|
44
39
|
get_thread_id,
|
|
45
40
|
get_cpu_id,
|
|
46
41
|
Thread
|
|
47
|
-
;
|
|
42
|
+
);
|
package/std/time/datetime.yo
CHANGED
|
@@ -8,41 +8,45 @@
|
|
|
8
8
|
//! now := DateTime.now_utc();
|
|
9
9
|
//! println(now.to_string()); // "2026-02-26T17:41:24Z"
|
|
10
10
|
//! ```
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
{
|
|
14
|
-
{
|
|
15
|
-
{ snprintf } :: import "../libc/stdio";
|
|
16
|
-
|
|
11
|
+
{ String } :: import("../string");
|
|
12
|
+
{ ToString } :: import("../fmt");
|
|
13
|
+
{ CLOCK_REALTIME, clock_gettime } :: import("../sys/clock");
|
|
14
|
+
{ snprintf } :: import("../libc/stdio");
|
|
17
15
|
/// Calendar date and time with nanosecond precision.
|
|
18
16
|
/// Values are in UTC unless `utc_offset_secs` is non-zero.
|
|
19
17
|
DateTime :: struct(
|
|
20
|
-
year
|
|
21
|
-
month
|
|
22
|
-
day
|
|
23
|
-
hour
|
|
24
|
-
minute
|
|
25
|
-
second
|
|
26
|
-
nanosecond
|
|
18
|
+
year : i32,
|
|
19
|
+
month : u8,
|
|
20
|
+
day : u8,
|
|
21
|
+
hour : u8,
|
|
22
|
+
minute : u8,
|
|
23
|
+
second : u8,
|
|
24
|
+
nanosecond : u32,
|
|
27
25
|
utc_offset_secs : i32
|
|
28
26
|
);
|
|
29
|
-
|
|
30
27
|
// Days per month lookup (non-leap year)
|
|
31
28
|
_DAYS_IN_MONTH :: Array(u8, usize(12))(
|
|
32
|
-
u8(31),
|
|
33
|
-
u8(
|
|
29
|
+
u8(31),
|
|
30
|
+
u8(28),
|
|
31
|
+
u8(31),
|
|
32
|
+
u8(30),
|
|
33
|
+
u8(31),
|
|
34
|
+
u8(30),
|
|
35
|
+
u8(31),
|
|
36
|
+
u8(31),
|
|
37
|
+
u8(30),
|
|
38
|
+
u8(31),
|
|
39
|
+
u8(30),
|
|
40
|
+
u8(31)
|
|
34
41
|
);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
(((y % i32(4)) == i32(0)) && (((y % i32(100)) != i32(0)) || ((y % i32(400)) == i32(0))))
|
|
42
|
+
_is_leap_year :: (fn(y : i32) -> bool)(
|
|
43
|
+
((y % i32(4)) == i32(0)) && (((y % i32(100)) != i32(0)) || ((y % i32(400)) == i32(0)))
|
|
38
44
|
);
|
|
39
|
-
|
|
40
45
|
// Convert a Unix timestamp (seconds since 1970-01-01 UTC) into date/time fields.
|
|
41
|
-
_from_unix_secs :: (fn(secs: i64, nanos: i64) -> DateTime)({
|
|
46
|
+
_from_unix_secs :: (fn(secs : i64, nanos : i64) -> DateTime)({
|
|
42
47
|
// Adjust epoch: number of days since Unix epoch
|
|
43
48
|
days := (secs / i64(86400));
|
|
44
|
-
rem
|
|
45
|
-
|
|
49
|
+
rem := (secs % i64(86400));
|
|
46
50
|
// Normalise negative remainders
|
|
47
51
|
rem_adj := cond(
|
|
48
52
|
(rem < i64(0)) => (rem + i64(86400)),
|
|
@@ -52,68 +56,62 @@ _from_unix_secs :: (fn(secs: i64, nanos: i64) -> DateTime)({
|
|
|
52
56
|
(rem < i64(0)) => (days - i64(1)),
|
|
53
57
|
true => days
|
|
54
58
|
);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
second := u8((min_r % i64(60)));
|
|
60
|
-
|
|
59
|
+
hour := u8(rem_adj / i64(3600));
|
|
60
|
+
min_r := (rem_adj % i64(3600));
|
|
61
|
+
minute := u8(min_r / i64(60));
|
|
62
|
+
second := u8(min_r % i64(60));
|
|
61
63
|
// Gregorian calendar computation starting from 1970-01-01
|
|
62
64
|
// Using the algorithm from days since epoch → year/month/day
|
|
63
65
|
z := (days_adj + i64(719468));
|
|
64
66
|
era := cond(
|
|
65
67
|
(z >= i64(0)) => (z / i64(146097)),
|
|
66
|
-
true => ((
|
|
68
|
+
true => ((z - i64(146096)) / i64(146097))
|
|
67
69
|
);
|
|
68
|
-
doe
|
|
69
|
-
yoe
|
|
70
|
-
yoe
|
|
71
|
-
y
|
|
72
|
-
doy
|
|
73
|
-
mp
|
|
74
|
-
d
|
|
75
|
-
m
|
|
70
|
+
doe := (z - (era * i64(146097)));
|
|
71
|
+
yoe := (((doe - (doe / i64(1460))) + (doe / i64(36524))) - (doe / i64(146096)));
|
|
72
|
+
yoe = (yoe / i64(365));
|
|
73
|
+
y := (yoe + (era * i64(400)));
|
|
74
|
+
doy := (doe - (((i64(365) * yoe) + (yoe / i64(4))) - (yoe / i64(100))));
|
|
75
|
+
mp := (((i64(5) * doy) + i64(2)) / i64(153));
|
|
76
|
+
d := (doy - (((i64(153) * mp) + i64(2)) / i64(5)));
|
|
77
|
+
m := cond(
|
|
76
78
|
(mp < i64(10)) => (mp + i64(3)),
|
|
77
79
|
true => (mp - i64(9))
|
|
78
80
|
);
|
|
79
|
-
y2
|
|
81
|
+
y2 := cond(
|
|
80
82
|
(m <= i64(2)) => (y + i64(1)),
|
|
81
83
|
true => y
|
|
82
84
|
);
|
|
83
|
-
|
|
84
85
|
DateTime(
|
|
85
|
-
year:
|
|
86
|
-
month:
|
|
87
|
-
day:
|
|
88
|
-
hour:
|
|
89
|
-
minute:
|
|
90
|
-
second:
|
|
91
|
-
nanosecond:
|
|
92
|
-
utc_offset_secs: i32(0)
|
|
86
|
+
year : i32(y2),
|
|
87
|
+
month : u8(m),
|
|
88
|
+
day : u8(d + i64(1)),
|
|
89
|
+
hour : hour,
|
|
90
|
+
minute : minute,
|
|
91
|
+
second : second,
|
|
92
|
+
nanosecond : u32(nanos),
|
|
93
|
+
utc_offset_secs : i32(0)
|
|
93
94
|
)
|
|
94
95
|
});
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
impl(
|
|
97
|
+
DateTime,
|
|
97
98
|
// Current UTC date/time.
|
|
98
99
|
now_utc : (fn() -> Self)({
|
|
99
|
-
sec
|
|
100
|
+
sec := i64(0);
|
|
100
101
|
nsec := i64(0);
|
|
101
|
-
clock_gettime(CLOCK_REALTIME, (
|
|
102
|
+
clock_gettime(CLOCK_REALTIME, &(sec), &(nsec));
|
|
102
103
|
_from_unix_secs(sec, nsec)
|
|
103
104
|
}),
|
|
104
|
-
|
|
105
105
|
// Current local date/time (UTC offset not resolved; same as now_utc for now).
|
|
106
106
|
now : (fn() -> Self)(
|
|
107
107
|
DateTime.now_utc()
|
|
108
108
|
),
|
|
109
|
-
|
|
110
109
|
// Construct from a Unix timestamp.
|
|
111
|
-
from_unix : (fn(secs: i64, nanos: i64) -> Self)(
|
|
110
|
+
from_unix : (fn(secs : i64, nanos : i64) -> Self)(
|
|
112
111
|
_from_unix_secs(secs, nanos)
|
|
113
112
|
),
|
|
114
|
-
|
|
115
113
|
// Convert back to a Unix timestamp (seconds since epoch).
|
|
116
|
-
to_unix : (fn(self: *(Self)) -> i64)({
|
|
114
|
+
to_unix : (fn(self : *(Self)) -> i64)({
|
|
117
115
|
// Compute days since epoch using the inverse Gregorian algorithm
|
|
118
116
|
y := i64(self.year);
|
|
119
117
|
m := i64(self.month);
|
|
@@ -124,10 +122,10 @@ impl(DateTime,
|
|
|
124
122
|
);
|
|
125
123
|
era := cond(
|
|
126
124
|
(y2 >= i64(0)) => (y2 / i64(400)),
|
|
127
|
-
true => ((
|
|
125
|
+
true => ((y2 - i64(399)) / i64(400))
|
|
128
126
|
);
|
|
129
127
|
yoe := (y2 - (era * i64(400)));
|
|
130
|
-
mp
|
|
128
|
+
mp := cond(
|
|
131
129
|
(m > i64(2)) => (m - i64(3)),
|
|
132
130
|
true => (m + i64(9))
|
|
133
131
|
);
|
|
@@ -135,43 +133,52 @@ impl(DateTime,
|
|
|
135
133
|
doe := ((((yoe * i64(365)) + (yoe / i64(4))) - (yoe / i64(100))) + doy);
|
|
136
134
|
days := (((era * i64(146097)) + doe) - i64(719468));
|
|
137
135
|
time_secs := (((i64(self.hour) * i64(3600)) + (i64(self.minute) * i64(60))) + i64(self.second));
|
|
138
|
-
(
|
|
136
|
+
(days * i64(86400)) + time_secs
|
|
139
137
|
}),
|
|
140
|
-
|
|
141
138
|
// True if this year is a leap year.
|
|
142
|
-
is_leap_year : (fn(self: *(Self)) -> bool)(
|
|
139
|
+
is_leap_year : (fn(self : *(Self)) -> bool)(
|
|
143
140
|
_is_leap_year(self.year)
|
|
144
141
|
),
|
|
145
|
-
|
|
146
142
|
// Day of week: 0 = Monday, 6 = Sunday (ISO 8601).
|
|
147
|
-
day_of_week : (fn(self: *(Self)) -> u8)({
|
|
143
|
+
day_of_week : (fn(self : *(Self)) -> u8)({
|
|
148
144
|
// Tomohiko Sakamoto's algorithm
|
|
149
145
|
t := Array(i32, usize(12))(
|
|
150
|
-
i32(0),
|
|
151
|
-
i32(
|
|
146
|
+
i32(0),
|
|
147
|
+
i32(3),
|
|
148
|
+
i32(2),
|
|
149
|
+
i32(5),
|
|
150
|
+
i32(0),
|
|
151
|
+
i32(3),
|
|
152
|
+
i32(5),
|
|
153
|
+
i32(1),
|
|
154
|
+
i32(4),
|
|
155
|
+
i32(6),
|
|
156
|
+
i32(2),
|
|
157
|
+
i32(4)
|
|
152
158
|
);
|
|
153
159
|
y := cond(
|
|
154
160
|
(i32(self.month) < i32(3)) => (self.year - i32(1)),
|
|
155
161
|
true => self.year
|
|
156
162
|
);
|
|
157
|
-
sum := (((((y + (y / i32(4))) - (y / i32(100))) + (y / i32(400))) + t(usize(
|
|
163
|
+
sum := (((((y + (y / i32(4))) - (y / i32(100))) + (y / i32(400))) + t(usize(i32(self.month) - i32(1)))) + i32(self.day));
|
|
158
164
|
dow := (sum % i32(7));
|
|
159
165
|
// Convert: 0=Sun → remap to 0=Mon
|
|
160
|
-
u8(
|
|
161
|
-
(
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
u8(
|
|
167
|
+
cond(
|
|
168
|
+
(dow == i32(0)) => i32(6),
|
|
169
|
+
true => (dow - i32(1))
|
|
170
|
+
)
|
|
171
|
+
)
|
|
164
172
|
}),
|
|
165
|
-
|
|
166
173
|
// Day of year (1-based).
|
|
167
|
-
day_of_year : (fn(self: *(Self)) -> u16)({
|
|
174
|
+
day_of_year : (fn(self : *(Self)) -> u16)({
|
|
168
175
|
m := i32(self.month);
|
|
169
176
|
d := i32(self.day);
|
|
170
177
|
// Sum days in preceding months
|
|
171
178
|
days := d;
|
|
172
179
|
i := i32(1);
|
|
173
|
-
while
|
|
174
|
-
idx := usize(
|
|
180
|
+
while(i < m, i = (i + i32(1)), {
|
|
181
|
+
idx := usize(i - i32(1));
|
|
175
182
|
days = (days + i32(_DAYS_IN_MONTH(idx)));
|
|
176
183
|
// Add leap day after Feb in a leap year
|
|
177
184
|
cond(
|
|
@@ -180,20 +187,29 @@ impl(DateTime,
|
|
|
180
187
|
},
|
|
181
188
|
true => ()
|
|
182
189
|
);
|
|
183
|
-
};
|
|
190
|
+
});
|
|
184
191
|
u16(days)
|
|
185
192
|
})
|
|
186
193
|
);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
194
|
+
impl(
|
|
195
|
+
DateTime,
|
|
196
|
+
ToString(
|
|
197
|
+
to_string : (fn(self : *(Self)) -> String)({
|
|
198
|
+
buf := Array(u8, usize(32)).fill(u8(0));
|
|
199
|
+
buf_ptr := &(buf(usize(0)));
|
|
200
|
+
snprintf(
|
|
201
|
+
*(char)(buf_ptr),
|
|
202
|
+
usize(32),
|
|
203
|
+
"%04d-%02u-%02uT%02u:%02u:%02uZ",
|
|
204
|
+
self.year,
|
|
205
|
+
self.month,
|
|
206
|
+
self.day,
|
|
207
|
+
self.hour,
|
|
208
|
+
self.minute,
|
|
209
|
+
self.second
|
|
210
|
+
);
|
|
211
|
+
String.from_cstr(buf_ptr).unwrap()
|
|
212
|
+
})
|
|
213
|
+
)
|
|
214
|
+
);
|
|
215
|
+
export(DateTime);
|