@shd101wyy/yo 0.1.28 → 0.1.29
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 +110 -121
- package/.github/skills/yo-syntax/SKILL.md +2 -2
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +49 -75
- package/README.md +2 -0
- package/out/cjs/index.cjs +622 -611
- package/out/cjs/yo-cli.cjs +727 -716
- package/out/cjs/yo-lsp.cjs +637 -626
- package/out/esm/index.mjs +515 -504
- 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 +0 -2
- package/out/types/src/evaluator/context.d.ts +1 -1
- package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
- 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.d.ts +5 -6
- package/out/types/src/types/creators.d.ts +4 -6
- package/out/types/src/types/definitions.d.ts +7 -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 +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/async.yo +1 -1
- package/std/crypto/random.yo +6 -6
- package/std/encoding/base64.yo +4 -4
- package/std/encoding/hex.yo +2 -2
- package/std/encoding/json.yo +3 -3
- package/std/encoding/utf16.yo +1 -1
- package/std/error.yo +14 -2
- package/std/fs/dir.yo +56 -62
- package/std/fs/file.yo +118 -124
- package/std/fs/metadata.yo +11 -17
- package/std/fs/temp.yo +21 -27
- package/std/fs/walker.yo +10 -16
- package/std/http/client.yo +25 -29
- package/std/http/index.yo +4 -4
- package/std/io/reader.yo +1 -1
- package/std/io/writer.yo +2 -2
- package/std/net/addr.yo +1 -1
- package/std/net/dns.yo +10 -14
- package/std/net/errors.yo +1 -1
- package/std/net/tcp.yo +67 -71
- package/std/net/udp.yo +36 -40
- package/std/os/signal.yo +2 -2
- package/std/prelude.yo +27 -21
- package/std/process/command.yo +32 -38
- package/std/regex/parser.yo +10 -10
- package/std/sys/bufio/buf_reader.yo +14 -14
- package/std/sys/bufio/buf_writer.yo +17 -17
- package/std/sys/errors.yo +1 -1
- package/std/thread.yo +2 -2
- package/std/url/index.yo +2 -2
- package/std/worker.yo +2 -2
package/std/net/tcp.yo
CHANGED
|
@@ -9,14 +9,10 @@
|
|
|
9
9
|
// { SocketAddr, IpAddr } :: import "std/net/addr";
|
|
10
10
|
// { Exception } :: import "std/error";
|
|
11
11
|
//
|
|
12
|
-
// main :: (fn(
|
|
13
|
-
// given(exn) := Exception(throw : ((err) -> {
|
|
14
|
-
// println(err.message());
|
|
15
|
-
// escape ();
|
|
16
|
-
// }));
|
|
12
|
+
// main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
17
13
|
// addr := SocketAddr.new(IpAddr.any_v4(), u16(8080));
|
|
18
|
-
// listener := io.await(TcpListener.bind(addr));
|
|
19
|
-
// stream := io.await(listener.accept());
|
|
14
|
+
// listener := io.await(TcpListener.bind(addr, io), { io, exn });
|
|
15
|
+
// stream := io.await(listener.accept(io), { io, exn });
|
|
20
16
|
// // ...
|
|
21
17
|
// });
|
|
22
18
|
{ GlobalAllocator } :: import("../allocator");
|
|
@@ -27,7 +23,7 @@ open(import("../fmt"));
|
|
|
27
23
|
{ NetError } :: import("./errors");
|
|
28
24
|
{ IOError } :: import("../sys/errors");
|
|
29
25
|
{ IpAddr, SocketAddr } :: import("./addr");
|
|
30
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
26
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
31
27
|
IO_tcp :: import("../sys/tcp");
|
|
32
28
|
{ AF_INET, AF_INET6, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, IPPROTO_TCP, TCP_NODELAY, SO_KEEPALIVE } :: import("../sys/socket");
|
|
33
29
|
// ============================================================================
|
|
@@ -49,7 +45,7 @@ _make_sockaddr :: (fn(addr : SocketAddr) -> IO_tcp.SockAddr)(
|
|
|
49
45
|
IO_tcp.make_sockaddr_in6(*(u8)("::1"), addr.port)
|
|
50
46
|
)
|
|
51
47
|
);
|
|
52
|
-
_throw_io :: (fn(errno_val : i32,
|
|
48
|
+
_throw_io :: (fn(errno_val : i32, exn : Exception) -> unit)(
|
|
53
49
|
exn.throw(dyn(NetError.from_io(IOError.from_errno(errno_val))))
|
|
54
50
|
);
|
|
55
51
|
// ============================================================================
|
|
@@ -73,36 +69,36 @@ TcpListener :: object(
|
|
|
73
69
|
impl(
|
|
74
70
|
TcpListener,
|
|
75
71
|
/// Bind to a socket address and start listening.
|
|
76
|
-
bind : (fn(addr : SocketAddr,
|
|
77
|
-
io.async((
|
|
72
|
+
bind : (fn(addr : SocketAddr, io : IO) -> Impl(Future(TcpListener, IOErr)))(
|
|
73
|
+
io.async((e) => {
|
|
78
74
|
domain := cond(
|
|
79
75
|
addr.ip.is_v4() => AF_INET,
|
|
80
76
|
true => AF_INET6
|
|
81
77
|
);
|
|
82
78
|
// Create socket
|
|
83
|
-
raw_fd := io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)));
|
|
84
|
-
fd := NetError.check(raw_fd);
|
|
79
|
+
raw_fd := e.io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)), e.io);
|
|
80
|
+
fd := NetError.check(raw_fd, e.exn);
|
|
85
81
|
// Set SO_REUSEADDR
|
|
86
82
|
reuse_val := i32(1);
|
|
87
83
|
reuse_ptr := &(reuse_val);
|
|
88
|
-
io.await(IO_tcp.setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, *(u8)(reuse_ptr), u32(4)));
|
|
84
|
+
e.io.await(IO_tcp.setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, *(u8)(reuse_ptr), u32(4)), e.io);
|
|
89
85
|
// Bind
|
|
90
86
|
saddr := _make_sockaddr(addr);
|
|
91
|
-
bind_result := io.await(IO_tcp.bind(fd, saddr.buf, saddr.len));
|
|
87
|
+
bind_result := e.io.await(IO_tcp.bind(fd, saddr.buf, saddr.len), e.io);
|
|
92
88
|
IO_tcp.free_sockaddr(saddr);
|
|
93
89
|
cond(
|
|
94
90
|
(bind_result < i32(0)) => {
|
|
95
|
-
io.await(IO_tcp.close(fd));
|
|
96
|
-
_throw_io(i32(0) - bind_result);
|
|
91
|
+
e.io.await(IO_tcp.close(fd), e.io);
|
|
92
|
+
_throw_io(i32(0) - bind_result, e.exn);
|
|
97
93
|
},
|
|
98
94
|
true => ()
|
|
99
95
|
);
|
|
100
96
|
// Listen
|
|
101
|
-
listen_result := io.await(IO_tcp.listen(fd, i32(128)));
|
|
97
|
+
listen_result := e.io.await(IO_tcp.listen(fd, i32(128)), e.io);
|
|
102
98
|
cond(
|
|
103
99
|
(listen_result < i32(0)) => {
|
|
104
|
-
io.await(IO_tcp.close(fd));
|
|
105
|
-
_throw_io(i32(0) - listen_result);
|
|
100
|
+
e.io.await(IO_tcp.close(fd), e.io);
|
|
101
|
+
_throw_io(i32(0) - listen_result, e.exn);
|
|
106
102
|
},
|
|
107
103
|
true => ()
|
|
108
104
|
);
|
|
@@ -110,19 +106,19 @@ impl(
|
|
|
110
106
|
})
|
|
111
107
|
),
|
|
112
108
|
/// Accept an incoming connection, returning a new `TcpStream`.
|
|
113
|
-
accept : (fn(self : Self,
|
|
109
|
+
accept : (fn(self : Self, io : IO) -> Impl(Future(TcpStream, IOErr)))({
|
|
114
110
|
fd := self._fd;
|
|
115
|
-
io.async((
|
|
111
|
+
io.async((e) => {
|
|
116
112
|
// Allocate space for the peer address
|
|
117
113
|
addr_buf := *(u8)(malloc(usize(128)).unwrap());
|
|
118
114
|
addr_len := *(u32)(malloc(usize(4)).unwrap());
|
|
119
115
|
addr_len.* = u32(128);
|
|
120
|
-
client_fd := io.await(IO_tcp.accept(fd, addr_buf, addr_len));
|
|
116
|
+
client_fd := e.io.await(IO_tcp.accept(fd, addr_buf, addr_len), e.io);
|
|
121
117
|
cond(
|
|
122
118
|
(client_fd < i32(0)) => {
|
|
123
119
|
free(.Some(*(void)(addr_buf)));
|
|
124
120
|
free(.Some(*(void)(addr_len)));
|
|
125
|
-
_throw_io(i32(0) - client_fd);
|
|
121
|
+
_throw_io(i32(0) - client_fd, e.exn);
|
|
126
122
|
},
|
|
127
123
|
true => ()
|
|
128
124
|
);
|
|
@@ -145,17 +141,17 @@ impl(
|
|
|
145
141
|
self._local_addr
|
|
146
142
|
),
|
|
147
143
|
/// Close the listener socket.
|
|
148
|
-
close : (fn(self : Self,
|
|
144
|
+
close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
149
145
|
fd := self._fd;
|
|
150
|
-
io.async((
|
|
146
|
+
io.async((e) => {
|
|
151
147
|
cond(
|
|
152
148
|
self._is_closed => (),
|
|
153
149
|
true => {
|
|
154
|
-
r := io.await(IO_tcp.close(fd));
|
|
150
|
+
r := e.io.await(IO_tcp.close(fd), e.io);
|
|
155
151
|
self._is_closed = true;
|
|
156
152
|
cond(
|
|
157
153
|
(r < i32(0)) => {
|
|
158
|
-
_throw_io(i32(0) - r);
|
|
154
|
+
_throw_io(i32(0) - r, e.exn);
|
|
159
155
|
},
|
|
160
156
|
true => ()
|
|
161
157
|
);
|
|
@@ -190,21 +186,21 @@ export(TcpListener);
|
|
|
190
186
|
impl(
|
|
191
187
|
TcpStream,
|
|
192
188
|
/// Connect to a remote address, returning a new `TcpStream`.
|
|
193
|
-
connect : (fn(addr : SocketAddr,
|
|
194
|
-
io.async((
|
|
189
|
+
connect : (fn(addr : SocketAddr, io : IO) -> Impl(Future(TcpStream, IOErr)))(
|
|
190
|
+
io.async((e) => {
|
|
195
191
|
domain := cond(
|
|
196
192
|
addr.ip.is_v4() => AF_INET,
|
|
197
193
|
true => AF_INET6
|
|
198
194
|
);
|
|
199
|
-
raw_fd := io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)));
|
|
200
|
-
fd := NetError.check(raw_fd);
|
|
195
|
+
raw_fd := e.io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)), e.io);
|
|
196
|
+
fd := NetError.check(raw_fd, e.exn);
|
|
201
197
|
saddr := _make_sockaddr(addr);
|
|
202
|
-
conn_result := io.await(IO_tcp.connect(fd, saddr.buf, saddr.len));
|
|
198
|
+
conn_result := e.io.await(IO_tcp.connect(fd, saddr.buf, saddr.len), e.io);
|
|
203
199
|
IO_tcp.free_sockaddr(saddr);
|
|
204
200
|
cond(
|
|
205
201
|
(conn_result < i32(0)) => {
|
|
206
|
-
io.await(IO_tcp.close(fd));
|
|
207
|
-
_throw_io(i32(0) - conn_result);
|
|
202
|
+
e.io.await(IO_tcp.close(fd), e.io);
|
|
203
|
+
_throw_io(i32(0) - conn_result, e.exn);
|
|
208
204
|
},
|
|
209
205
|
true => ()
|
|
210
206
|
);
|
|
@@ -219,58 +215,58 @@ impl(
|
|
|
219
215
|
),
|
|
220
216
|
/// Read bytes from the stream into `buf`.
|
|
221
217
|
/// Returns the number of bytes read, or 0 if the peer closed the connection.
|
|
222
|
-
read : (fn(self : Self, buf : *(u8), size : usize,
|
|
218
|
+
read : (fn(self : Self, buf : *(u8), size : usize, io : IO) -> Impl(Future(i32, IOErr)))({
|
|
223
219
|
fd := self._fd;
|
|
224
|
-
io.async((
|
|
225
|
-
r := io.await(IO_tcp.recv(fd, buf, size, i32(0)));
|
|
226
|
-
NetError.check(r)
|
|
220
|
+
io.async((e) => {
|
|
221
|
+
r := e.io.await(IO_tcp.recv(fd, buf, size, i32(0)), e.io);
|
|
222
|
+
NetError.check(r, e.exn)
|
|
227
223
|
})
|
|
228
224
|
}),
|
|
229
225
|
/// Write a `str` to the stream.
|
|
230
226
|
/// Returns the number of bytes written.
|
|
231
|
-
write_str : (fn(self : Self, data : str,
|
|
227
|
+
write_str : (fn(self : Self, data : str, io : IO) -> Impl(Future(i32, IOErr)))({
|
|
232
228
|
fd := self._fd;
|
|
233
229
|
s := String.from(data);
|
|
234
230
|
s_bytes := s.as_bytes();
|
|
235
|
-
io.async((
|
|
236
|
-
r := io.await(IO_tcp.send(fd, s_bytes.ptr().unwrap(), s_bytes.len(), i32(0)));
|
|
237
|
-
NetError.check(r)
|
|
231
|
+
io.async((e) => {
|
|
232
|
+
r := e.io.await(IO_tcp.send(fd, s_bytes.ptr().unwrap(), s_bytes.len(), i32(0)), e.io);
|
|
233
|
+
NetError.check(r, e.exn)
|
|
238
234
|
})
|
|
239
235
|
}),
|
|
240
236
|
/// Write a `String` to the stream.
|
|
241
237
|
/// Returns the number of bytes written.
|
|
242
|
-
write_string : (fn(self : Self, data : String,
|
|
238
|
+
write_string : (fn(self : Self, data : String, io : IO) -> Impl(Future(i32, IOErr)))({
|
|
243
239
|
fd := self._fd;
|
|
244
240
|
data_bytes := data.as_bytes();
|
|
245
|
-
io.async((
|
|
246
|
-
r := io.await(IO_tcp.send(fd, data_bytes.ptr().unwrap(), data_bytes.len(), i32(0)));
|
|
247
|
-
NetError.check(r)
|
|
241
|
+
io.async((e) => {
|
|
242
|
+
r := e.io.await(IO_tcp.send(fd, data_bytes.ptr().unwrap(), data_bytes.len(), i32(0)), e.io);
|
|
243
|
+
NetError.check(r, e.exn)
|
|
248
244
|
})
|
|
249
245
|
}),
|
|
250
246
|
/// Write raw bytes from an `ArrayList(u8)` to the stream.
|
|
251
247
|
/// Returns the number of bytes written.
|
|
252
|
-
write_bytes : (fn(self : Self, data : ArrayList(u8),
|
|
248
|
+
write_bytes : (fn(self : Self, data : ArrayList(u8), io : IO) -> Impl(Future(i32, IOErr)))({
|
|
253
249
|
fd := self._fd;
|
|
254
|
-
io.async((
|
|
255
|
-
r := io.await(IO_tcp.send(fd, data.ptr().unwrap(), data.len(), i32(0)));
|
|
256
|
-
NetError.check(r)
|
|
250
|
+
io.async((e) => {
|
|
251
|
+
r := e.io.await(IO_tcp.send(fd, data.ptr().unwrap(), data.len(), i32(0)), e.io);
|
|
252
|
+
NetError.check(r, e.exn)
|
|
257
253
|
})
|
|
258
254
|
}),
|
|
259
255
|
/// Read all available data from the stream into a byte list.
|
|
260
|
-
read_bytes : (fn(self : Self,
|
|
256
|
+
read_bytes : (fn(self : Self, io : IO) -> Impl(Future(ArrayList(u8), IOErr)))({
|
|
261
257
|
fd := self._fd;
|
|
262
|
-
io.async((
|
|
258
|
+
io.async((e) => {
|
|
263
259
|
buf_size := usize(4096);
|
|
264
260
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
265
261
|
acc := ArrayList(u8).new();
|
|
266
262
|
done := false;
|
|
267
263
|
while(runtime(!(done)), {
|
|
268
|
-
n := io.await(IO_tcp.recv(fd, buf, buf_size, i32(0)));
|
|
264
|
+
n := e.io.await(IO_tcp.recv(fd, buf, buf_size, i32(0)), e.io);
|
|
269
265
|
cond(
|
|
270
266
|
(n < i32(0)) => {
|
|
271
267
|
free(.Some(*(void)(buf)));
|
|
272
268
|
done = true;
|
|
273
|
-
_throw_io(i32(0) - n);
|
|
269
|
+
_throw_io(i32(0) - n, e.exn);
|
|
274
270
|
},
|
|
275
271
|
(n == i32(0)) => {
|
|
276
272
|
done = true;
|
|
@@ -290,30 +286,30 @@ impl(
|
|
|
290
286
|
}),
|
|
291
287
|
/// Shut down part or all of the connection.
|
|
292
288
|
/// `how`: 0 = read, 1 = write, 2 = both.
|
|
293
|
-
shutdown : (fn(self : Self, how : i32,
|
|
289
|
+
shutdown : (fn(self : Self, how : i32, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
294
290
|
fd := self._fd;
|
|
295
|
-
io.async((
|
|
296
|
-
r := io.await(IO_tcp.shutdown(fd, how));
|
|
291
|
+
io.async((e) => {
|
|
292
|
+
r := e.io.await(IO_tcp.shutdown(fd, how), e.io);
|
|
297
293
|
cond(
|
|
298
294
|
(r < i32(0)) => {
|
|
299
|
-
_throw_io(i32(0) - r);
|
|
295
|
+
_throw_io(i32(0) - r, e.exn);
|
|
300
296
|
},
|
|
301
297
|
true => ()
|
|
302
298
|
);
|
|
303
299
|
})
|
|
304
300
|
}),
|
|
305
301
|
/// Close the stream.
|
|
306
|
-
close : (fn(self : Self,
|
|
302
|
+
close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
307
303
|
fd := self._fd;
|
|
308
|
-
io.async((
|
|
304
|
+
io.async((e) => {
|
|
309
305
|
cond(
|
|
310
306
|
self._is_closed => (),
|
|
311
307
|
true => {
|
|
312
|
-
r := io.await(IO_tcp.close(fd));
|
|
308
|
+
r := e.io.await(IO_tcp.close(fd), e.io);
|
|
313
309
|
self._is_closed = true;
|
|
314
310
|
cond(
|
|
315
311
|
(r < i32(0)) => {
|
|
316
|
-
_throw_io(i32(0) - r);
|
|
312
|
+
_throw_io(i32(0) - r, e.exn);
|
|
317
313
|
},
|
|
318
314
|
true => ()
|
|
319
315
|
);
|
|
@@ -330,30 +326,30 @@ impl(
|
|
|
330
326
|
self._fd
|
|
331
327
|
),
|
|
332
328
|
/// Enable or disable TCP_NODELAY (disables Nagle's algorithm).
|
|
333
|
-
set_nodelay : (fn(self : Self, nodelay : bool,
|
|
329
|
+
set_nodelay : (fn(self : Self, nodelay : bool, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
334
330
|
sock_fd := self._fd;
|
|
335
|
-
io.async((
|
|
331
|
+
io.async((e) => {
|
|
336
332
|
val := cond(nodelay => i32(1), true => i32(0));
|
|
337
333
|
val_ptr := &(val);
|
|
338
|
-
r := io.await(IO_tcp.setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, *(u8)(val_ptr), u32(4)));
|
|
334
|
+
r := e.io.await(IO_tcp.setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, *(u8)(val_ptr), u32(4)), e.io);
|
|
339
335
|
cond(
|
|
340
336
|
(r < i32(0)) => {
|
|
341
|
-
_throw_io(i32(0) - r);
|
|
337
|
+
_throw_io(i32(0) - r, e.exn);
|
|
342
338
|
},
|
|
343
339
|
true => ()
|
|
344
340
|
);
|
|
345
341
|
})
|
|
346
342
|
}),
|
|
347
343
|
/// Enable or disable SO_KEEPALIVE on the socket.
|
|
348
|
-
set_keepalive : (fn(self : Self, enabled : bool,
|
|
344
|
+
set_keepalive : (fn(self : Self, enabled : bool, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
349
345
|
sock_fd := self._fd;
|
|
350
|
-
io.async((
|
|
346
|
+
io.async((e) => {
|
|
351
347
|
val := cond(enabled => i32(1), true => i32(0));
|
|
352
348
|
val_ptr := &(val);
|
|
353
|
-
r := io.await(IO_tcp.setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, *(u8)(val_ptr), u32(4)));
|
|
349
|
+
r := e.io.await(IO_tcp.setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, *(u8)(val_ptr), u32(4)), e.io);
|
|
354
350
|
cond(
|
|
355
351
|
(r < i32(0)) => {
|
|
356
|
-
_throw_io(i32(0) - r);
|
|
352
|
+
_throw_io(i32(0) - r, e.exn);
|
|
357
353
|
},
|
|
358
354
|
true => ()
|
|
359
355
|
);
|
package/std/net/udp.yo
CHANGED
|
@@ -9,14 +9,10 @@
|
|
|
9
9
|
// { SocketAddr, IpAddr } :: import "std/net/addr";
|
|
10
10
|
// { Exception } :: import "std/error";
|
|
11
11
|
//
|
|
12
|
-
// main :: (fn(
|
|
13
|
-
// given(exn) := Exception(throw : ((err) -> {
|
|
14
|
-
// println(err.message());
|
|
15
|
-
// escape ();
|
|
16
|
-
// }));
|
|
12
|
+
// main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
17
13
|
// addr := SocketAddr.new(IpAddr.loopback_v4(), u16(9999));
|
|
18
|
-
// sock := io.await(UdpSocket.bind(addr));
|
|
19
|
-
// io.await(sock.close());
|
|
14
|
+
// sock := io.await(UdpSocket.bind(addr, io), { io, exn });
|
|
15
|
+
// io.await(sock.close(io), { io, exn });
|
|
20
16
|
// });
|
|
21
17
|
{ GlobalAllocator } :: import("../allocator");
|
|
22
18
|
{ malloc, free } :: GlobalAllocator;
|
|
@@ -26,7 +22,7 @@ open(import("../fmt"));
|
|
|
26
22
|
{ NetError } :: import("./errors");
|
|
27
23
|
{ IOError } :: import("../sys/errors");
|
|
28
24
|
{ IpAddr, SocketAddr } :: import("./addr");
|
|
29
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
25
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
30
26
|
IO_udp :: import("../sys/udp");
|
|
31
27
|
IO_tcp :: import("../sys/tcp");
|
|
32
28
|
{ AF_INET, AF_INET6, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST } :: import("../sys/socket");
|
|
@@ -46,7 +42,7 @@ _make_sockaddr :: (fn(addr : SocketAddr) -> IO_tcp.SockAddr)(
|
|
|
46
42
|
IO_tcp.make_sockaddr_in6(*(u8)("::1"), addr.port)
|
|
47
43
|
)
|
|
48
44
|
);
|
|
49
|
-
_throw_net_io :: (fn(errno_val : i32,
|
|
45
|
+
_throw_net_io :: (fn(errno_val : i32, exn : Exception) -> unit)(
|
|
50
46
|
exn.throw(dyn(NetError.from_io(IOError.from_errno(errno_val))))
|
|
51
47
|
);
|
|
52
48
|
// ============================================================================
|
|
@@ -61,21 +57,21 @@ UdpSocket :: object(
|
|
|
61
57
|
impl(
|
|
62
58
|
UdpSocket,
|
|
63
59
|
/// Create and bind a UDP socket to the given address.
|
|
64
|
-
bind : (fn(addr : SocketAddr,
|
|
65
|
-
io.async((
|
|
60
|
+
bind : (fn(addr : SocketAddr, io : IO) -> Impl(Future(UdpSocket, IOErr)))(
|
|
61
|
+
io.async((e) => {
|
|
66
62
|
domain := cond(
|
|
67
63
|
addr.ip.is_v4() => AF_INET,
|
|
68
64
|
true => AF_INET6
|
|
69
65
|
);
|
|
70
|
-
raw_fd := io.await(IO_udp.socket(domain, i32(0)));
|
|
71
|
-
fd := NetError.check(raw_fd);
|
|
66
|
+
raw_fd := e.io.await(IO_udp.socket(domain, i32(0)), e.io);
|
|
67
|
+
fd := NetError.check(raw_fd, e.exn);
|
|
72
68
|
saddr := _make_sockaddr(addr);
|
|
73
|
-
bind_r := io.await(IO_udp.bind(fd, saddr.buf, saddr.len));
|
|
69
|
+
bind_r := e.io.await(IO_udp.bind(fd, saddr.buf, saddr.len), e.io);
|
|
74
70
|
IO_tcp.free_sockaddr(saddr);
|
|
75
71
|
cond(
|
|
76
72
|
(bind_r < i32(0)) => {
|
|
77
|
-
io.await(IO_udp.close(fd));
|
|
78
|
-
_throw_net_io(i32(0) - bind_r);
|
|
73
|
+
e.io.await(IO_udp.close(fd), e.io);
|
|
74
|
+
_throw_net_io(i32(0) - bind_r, e.exn);
|
|
79
75
|
},
|
|
80
76
|
true => ()
|
|
81
77
|
);
|
|
@@ -84,53 +80,53 @@ impl(
|
|
|
84
80
|
),
|
|
85
81
|
/// Send a datagram to a specific address.
|
|
86
82
|
/// Returns the number of bytes sent.
|
|
87
|
-
send_to : (fn(self : Self, data : ArrayList(u8), addr : SocketAddr,
|
|
83
|
+
send_to : (fn(self : Self, data : ArrayList(u8), addr : SocketAddr, io : IO) -> Impl(Future(i32, IOErr)))({
|
|
88
84
|
fd := self._fd;
|
|
89
|
-
io.async((
|
|
85
|
+
io.async((e) => {
|
|
90
86
|
saddr := _make_sockaddr(addr);
|
|
91
|
-
r := io.await(IO_udp.sendto(fd, data.ptr().unwrap(), data.len(), i32(0), saddr.buf, saddr.len));
|
|
87
|
+
r := e.io.await(IO_udp.sendto(fd, data.ptr().unwrap(), data.len(), i32(0), saddr.buf, saddr.len), e.io);
|
|
92
88
|
IO_tcp.free_sockaddr(saddr);
|
|
93
|
-
NetError.check(r)
|
|
89
|
+
NetError.check(r, e.exn)
|
|
94
90
|
})
|
|
95
91
|
}),
|
|
96
92
|
/// Receive a datagram into the provided buffer.
|
|
97
93
|
/// Returns the number of bytes received.
|
|
98
|
-
recv : (fn(self : Self, buf : *(u8), size : usize,
|
|
94
|
+
recv : (fn(self : Self, buf : *(u8), size : usize, io : IO) -> Impl(Future(i32, IOErr)))({
|
|
99
95
|
fd := self._fd;
|
|
100
|
-
io.async((
|
|
101
|
-
r := io.await(IO_udp.recv(fd, buf, size, i32(0)));
|
|
102
|
-
NetError.check(r)
|
|
96
|
+
io.async((e) => {
|
|
97
|
+
r := e.io.await(IO_udp.recv(fd, buf, size, i32(0)), e.io);
|
|
98
|
+
NetError.check(r, e.exn)
|
|
103
99
|
})
|
|
104
100
|
}),
|
|
105
101
|
/// Receive a datagram and retrieve the sender's address.
|
|
106
102
|
/// Returns the number of bytes received.
|
|
107
|
-
recv_from : (fn(self : Self, buf : *(u8), size : usize, src_addr : *(u8), src_addr_len : *(u32),
|
|
103
|
+
recv_from : (fn(self : Self, buf : *(u8), size : usize, src_addr : *(u8), src_addr_len : *(u32), io : IO) -> Impl(Future(i32, IOErr)))({
|
|
108
104
|
fd := self._fd;
|
|
109
|
-
io.async((
|
|
110
|
-
r := io.await(IO_udp.recvfrom(fd, buf, size, i32(0), src_addr, src_addr_len));
|
|
111
|
-
NetError.check(r)
|
|
105
|
+
io.async((e) => {
|
|
106
|
+
r := e.io.await(IO_udp.recvfrom(fd, buf, size, i32(0), src_addr, src_addr_len), e.io);
|
|
107
|
+
NetError.check(r, e.exn)
|
|
112
108
|
})
|
|
113
109
|
}),
|
|
114
110
|
/// Send data on a connected socket (requires prior connect).
|
|
115
|
-
send : (fn(self : Self, data : ArrayList(u8),
|
|
111
|
+
send : (fn(self : Self, data : ArrayList(u8), io : IO) -> Impl(Future(i32, IOErr)))({
|
|
116
112
|
fd := self._fd;
|
|
117
|
-
io.async((
|
|
118
|
-
r := io.await(IO_udp.send(fd, data.ptr().unwrap(), data.len(), i32(0)));
|
|
119
|
-
NetError.check(r)
|
|
113
|
+
io.async((e) => {
|
|
114
|
+
r := e.io.await(IO_udp.send(fd, data.ptr().unwrap(), data.len(), i32(0)), e.io);
|
|
115
|
+
NetError.check(r, e.exn)
|
|
120
116
|
})
|
|
121
117
|
}),
|
|
122
118
|
/// Close the socket.
|
|
123
|
-
close : (fn(self : Self,
|
|
119
|
+
close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
124
120
|
fd := self._fd;
|
|
125
|
-
io.async((
|
|
121
|
+
io.async((e) => {
|
|
126
122
|
cond(
|
|
127
123
|
self._is_closed => (),
|
|
128
124
|
true => {
|
|
129
|
-
r := io.await(IO_udp.close(fd));
|
|
125
|
+
r := e.io.await(IO_udp.close(fd), e.io);
|
|
130
126
|
self._is_closed = true;
|
|
131
127
|
cond(
|
|
132
128
|
(r < i32(0)) => {
|
|
133
|
-
_throw_net_io(i32(0) - r);
|
|
129
|
+
_throw_net_io(i32(0) - r, e.exn);
|
|
134
130
|
},
|
|
135
131
|
true => ()
|
|
136
132
|
);
|
|
@@ -139,15 +135,15 @@ impl(
|
|
|
139
135
|
})
|
|
140
136
|
}),
|
|
141
137
|
/// Enable or disable SO_BROADCAST on the socket.
|
|
142
|
-
set_broadcast : (fn(self : Self, enabled : bool,
|
|
138
|
+
set_broadcast : (fn(self : Self, enabled : bool, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
143
139
|
fd := self._fd;
|
|
144
|
-
io.async((
|
|
140
|
+
io.async((e) => {
|
|
145
141
|
val := cond(enabled => i32(1), true => i32(0));
|
|
146
142
|
val_ptr := &(val);
|
|
147
|
-
r := io.await(IO_udp.setsockopt(fd, SOL_SOCKET, SO_BROADCAST, *(u8)(val_ptr), u32(4)));
|
|
143
|
+
r := e.io.await(IO_udp.setsockopt(fd, SOL_SOCKET, SO_BROADCAST, *(u8)(val_ptr), u32(4)), e.io);
|
|
148
144
|
cond(
|
|
149
145
|
(r < i32(0)) => {
|
|
150
|
-
_throw_net_io(i32(0) - r);
|
|
146
|
+
_throw_net_io(i32(0) - r, e.exn);
|
|
151
147
|
},
|
|
152
148
|
true => ()
|
|
153
149
|
);
|
package/std/os/signal.yo
CHANGED
|
@@ -78,7 +78,7 @@ _signal_num :: (fn(sig : Signal) -> i32)(
|
|
|
78
78
|
// on_signal / off_signal
|
|
79
79
|
// ============================================================================
|
|
80
80
|
/// Register a handler for the given signal.
|
|
81
|
-
on_signal :: (fn(sig : Signal, handler : SignalHandler,
|
|
81
|
+
on_signal :: (fn(sig : Signal, handler : SignalHandler, exn : Exception) -> unit)({
|
|
82
82
|
num := _signal_num(sig);
|
|
83
83
|
r := _on_signal(num, handler);
|
|
84
84
|
cond(
|
|
@@ -89,7 +89,7 @@ on_signal :: (fn(sig : Signal, handler : SignalHandler, using(exn : Exception))
|
|
|
89
89
|
);
|
|
90
90
|
});
|
|
91
91
|
/// Remove the handler for the given signal.
|
|
92
|
-
off_signal :: (fn(sig : Signal,
|
|
92
|
+
off_signal :: (fn(sig : Signal, exn : Exception) -> unit)({
|
|
93
93
|
num := _signal_num(sig);
|
|
94
94
|
r := _off_signal(num);
|
|
95
95
|
cond(
|
package/std/prelude.yo
CHANGED
|
@@ -113,7 +113,7 @@ extern(
|
|
|
113
113
|
__yo_process_node_version : (fn() -> comptime(comptime_string))
|
|
114
114
|
);
|
|
115
115
|
export(__yo_as);
|
|
116
|
-
/// The `unsafe` module — provides low-level
|
|
116
|
+
/// The `unsafe` module — provides low-level unwind hatches.
|
|
117
117
|
unsafe :: impl({
|
|
118
118
|
/// Manually drop `value`, running its destructor immediately.
|
|
119
119
|
drop :: (fn(quote(value) : Expr) -> unquote(Expr))(quote(___drop(unquote(value))));
|
|
@@ -5903,6 +5903,12 @@ impl(
|
|
|
5903
5903
|
);
|
|
5904
5904
|
_Type :: Type;
|
|
5905
5905
|
export(Type : _Type);
|
|
5906
|
+
// Kind-constraint syntax `Type.Struct`, `Type.Enum`, `Type.Union`,
|
|
5907
|
+
// `Type.Trait`, `Type.Function` is recognised by the evaluator (see
|
|
5908
|
+
// `src/evaluator/exprs/property-access.ts`). Use `T : Type.Struct` for
|
|
5909
|
+
// forall type-variable constraints that signal an effect record (or
|
|
5910
|
+
// other kind-restricted type). The legacy `Struct :: Type` alias was
|
|
5911
|
+
// removed in favour of this syntax.
|
|
5906
5912
|
/// Type reflection metadata structs — used by `Type.get_info()`.
|
|
5907
5913
|
/// StructKind — discriminant for struct flavors.
|
|
5908
5914
|
StructKind :: enum(
|
|
@@ -6591,7 +6597,7 @@ __derive_eq :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(t
|
|
|
6591
6597
|
);
|
|
6592
6598
|
ctx.make_impl(
|
|
6593
6599
|
quote(
|
|
6594
|
-
Eq(
|
|
6600
|
+
Eq(...#(trait_params))(
|
|
6595
6601
|
(==) : ((lhs, rhs) -> #(eq_body))
|
|
6596
6602
|
)
|
|
6597
6603
|
)
|
|
@@ -6661,7 +6667,7 @@ __derive_eq :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(t
|
|
|
6661
6667
|
match_body :: __s3("match(lhs,\n ", eq_branches, "\n )");
|
|
6662
6668
|
ctx.make_impl(
|
|
6663
6669
|
quote(
|
|
6664
|
-
Eq(
|
|
6670
|
+
Eq(...#(trait_params))(
|
|
6665
6671
|
(==) : ((lhs, rhs) -> #(match_body.to_expr()))
|
|
6666
6672
|
)
|
|
6667
6673
|
)
|
|
@@ -6670,7 +6676,7 @@ __derive_eq :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(t
|
|
|
6670
6676
|
true =>
|
|
6671
6677
|
ctx.make_impl(
|
|
6672
6678
|
quote(
|
|
6673
|
-
Eq(
|
|
6679
|
+
Eq(...#(trait_params))(
|
|
6674
6680
|
(==) : ((lhs, rhs) -> true)
|
|
6675
6681
|
)
|
|
6676
6682
|
)
|
|
@@ -6951,7 +6957,7 @@ __derive_ord :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(
|
|
|
6951
6957
|
(fc == 0) =>
|
|
6952
6958
|
ctx.make_impl(
|
|
6953
6959
|
quote(
|
|
6954
|
-
Ord(
|
|
6960
|
+
Ord(...#(trait_params))(
|
|
6955
6961
|
(<) : ((lhs, rhs) -> false),
|
|
6956
6962
|
(<=) : ((lhs, rhs) -> true),
|
|
6957
6963
|
(>) : ((lhs, rhs) -> false),
|
|
@@ -6966,7 +6972,7 @@ __derive_ord :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(
|
|
|
6966
6972
|
ge_body :: __derive_ord_struct_body(T, ">=");
|
|
6967
6973
|
ctx.make_impl(
|
|
6968
6974
|
quote(
|
|
6969
|
-
Ord(
|
|
6975
|
+
Ord(...#(trait_params))(
|
|
6970
6976
|
(<) : ((lhs, rhs) -> #(lt_body.to_expr())),
|
|
6971
6977
|
(<=) : ((lhs, rhs) -> #(le_body.to_expr())),
|
|
6972
6978
|
(>) : ((lhs, rhs) -> #(gt_body.to_expr())),
|
|
@@ -7037,7 +7043,7 @@ __derive_ord :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(
|
|
|
7037
7043
|
ge_match :: __gen_op_branches(">=", "true");
|
|
7038
7044
|
ctx.make_impl(
|
|
7039
7045
|
quote(
|
|
7040
|
-
Ord(
|
|
7046
|
+
Ord(...#(trait_params))(
|
|
7041
7047
|
(<) : ((lhs, rhs) -> #(lt_match.to_expr())),
|
|
7042
7048
|
(<=) : ((lhs, rhs) -> #(le_match.to_expr())),
|
|
7043
7049
|
(>) : ((lhs, rhs) -> #(gt_match.to_expr())),
|
|
@@ -7049,7 +7055,7 @@ __derive_ord :: (fn(comptime(T) : Type, comptime(ctx) : DeriveContext, comptime(
|
|
|
7049
7055
|
true =>
|
|
7050
7056
|
ctx.make_impl(
|
|
7051
7057
|
quote(
|
|
7052
|
-
Ord(
|
|
7058
|
+
Ord(...#(trait_params))(
|
|
7053
7059
|
(<) : ((lhs, rhs) -> false),
|
|
7054
7060
|
(<=) : ((lhs, rhs) -> true),
|
|
7055
7061
|
(>) : ((lhs, rhs) -> false),
|
|
@@ -8145,7 +8151,7 @@ FutureState :: enum(
|
|
|
8145
8151
|
Running = 1,
|
|
8146
8152
|
/// The future completed successfully.
|
|
8147
8153
|
Completed = -(1),
|
|
8148
|
-
/// The future was aborted (e.g., via `
|
|
8154
|
+
/// The future was aborted (e.g., via `unwind`).
|
|
8149
8155
|
Aborted = -(2)
|
|
8150
8156
|
);
|
|
8151
8157
|
impl(FutureState, Acyclic());
|
|
@@ -8172,27 +8178,27 @@ export(JoinHandle);
|
|
|
8172
8178
|
/// IO module — the async runtime effect.
|
|
8173
8179
|
///
|
|
8174
8180
|
/// Provides `io.async`, `io.await`, `io.spawn`, and `io.state` operations.
|
|
8175
|
-
/// Automatically injected into `main` when declared with `
|
|
8181
|
+
/// Automatically injected into `main` when declared with `io : IO`.
|
|
8176
8182
|
IO :: struct(
|
|
8177
8183
|
/// Create a new `Future` from an async closure.
|
|
8178
|
-
async : (fn(forall(T : Type,
|
|
8184
|
+
async : (fn(forall(T : Type, E : Type.Struct), action : Impl(Fn(e : E) -> T)) -> Impl(Future(T, E))),
|
|
8179
8185
|
/// Await a `Future`, suspending until its result is ready.
|
|
8180
|
-
await : (fn(forall(T : Type,
|
|
8186
|
+
await : (fn(forall(T : Type, E : Type.Struct), fut : Impl(Future(T, E)), e : E) -> T),
|
|
8181
8187
|
/// Inspect the current state of a `Future` without blocking.
|
|
8182
|
-
state : (fn(forall(T : Type,
|
|
8188
|
+
state : (fn(forall(T : Type, E : Type), fut : Impl(Future(T, E))) -> FutureState),
|
|
8183
8189
|
/// Spawn a `Future` as an independent task, returning a `JoinHandle`.
|
|
8184
|
-
spawn : (fn(forall(T : Type,
|
|
8190
|
+
spawn : (fn(forall(T : Type, E : Type.Struct), fut : Impl(Future(T, E)), e : E) -> JoinHandle(T))
|
|
8185
8191
|
);
|
|
8186
8192
|
export(IO);
|
|
8187
8193
|
extern(
|
|
8188
8194
|
"Yo",
|
|
8189
|
-
__yo_io_async : (fn(forall(T : Type,
|
|
8190
|
-
__yo_io_await : (fn(forall(T : Type,
|
|
8191
|
-
__yo_io_state : (fn(forall(T : Type,
|
|
8192
|
-
__yo_io_spawn : (fn(forall(T : Type,
|
|
8195
|
+
__yo_io_async : (fn(forall(T : Type, E : Type.Struct), action : Impl(Fn(e : E) -> T)) -> Impl(Future(T, E))),
|
|
8196
|
+
__yo_io_await : (fn(forall(T : Type, E : Type.Struct), fut : Impl(Future(T, E)), e : E) -> T),
|
|
8197
|
+
__yo_io_state : (fn(forall(T : Type, E : Type), fut : Impl(Future(T, E))) -> FutureState),
|
|
8198
|
+
__yo_io_spawn : (fn(forall(T : Type, E : Type.Struct), fut : Impl(Future(T, E)), e : E) -> JoinHandle(T))
|
|
8193
8199
|
);
|
|
8194
8200
|
/// Built-in IO module instance. Automatically injected for `main` functions
|
|
8195
|
-
/// with `
|
|
8201
|
+
/// with `io : IO`.
|
|
8196
8202
|
__yo_builtin_io :: IO(
|
|
8197
8203
|
async : __yo_io_async,
|
|
8198
8204
|
await : __yo_io_await,
|
|
@@ -8200,10 +8206,10 @@ __yo_builtin_io :: IO(
|
|
|
8200
8206
|
spawn : __yo_io_spawn
|
|
8201
8207
|
);
|
|
8202
8208
|
export(__yo_builtin_io);
|
|
8203
|
-
/// JoinHandle methods — defined after IO so `
|
|
8209
|
+
/// JoinHandle methods — defined after IO so `io : IO` resolves.
|
|
8204
8210
|
extern(
|
|
8205
8211
|
"Yo",
|
|
8206
|
-
__yo_join_handle_await : (fn(forall(T : Type), self : JoinHandle(T),
|
|
8212
|
+
__yo_join_handle_await : (fn(forall(T : Type), self : JoinHandle(T), io : IO) -> Option(T))
|
|
8207
8213
|
);
|
|
8208
8214
|
impl(
|
|
8209
8215
|
forall(T : Type),
|