@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/process/command.yo
CHANGED
|
@@ -9,23 +9,17 @@
|
|
|
9
9
|
//! { Command } :: import "std/process/command";
|
|
10
10
|
//! { Exception, AnyError } :: import "std/error";
|
|
11
11
|
//!
|
|
12
|
-
//! main :: (fn(
|
|
13
|
-
//! given(exn) := Exception(
|
|
14
|
-
//! throw : (fn(forall(T : Type), error: AnyError) -> T)(
|
|
15
|
-
//! { println(error); panic("Exception"); }
|
|
16
|
-
//! )
|
|
17
|
-
//! );
|
|
18
|
-
//!
|
|
12
|
+
//! main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
19
13
|
//! cmd := Command.new(`echo`);
|
|
20
14
|
//! cmd.arg(`hello`);
|
|
21
15
|
//! cmd.arg(`world`);
|
|
22
|
-
//! out := io.await(cmd.output());
|
|
16
|
+
//! out := io.await(cmd.output(io), { io, exn });
|
|
23
17
|
//! assert(out.status.success(), "echo should succeed");
|
|
24
18
|
//! });
|
|
25
19
|
//! ```
|
|
26
20
|
open(import("../collections/array_list"));
|
|
27
21
|
open(import("../string"));
|
|
28
|
-
{ Exception } :: import("../error");
|
|
22
|
+
{ Exception, IOErr } :: import("../error");
|
|
29
23
|
{ IOError } :: import("../sys/errors");
|
|
30
24
|
IO_process :: import("../sys/process");
|
|
31
25
|
IO_file :: import("../sys/file");
|
|
@@ -155,10 +149,10 @@ _spawn_with_fds :: (
|
|
|
155
149
|
stdin_fd : i32,
|
|
156
150
|
stdout_fd : i32,
|
|
157
151
|
stderr_fd : i32,
|
|
158
|
-
|
|
159
|
-
) -> Impl(Future(i32,
|
|
152
|
+
io : IO
|
|
153
|
+
) -> Impl(Future(i32, IOErr))
|
|
160
154
|
)(
|
|
161
|
-
io.async((
|
|
155
|
+
io.async((e) => {
|
|
162
156
|
storage := _build_cstr_storage(self);
|
|
163
157
|
argc := storage.len();
|
|
164
158
|
// Allocate argv buffer: argc entries + 1 null terminator.
|
|
@@ -188,25 +182,25 @@ _spawn_with_fds :: (
|
|
|
188
182
|
(argv_buf &+ argc).* =.None;
|
|
189
183
|
// Resolve program path C string (always present — _build_cstr_storage pushes program first).
|
|
190
184
|
program_cstr := (argv_buf &+ usize(0)).*.unwrap();
|
|
191
|
-
pid := io.await(IO_process.spawn(program_cstr, argv_buf,.None, stdin_fd, stdout_fd, stderr_fd));
|
|
185
|
+
pid := e.io.await(IO_process.spawn(program_cstr, argv_buf,.None, stdin_fd, stdout_fd, stderr_fd), e.io);
|
|
192
186
|
// Free argv buffer (storage is dropped naturally at scope end).
|
|
193
187
|
free(.Some(argv_raw));
|
|
194
|
-
IOError.check(pid)
|
|
188
|
+
IOError.check(pid, e.exn)
|
|
195
189
|
})
|
|
196
190
|
);
|
|
197
191
|
// Read all available bytes from `fd` into a freshly returned ArrayList(u8)
|
|
198
192
|
// until EOF (read returns 0).
|
|
199
|
-
_drain_fd :: (fn(fd : i32,
|
|
200
|
-
io.async((
|
|
193
|
+
_drain_fd :: (fn(fd : i32, io : IO) -> Impl(Future(ArrayList(u8), IOErr)))(
|
|
194
|
+
io.async((e) => {
|
|
201
195
|
buf_size := usize(4096);
|
|
202
196
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
203
197
|
out := ArrayList(u8).new();
|
|
204
198
|
while(runtime(true), {
|
|
205
|
-
n := io.await(IO_file.read(fd, buf, u32(buf_size), u64(0)));
|
|
199
|
+
n := e.io.await(IO_file.read(fd, buf, u32(buf_size), u64(0)), e.io);
|
|
206
200
|
cond(
|
|
207
201
|
(n < i32(0)) => {
|
|
208
202
|
free(.Some(*(void)(buf)));
|
|
209
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - n)));
|
|
203
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - n)));
|
|
210
204
|
},
|
|
211
205
|
(n == i32(0)) => break,
|
|
212
206
|
true => {
|
|
@@ -229,24 +223,24 @@ impl(
|
|
|
229
223
|
Command,
|
|
230
224
|
/// Spawn the child with stdio inherited from the parent, wait for it to
|
|
231
225
|
/// exit, and return its `ExitStatus`.
|
|
232
|
-
status : (fn(self : *(Self),
|
|
233
|
-
io.async((
|
|
234
|
-
pid := io.await(_spawn_with_fds(self, i32(-(1)), i32(-(1)), i32(-(1))));
|
|
235
|
-
raw := io.await(IO_process.waitpid(pid, i32(0)));
|
|
236
|
-
IOError.check(raw);
|
|
226
|
+
status : (fn(self : *(Self), io : IO) -> Impl(Future(ExitStatus, IOErr)))(
|
|
227
|
+
io.async((e) => {
|
|
228
|
+
pid := e.io.await(_spawn_with_fds(self, i32(-(1)), i32(-(1)), i32(-(1)), io), e);
|
|
229
|
+
raw := e.io.await(IO_process.waitpid(pid, i32(0)), e.io);
|
|
230
|
+
IOError.check(raw, e.exn);
|
|
237
231
|
ExitStatus(raw : raw)
|
|
238
232
|
})
|
|
239
233
|
),
|
|
240
234
|
/// Spawn the child with stdout and stderr captured through pipes. Waits for
|
|
241
235
|
/// the child to exit and returns the exit status plus the captured bytes.
|
|
242
|
-
output : (fn(self : *(Self),
|
|
243
|
-
io.async((
|
|
236
|
+
output : (fn(self : *(Self), io : IO) -> Impl(Future(Output, IOErr)))(
|
|
237
|
+
io.async((e) => {
|
|
244
238
|
// Create stdout and stderr pipes.
|
|
245
239
|
out_fd_buf := MaybeUninit(Array(i32, usize(2))).new();
|
|
246
240
|
out_fd := *(i32)(out_fd_buf.as_ptr());
|
|
247
241
|
pr1 := IO_pipe.pipe(out_fd);
|
|
248
242
|
cond(
|
|
249
|
-
(pr1 < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - pr1))),
|
|
243
|
+
(pr1 < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - pr1))),
|
|
250
244
|
true => ()
|
|
251
245
|
);
|
|
252
246
|
out_read := (out_fd &+ usize(0)).*;
|
|
@@ -256,26 +250,26 @@ impl(
|
|
|
256
250
|
pr2 := IO_pipe.pipe(err_fd);
|
|
257
251
|
cond(
|
|
258
252
|
(pr2 < i32(0)) => {
|
|
259
|
-
io.await(IO_file.close(out_read));
|
|
260
|
-
io.await(IO_file.close(out_write));
|
|
261
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - pr2)));
|
|
253
|
+
e.io.await(IO_file.close(out_read), e.io);
|
|
254
|
+
e.io.await(IO_file.close(out_write), e.io);
|
|
255
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - pr2)));
|
|
262
256
|
},
|
|
263
257
|
true => ()
|
|
264
258
|
);
|
|
265
259
|
err_read := (err_fd &+ usize(0)).*;
|
|
266
260
|
err_write := (err_fd &+ usize(1)).*;
|
|
267
261
|
// Spawn child with the write ends of both pipes.
|
|
268
|
-
pid := io.await(_spawn_with_fds(self, i32(-(1)), out_write, err_write));
|
|
262
|
+
pid := e.io.await(_spawn_with_fds(self, i32(-(1)), out_write, err_write, io), e);
|
|
269
263
|
// Close write ends in parent so reads see EOF when child exits.
|
|
270
|
-
io.await(IO_file.close(out_write));
|
|
271
|
-
io.await(IO_file.close(err_write));
|
|
264
|
+
e.io.await(IO_file.close(out_write), e.io);
|
|
265
|
+
e.io.await(IO_file.close(err_write), e.io);
|
|
272
266
|
// Drain both pipes sequentially.
|
|
273
|
-
stdout_buf := io.await(_drain_fd(out_read));
|
|
274
|
-
stderr_buf := io.await(_drain_fd(err_read));
|
|
275
|
-
io.await(IO_file.close(out_read));
|
|
276
|
-
io.await(IO_file.close(err_read));
|
|
277
|
-
raw := io.await(IO_process.waitpid(pid, i32(0)));
|
|
278
|
-
IOError.check(raw);
|
|
267
|
+
stdout_buf := e.io.await(_drain_fd(out_read, io), e);
|
|
268
|
+
stderr_buf := e.io.await(_drain_fd(err_read, io), e);
|
|
269
|
+
e.io.await(IO_file.close(out_read), e.io);
|
|
270
|
+
e.io.await(IO_file.close(err_read), e.io);
|
|
271
|
+
raw := e.io.await(IO_process.waitpid(pid, i32(0)), e.io);
|
|
272
|
+
IOError.check(raw, e.exn);
|
|
279
273
|
Output(
|
|
280
274
|
status : ExitStatus(raw : raw),
|
|
281
275
|
stdout : stdout_buf,
|
package/std/regex/parser.yo
CHANGED
|
@@ -176,7 +176,7 @@ impl(
|
|
|
176
176
|
r.push(CharRange(low : u32(32), high : u32(32)));
|
|
177
177
|
r
|
|
178
178
|
}),
|
|
179
|
-
// Parse \xHH hex
|
|
179
|
+
// Parse \xHH hex unwind — reads exactly 2 hex digits and returns the codepoint.
|
|
180
180
|
_parse_hex_byte : (fn(self : Self) -> Option(u32))({
|
|
181
181
|
if((self._pos + usize(2)) > self._bytes.len(), {
|
|
182
182
|
return(.None);
|
|
@@ -202,7 +202,7 @@ impl(
|
|
|
202
202
|
self._pos = (self._pos + usize(2));
|
|
203
203
|
.Some(u32((v1 << i32(4)) | v2))
|
|
204
204
|
}),
|
|
205
|
-
|
|
205
|
+
_parse_class_unwind : (fn(self : Self) -> Result(ArrayList(CharRange), String))({
|
|
206
206
|
b := self._advance();
|
|
207
207
|
match(
|
|
208
208
|
b,
|
|
@@ -273,7 +273,7 @@ impl(
|
|
|
273
273
|
// High end is an escape sequence (e.g. \x20, \0, \n)
|
|
274
274
|
self._pos = (self._pos + usize(1));
|
|
275
275
|
self._pos = (self._pos + usize(1));
|
|
276
|
-
esc := self.
|
|
276
|
+
esc := self._parse_class_unwind();
|
|
277
277
|
match(
|
|
278
278
|
esc,
|
|
279
279
|
.Ok(esc_ranges) => {
|
|
@@ -281,7 +281,7 @@ impl(
|
|
|
281
281
|
(high : u32) = esc_ranges.get(usize(0)).unwrap().low;
|
|
282
282
|
ranges.push(CharRange(low : low, high : high));
|
|
283
283
|
}, {
|
|
284
|
-
// Multi-range
|
|
284
|
+
// Multi-range unwind like \d can't be range endpoint; treat dash as literal
|
|
285
285
|
ranges.push(CharRange(low : low, high : low));
|
|
286
286
|
ranges.push(CharRange(low : u32(45), high : u32(45)));
|
|
287
287
|
j := usize(0);
|
|
@@ -331,11 +331,11 @@ impl(
|
|
|
331
331
|
},
|
|
332
332
|
(b == u8(92)) => {
|
|
333
333
|
self._pos = (self._pos + usize(1));
|
|
334
|
-
esc := self.
|
|
334
|
+
esc := self._parse_class_unwind();
|
|
335
335
|
match(
|
|
336
336
|
esc,
|
|
337
337
|
.Ok(esc_ranges) => {
|
|
338
|
-
// If
|
|
338
|
+
// If unwind produced a single codepoint, check for range (e.g. \0-\x20)
|
|
339
339
|
if((esc_ranges.len() == usize(1)) && (esc_ranges.get(usize(0)).unwrap().low == esc_ranges.get(usize(0)).unwrap().high), {
|
|
340
340
|
(low : u32) = esc_ranges.get(usize(0)).unwrap().low;
|
|
341
341
|
self._try_parse_char_range(ranges, low);
|
|
@@ -402,7 +402,7 @@ impl(
|
|
|
402
402
|
});
|
|
403
403
|
.Err(`Unterminated character class`)
|
|
404
404
|
}),
|
|
405
|
-
// Parse \p{PropertyName} or \P{PropertyName} unicode property
|
|
405
|
+
// Parse \p{PropertyName} or \P{PropertyName} unicode property unwind.
|
|
406
406
|
// negated=true for \P (inverted match).
|
|
407
407
|
_parse_unicode_property : (fn(self : Self, negated : bool) -> Result(RegexNode, String))({
|
|
408
408
|
// Expect opening '{'
|
|
@@ -451,7 +451,7 @@ impl(
|
|
|
451
451
|
});
|
|
452
452
|
.Err(`Unterminated Unicode property \\p{...}`)
|
|
453
453
|
}),
|
|
454
|
-
|
|
454
|
+
_parse_unwind : (fn(self : Self) -> Result(RegexNode, String))({
|
|
455
455
|
b := self._advance();
|
|
456
456
|
match(
|
|
457
457
|
b,
|
|
@@ -524,7 +524,7 @@ impl(
|
|
|
524
524
|
(ch == u8(112)) => self._parse_unicode_property(false),
|
|
525
525
|
// Negated unicode property \P{Name}
|
|
526
526
|
(ch == u8(80)) => self._parse_unicode_property(true),
|
|
527
|
-
// Hex
|
|
527
|
+
// Hex unwind \xHH
|
|
528
528
|
(ch == u8(120)) => match(
|
|
529
529
|
self._parse_hex_byte(),
|
|
530
530
|
.Some(v) =>.Ok(RegexNode.literal(v)),
|
|
@@ -627,7 +627,7 @@ impl(
|
|
|
627
627
|
(ch == u8(94)) =>.Ok(RegexNode.anchor_node(.Start)),
|
|
628
628
|
(ch == u8(36)) =>.Ok(RegexNode.anchor_node(.End)),
|
|
629
629
|
(ch == u8(91)) => self._parse_char_class(),
|
|
630
|
-
(ch == u8(92)) => self.
|
|
630
|
+
(ch == u8(92)) => self._parse_unwind(),
|
|
631
631
|
true =>.Ok(RegexNode.literal(self._read_codepoint(ch)))
|
|
632
632
|
),
|
|
633
633
|
.None =>.Err(`Unexpected end of pattern`)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
//! IO_file :: import "std/sys/file";
|
|
11
11
|
//!
|
|
12
12
|
//! reader := BufReader.new(fd);
|
|
13
|
-
//! line := io.await(reader.read_line(
|
|
13
|
+
//! line := io.await(reader.read_line(io));
|
|
14
14
|
//! match(line,
|
|
15
15
|
//! .Ok(.Some(s)) => println(s),
|
|
16
16
|
//! .Ok(.None) => println("EOF"),
|
|
@@ -68,9 +68,9 @@ impl(
|
|
|
68
68
|
// Read a line from the reader (up to and including '\n').
|
|
69
69
|
// Returns .None on EOF when no data is available.
|
|
70
70
|
// Returns .Some(line) with the line content (without the trailing '\n').
|
|
71
|
-
read_line : (fn(self : Self,
|
|
71
|
+
read_line : (fn(self : Self, io : IO) -> Impl(Future(Result(Option(String), IOError), IO)))({
|
|
72
72
|
the_fd := self._fd;
|
|
73
|
-
io.async((
|
|
73
|
+
io.async((io) => {
|
|
74
74
|
line_bytes := ArrayList(u8).new();
|
|
75
75
|
found_newline := false;
|
|
76
76
|
hit_eof := false;
|
|
@@ -95,7 +95,7 @@ impl(
|
|
|
95
95
|
},
|
|
96
96
|
true => {
|
|
97
97
|
raw_buf := *(u8)(malloc(self._capacity).unwrap());
|
|
98
|
-
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset));
|
|
98
|
+
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset), io);
|
|
99
99
|
cond(
|
|
100
100
|
(n < i32(0)) => {
|
|
101
101
|
free(.Some(*(void)(raw_buf)));
|
|
@@ -134,9 +134,9 @@ impl(
|
|
|
134
134
|
}),
|
|
135
135
|
// Read up to `size` bytes into a provided buffer.
|
|
136
136
|
// Returns the number of bytes actually read.
|
|
137
|
-
read : (fn(self : Self, buf : *(u8), size : u32,
|
|
137
|
+
read : (fn(self : Self, buf : *(u8), size : u32, io : IO) -> Impl(Future(Result(i32, IOError), IO)))({
|
|
138
138
|
the_fd := self._fd;
|
|
139
|
-
io.async((
|
|
139
|
+
io.async((io) => {
|
|
140
140
|
available := (self._filled - self._pos);
|
|
141
141
|
(read_err : Option(IOError)) =.None;
|
|
142
142
|
(read_n : i32) = i32(0);
|
|
@@ -163,7 +163,7 @@ impl(
|
|
|
163
163
|
// Buffer is empty and large read: bypass buffer
|
|
164
164
|
cond(
|
|
165
165
|
((!(done)) && (usize(size) >= self._capacity)) => {
|
|
166
|
-
n := io.await(IO_file.read(the_fd, buf, size, self._offset));
|
|
166
|
+
n := io.await(IO_file.read(the_fd, buf, size, self._offset), io);
|
|
167
167
|
cond(
|
|
168
168
|
(n < i32(0)) => {
|
|
169
169
|
read_err =.Some(IOError.from_errno(i32(0) - n));
|
|
@@ -181,7 +181,7 @@ impl(
|
|
|
181
181
|
cond(
|
|
182
182
|
(!(done)) => {
|
|
183
183
|
raw_buf := *(u8)(malloc(self._capacity).unwrap());
|
|
184
|
-
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset));
|
|
184
|
+
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset), io);
|
|
185
185
|
cond(
|
|
186
186
|
(n < i32(0)) => {
|
|
187
187
|
free(.Some(*(void)(raw_buf)));
|
|
@@ -227,9 +227,9 @@ impl(
|
|
|
227
227
|
})
|
|
228
228
|
}),
|
|
229
229
|
// Read all remaining data into an ArrayList of bytes.
|
|
230
|
-
read_bytes : (fn(self : Self,
|
|
230
|
+
read_bytes : (fn(self : Self, io : IO) -> Impl(Future(Result(ArrayList(u8), IOError), IO)))({
|
|
231
231
|
the_fd := self._fd;
|
|
232
|
-
io.async((
|
|
232
|
+
io.async((io) => {
|
|
233
233
|
result := ArrayList(u8).new();
|
|
234
234
|
// First drain any buffered data
|
|
235
235
|
cond(
|
|
@@ -247,7 +247,7 @@ impl(
|
|
|
247
247
|
raw_buf := *(u8)(malloc(self._capacity).unwrap());
|
|
248
248
|
(read_err : Option(IOError)) =.None;
|
|
249
249
|
while(runtime(true), {
|
|
250
|
-
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset));
|
|
250
|
+
n := io.await(IO_file.read(the_fd, raw_buf, u32(self._capacity), self._offset), io);
|
|
251
251
|
cond(
|
|
252
252
|
(n < i32(0)) => {
|
|
253
253
|
read_err =.Some(IOError.from_errno(i32(0) - n));
|
|
@@ -273,9 +273,9 @@ impl(
|
|
|
273
273
|
})
|
|
274
274
|
}),
|
|
275
275
|
// Read all remaining data as a String.
|
|
276
|
-
read_to_string : (fn(self : Self,
|
|
277
|
-
io.async((
|
|
278
|
-
bytes_result := io.await(self.read_bytes(
|
|
276
|
+
read_to_string : (fn(self : Self, io : IO) -> Impl(Future(Result(String, IOError), IO)))(
|
|
277
|
+
io.async((io) => {
|
|
278
|
+
bytes_result := io.await(self.read_bytes(io), io);
|
|
279
279
|
match(
|
|
280
280
|
bytes_result,
|
|
281
281
|
.Ok(bytes) =>.Ok(String.from_bytes(bytes)),
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
//! { BufWriter } :: import "std/sys/bufio/buf_writer";
|
|
10
10
|
//!
|
|
11
11
|
//! writer := BufWriter.new(fd);
|
|
12
|
-
//! io.await(writer.write_string(`hello\n`,
|
|
13
|
-
//! io.await(writer.flush(
|
|
12
|
+
//! io.await(writer.write_string(`hello\n`, io));
|
|
13
|
+
//! io.await(writer.flush(io));
|
|
14
14
|
//! ```
|
|
15
15
|
{ ArrayList } :: import("../../collections/array_list");
|
|
16
16
|
open(import("../../string"));
|
|
@@ -54,9 +54,9 @@ impl(
|
|
|
54
54
|
self._buf.len()
|
|
55
55
|
),
|
|
56
56
|
// Internal: flush the buffer contents to fd.
|
|
57
|
-
_flush_inner : (fn(self : Self,
|
|
57
|
+
_flush_inner : (fn(self : Self, io : IO) -> Impl(Future(Result(unit, IOError), IO)))({
|
|
58
58
|
the_fd := self._fd;
|
|
59
|
-
io.async((
|
|
59
|
+
io.async((io) => {
|
|
60
60
|
(write_err : Option(IOError)) =.None;
|
|
61
61
|
cond(
|
|
62
62
|
(self._buf.len() > usize(0)) => {
|
|
@@ -65,7 +65,7 @@ impl(
|
|
|
65
65
|
while(runtime((written < total) && write_err.is_none()), {
|
|
66
66
|
remaining := u32(total - written);
|
|
67
67
|
buf_ptr := self._buf.ptr().unwrap();
|
|
68
|
-
n := io.await(IO_file.write(the_fd, buf_ptr &+ written, remaining, self._offset));
|
|
68
|
+
n := io.await(IO_file.write(the_fd, buf_ptr &+ written, remaining, self._offset), io);
|
|
69
69
|
cond(
|
|
70
70
|
(n < i32(0)) => {
|
|
71
71
|
write_err =.Some(IOError.from_errno(i32(0) - n));
|
|
@@ -90,9 +90,9 @@ impl(
|
|
|
90
90
|
// Write bytes from a pointer into the buffer.
|
|
91
91
|
// Automatically flushes when the buffer is full.
|
|
92
92
|
// Returns total number of bytes written.
|
|
93
|
-
write : (fn(self : Self, data : *(u8), size : u32,
|
|
93
|
+
write : (fn(self : Self, data : *(u8), size : u32, io : IO) -> Impl(Future(Result(i32, IOError), IO)))({
|
|
94
94
|
the_fd := self._fd;
|
|
95
|
-
io.async((
|
|
95
|
+
io.async((io) => {
|
|
96
96
|
remaining := usize(size);
|
|
97
97
|
src_pos := usize(0);
|
|
98
98
|
(write_err : Option(IOError)) =.None;
|
|
@@ -101,7 +101,7 @@ impl(
|
|
|
101
101
|
cond(
|
|
102
102
|
(space == usize(0)) => {
|
|
103
103
|
// Buffer full, flush it
|
|
104
|
-
flush_result := io.await(self._flush_inner(
|
|
104
|
+
flush_result := io.await(self._flush_inner(io), io);
|
|
105
105
|
match(
|
|
106
106
|
flush_result,
|
|
107
107
|
.Err(e) => {
|
|
@@ -133,24 +133,24 @@ impl(
|
|
|
133
133
|
})
|
|
134
134
|
}),
|
|
135
135
|
// Write a String to the buffer.
|
|
136
|
-
write_string : (fn(self : Self, s : String,
|
|
137
|
-
io.async((
|
|
136
|
+
write_string : (fn(self : Self, s : String, io : IO) -> Impl(Future(Result(i32, IOError), IO)))(
|
|
137
|
+
io.async((io) => {
|
|
138
138
|
bytes := s.as_bytes();
|
|
139
|
-
result := io.await(self.write(bytes.ptr().unwrap(), u32(bytes.len()),
|
|
139
|
+
result := io.await(self.write(bytes.ptr().unwrap(), u32(bytes.len()), io), io);
|
|
140
140
|
result
|
|
141
141
|
})
|
|
142
142
|
),
|
|
143
143
|
// Write bytes from an ArrayList to the buffer.
|
|
144
|
-
write_bytes : (fn(self : Self, data : ArrayList(u8),
|
|
145
|
-
io.async((
|
|
146
|
-
result := io.await(self.write(data.ptr().unwrap(), u32(data.len()),
|
|
144
|
+
write_bytes : (fn(self : Self, data : ArrayList(u8), io : IO) -> Impl(Future(Result(i32, IOError), IO)))(
|
|
145
|
+
io.async((io) => {
|
|
146
|
+
result := io.await(self.write(data.ptr().unwrap(), u32(data.len()), io), io);
|
|
147
147
|
result
|
|
148
148
|
})
|
|
149
149
|
),
|
|
150
150
|
// Flush all buffered data to the underlying file descriptor.
|
|
151
|
-
flush : (fn(self : Self,
|
|
152
|
-
io.async((
|
|
153
|
-
flush_result := io.await(self._flush_inner(
|
|
151
|
+
flush : (fn(self : Self, io : IO) -> Impl(Future(Result(unit, IOError), IO)))(
|
|
152
|
+
io.async((io) => {
|
|
153
|
+
flush_result := io.await(self._flush_inner(io), io);
|
|
154
154
|
flush_result
|
|
155
155
|
})
|
|
156
156
|
)
|
package/std/sys/errors.yo
CHANGED
|
@@ -171,7 +171,7 @@ impl(IOError, Error());
|
|
|
171
171
|
impl(
|
|
172
172
|
IOError,
|
|
173
173
|
// Check a raw result code, throwing on error via Exception effect.
|
|
174
|
-
check : (fn(result : i32,
|
|
174
|
+
check : (fn(result : i32, exn : Exception) -> i32)(
|
|
175
175
|
cond(
|
|
176
176
|
(result >= i32(0)) => result,
|
|
177
177
|
true => exn.throw(dyn(Self.from_errno(i32(0) - result)))
|
package/std/thread.yo
CHANGED
|
@@ -8,7 +8,7 @@ extern(
|
|
|
8
8
|
extern(
|
|
9
9
|
"Yo",
|
|
10
10
|
__yo_thread_t : Type,
|
|
11
|
-
__yo_thread_spawn : (fn(cb : Impl(Fn(
|
|
11
|
+
__yo_thread_spawn : (fn(cb : Impl(Fn(io : IO) -> unit, Send)) -> __yo_thread_t),
|
|
12
12
|
__yo_thread_join : (fn(t : __yo_thread_t) -> unit)
|
|
13
13
|
);
|
|
14
14
|
/// OS thread handle. Each spawned thread gets its own IO event loop.
|
|
@@ -19,7 +19,7 @@ impl(
|
|
|
19
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
|
-
spawn : (fn(cb : Impl(Fn(
|
|
22
|
+
spawn : (fn(cb : Impl(Fn(io : IO) -> unit, Send)) -> Self)({
|
|
23
23
|
raw := __yo_thread_spawn(cb);
|
|
24
24
|
Self(raw)
|
|
25
25
|
}),
|
package/std/url/index.yo
CHANGED
|
@@ -51,7 +51,7 @@ _DOT :: u8(46); // '.'
|
|
|
51
51
|
// ============================================================================
|
|
52
52
|
// Helper: parse port number from bytes
|
|
53
53
|
// ============================================================================
|
|
54
|
-
_parse_port :: (fn(s : str, start : usize, end : usize,
|
|
54
|
+
_parse_port :: (fn(s : str, start : usize, end : usize, exn : Exception) -> u16)({
|
|
55
55
|
cond(
|
|
56
56
|
(start >= end) => {
|
|
57
57
|
exn.throw(dyn(UrlError.InvalidPort));
|
|
@@ -95,7 +95,7 @@ impl(
|
|
|
95
95
|
// Parse a URL string.
|
|
96
96
|
// Supports: scheme://[userinfo@]host[:port]/path[?query][#fragment]
|
|
97
97
|
// Also supports scheme:path (opaque URIs like mailto:user@example.com)
|
|
98
|
-
parse : (fn(s : str,
|
|
98
|
+
parse : (fn(s : str, exn : Exception) -> Url)({
|
|
99
99
|
cond(
|
|
100
100
|
(s.len() == usize(0)) => {
|
|
101
101
|
exn.throw(dyn(UrlError.EmptyInput));
|
package/std/worker.yo
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
//! Each worker thread has its own GC heap and async IO event loop.
|
|
5
5
|
extern(
|
|
6
6
|
"Yo",
|
|
7
|
-
__yo_worker_spawn : (fn(cb : Impl(Fn(
|
|
7
|
+
__yo_worker_spawn : (fn(cb : Impl(Fn(io : IO) -> unit, Send)) -> unit),
|
|
8
8
|
__yo_worker_get_num_threads : (fn() -> usize),
|
|
9
9
|
__yo_worker_set_num_threads : (fn(num : usize) -> unit)
|
|
10
10
|
);
|
|
11
11
|
/// Spawn a task on the thread pool. Returns immediately; the task runs in the background.
|
|
12
12
|
/// Tasks are distributed round-robin to worker threads.
|
|
13
|
-
spawn :: (fn(cb : Impl(Fn(
|
|
13
|
+
spawn :: (fn(cb : Impl(Fn(io : IO) -> unit, Send)) -> unit)({
|
|
14
14
|
__yo_worker_spawn(cb);
|
|
15
15
|
});
|
|
16
16
|
/// Get the number of worker threads in the pool.
|