@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.
Files changed (55) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +15 -15
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +110 -121
  3. package/.github/skills/yo-syntax/SKILL.md +2 -2
  4. package/.github/skills/yo-syntax/syntax-cheatsheet.md +49 -75
  5. package/README.md +2 -0
  6. package/out/cjs/index.cjs +622 -611
  7. package/out/cjs/yo-cli.cjs +727 -716
  8. package/out/cjs/yo-lsp.cjs +637 -626
  9. package/out/esm/index.mjs +515 -504
  10. package/out/types/src/codegen/functions/declarations.d.ts +1 -1
  11. package/out/types/src/doc/model.d.ts +0 -1
  12. package/out/types/src/env.d.ts +0 -2
  13. package/out/types/src/evaluator/context.d.ts +1 -1
  14. package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
  15. package/out/types/src/evaluator/types/function.d.ts +1 -2
  16. package/out/types/src/evaluator/utils.d.ts +0 -1
  17. package/out/types/src/expr.d.ts +5 -6
  18. package/out/types/src/types/creators.d.ts +4 -6
  19. package/out/types/src/types/definitions.d.ts +7 -16
  20. package/out/types/src/types/guards.d.ts +1 -2
  21. package/out/types/src/types/tags.d.ts +0 -1
  22. package/out/types/src/types/utils.d.ts +1 -0
  23. package/out/types/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +1 -1
  25. package/std/async.yo +1 -1
  26. package/std/crypto/random.yo +6 -6
  27. package/std/encoding/base64.yo +4 -4
  28. package/std/encoding/hex.yo +2 -2
  29. package/std/encoding/json.yo +3 -3
  30. package/std/encoding/utf16.yo +1 -1
  31. package/std/error.yo +14 -2
  32. package/std/fs/dir.yo +56 -62
  33. package/std/fs/file.yo +118 -124
  34. package/std/fs/metadata.yo +11 -17
  35. package/std/fs/temp.yo +21 -27
  36. package/std/fs/walker.yo +10 -16
  37. package/std/http/client.yo +25 -29
  38. package/std/http/index.yo +4 -4
  39. package/std/io/reader.yo +1 -1
  40. package/std/io/writer.yo +2 -2
  41. package/std/net/addr.yo +1 -1
  42. package/std/net/dns.yo +10 -14
  43. package/std/net/errors.yo +1 -1
  44. package/std/net/tcp.yo +67 -71
  45. package/std/net/udp.yo +36 -40
  46. package/std/os/signal.yo +2 -2
  47. package/std/prelude.yo +27 -21
  48. package/std/process/command.yo +32 -38
  49. package/std/regex/parser.yo +10 -10
  50. package/std/sys/bufio/buf_reader.yo +14 -14
  51. package/std/sys/bufio/buf_writer.yo +17 -17
  52. package/std/sys/errors.yo +1 -1
  53. package/std/thread.yo +2 -2
  54. package/std/url/index.yo +2 -2
  55. 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(using(io : IO)) -> unit)({
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, using(exn : Exception)) -> unit)(
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, using(io : IO)) -> Impl(Future(TcpListener, IO, Exception)))(
77
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(TcpStream, IO, Exception)))({
109
+ accept : (fn(self : Self, io : IO) -> Impl(Future(TcpStream, IOErr)))({
114
110
  fd := self._fd;
115
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
144
+ close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
149
145
  fd := self._fd;
150
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(TcpStream, IO, Exception)))(
194
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
218
+ read : (fn(self : Self, buf : *(u8), size : usize, io : IO) -> Impl(Future(i32, IOErr)))({
223
219
  fd := self._fd;
224
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
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((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
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((using(io : IO, exn : Exception)) => {
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), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
248
+ write_bytes : (fn(self : Self, data : ArrayList(u8), io : IO) -> Impl(Future(i32, IOErr)))({
253
249
  fd := self._fd;
254
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))({
256
+ read_bytes : (fn(self : Self, io : IO) -> Impl(Future(ArrayList(u8), IOErr)))({
261
257
  fd := self._fd;
262
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
289
+ shutdown : (fn(self : Self, how : i32, io : IO) -> Impl(Future(unit, IOErr)))({
294
290
  fd := self._fd;
295
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
302
+ close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
307
303
  fd := self._fd;
308
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
329
+ set_nodelay : (fn(self : Self, nodelay : bool, io : IO) -> Impl(Future(unit, IOErr)))({
334
330
  sock_fd := self._fd;
335
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
344
+ set_keepalive : (fn(self : Self, enabled : bool, io : IO) -> Impl(Future(unit, IOErr)))({
349
345
  sock_fd := self._fd;
350
- io.async((using(io : IO, exn : Exception)) => {
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(using(io : IO)) -> unit)({
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, using(exn : Exception)) -> unit)(
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, using(io : IO)) -> Impl(Future(UdpSocket, IO, Exception)))(
65
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
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((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
94
+ recv : (fn(self : Self, buf : *(u8), size : usize, io : IO) -> Impl(Future(i32, IOErr)))({
99
95
  fd := self._fd;
100
- io.async((using(io : IO, exn : Exception)) => {
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), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
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((using(io : IO, exn : Exception)) => {
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), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
111
+ send : (fn(self : Self, data : ArrayList(u8), io : IO) -> Impl(Future(i32, IOErr)))({
116
112
  fd := self._fd;
117
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
119
+ close : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
124
120
  fd := self._fd;
125
- io.async((using(io : IO, exn : Exception)) => {
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, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
138
+ set_broadcast : (fn(self : Self, enabled : bool, io : IO) -> Impl(Future(unit, IOErr)))({
143
139
  fd := self._fd;
144
- io.async((using(io : IO, exn : Exception)) => {
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, using(exn : Exception)) -> unit)({
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, using(exn : Exception)) -> unit)({
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 escape hatches.
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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(...(#(trait_params)))(
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 `escape`).
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 `using(io : IO)`.
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, ...(E)), action : Impl(Fn(using(...(E))) -> T)) -> Impl(Future(T, ...(E)))),
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, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> T),
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, ...(E)), fut : Impl(Future(T, ...(E)))) -> FutureState),
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, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> JoinHandle(T))
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, ...(E)), action : Impl(Fn(using(...(E))) -> T)) -> Impl(Future(T, ...(E)))),
8190
- __yo_io_await : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> T),
8191
- __yo_io_state : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E)))) -> FutureState),
8192
- __yo_io_spawn : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> JoinHandle(T))
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 `using(io : IO)`.
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 `using(io : IO)` resolves.
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), using(io : IO)) -> Option(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),