@shd101wyy/yo 0.1.27 → 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-core-patterns/core-patterns-cheatsheet.md +3 -0
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +2 -0
- package/.github/skills/yo-syntax/SKILL.md +2 -2
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +195 -73
- package/README.md +2 -0
- package/out/cjs/index.cjs +624 -613
- package/out/cjs/yo-cli.cjs +739 -727
- package/out/cjs/yo-lsp.cjs +636 -625
- package/out/esm/index.mjs +526 -515
- 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 +1 -2
- package/out/types/src/evaluator/calls/helper.d.ts +4 -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/types/synthesizer.d.ts +1 -0
- package/out/types/src/evaluator/utils.d.ts +0 -1
- package/out/types/src/expr.d.ts +5 -6
- package/out/types/src/test-runner.d.ts +2 -0
- 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/scripts/probe-parser-parity.ts +61 -0
- package/scripts/probe-yo-self-parser.sh +33 -0
- package/scripts/validate-yo-self-fmt.ts +184 -0
- 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/fs/temp.yo
CHANGED
|
@@ -5,16 +5,10 @@
|
|
|
5
5
|
//! ```rust
|
|
6
6
|
//! { TempDir } :: import "std/fs/temp";
|
|
7
7
|
//!
|
|
8
|
-
//! main :: (fn(
|
|
9
|
-
//!
|
|
10
|
-
//! throw : (fn(forall(T : Type), error: AnyError) -> T)(
|
|
11
|
-
//! { println(error.to_string()); exit(i32(1)); }
|
|
12
|
-
//! )
|
|
13
|
-
//! };
|
|
14
|
-
//!
|
|
15
|
-
//! dir := io.await(TempDir.new());
|
|
8
|
+
//! main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
9
|
+
//! dir := io.await(TempDir.new(io), { io, exn });
|
|
16
10
|
//! println(dir.path());
|
|
17
|
-
//! io.await(dir.remove());
|
|
11
|
+
//! io.await(dir.remove(io), { io, exn });
|
|
18
12
|
//! });
|
|
19
13
|
//! ```
|
|
20
14
|
{ GlobalAllocator } :: import("../allocator");
|
|
@@ -23,7 +17,7 @@ open(import("../string"));
|
|
|
23
17
|
open(import("../fmt"));
|
|
24
18
|
{ Path } :: import("../path");
|
|
25
19
|
{ IOError } :: import("../sys/errors");
|
|
26
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
20
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
27
21
|
_file_mod :: import("./file");
|
|
28
22
|
_dir_mod :: import("./dir");
|
|
29
23
|
IO_temp :: import("../sys/temp");
|
|
@@ -59,8 +53,8 @@ TempDir :: object(
|
|
|
59
53
|
impl(
|
|
60
54
|
TempDir,
|
|
61
55
|
// Create a temporary directory in the given parent directory.
|
|
62
|
-
new_in : (fn(parent : Path,
|
|
63
|
-
io.async((
|
|
56
|
+
new_in : (fn(parent : Path, io : IO) -> Impl(Future(TempDir, IOErr)))(
|
|
57
|
+
io.async((e) => {
|
|
64
58
|
// Build template: parent/yo_tmp_XXXXXX
|
|
65
59
|
template_path := parent.join(Path.new(`yo_tmp_XXXXXX`));
|
|
66
60
|
template_str := template_path.to_string();
|
|
@@ -74,7 +68,7 @@ impl(
|
|
|
74
68
|
cond(
|
|
75
69
|
(result < i32(0)) => {
|
|
76
70
|
free(.Some(*(void)(buf)));
|
|
77
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - result)));
|
|
71
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - result)));
|
|
78
72
|
},
|
|
79
73
|
true => ()
|
|
80
74
|
);
|
|
@@ -84,22 +78,22 @@ impl(
|
|
|
84
78
|
})
|
|
85
79
|
),
|
|
86
80
|
// Create a temporary directory in the system temp dir.
|
|
87
|
-
new : (fn(
|
|
88
|
-
TempDir.new_in(Path.new(_default_tmp_dir()))
|
|
81
|
+
new : (fn(io : IO) -> Impl(Future(TempDir, IOErr)))(
|
|
82
|
+
TempDir.new_in(Path.new(_default_tmp_dir()), io)
|
|
89
83
|
),
|
|
90
84
|
// Get the path of the temporary directory.
|
|
91
85
|
path : (fn(self : Self) -> Path)(
|
|
92
86
|
self._path
|
|
93
87
|
),
|
|
94
88
|
// Remove the temporary directory.
|
|
95
|
-
remove : (fn(self : Self,
|
|
89
|
+
remove : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
96
90
|
self_path := self._path;
|
|
97
91
|
io.async(
|
|
98
|
-
(
|
|
92
|
+
(e) =>
|
|
99
93
|
cond(
|
|
100
94
|
self._removed => (),
|
|
101
95
|
true => {
|
|
102
|
-
io.await(_dir_mod.remove_dir(self_path));
|
|
96
|
+
e.io.await(_dir_mod.remove_dir(self_path, io), e);
|
|
103
97
|
self._removed = true;
|
|
104
98
|
}
|
|
105
99
|
)
|
|
@@ -116,8 +110,8 @@ TempFile :: object(
|
|
|
116
110
|
impl(
|
|
117
111
|
TempFile,
|
|
118
112
|
// Create a temporary file in the given parent directory.
|
|
119
|
-
new_in : (fn(parent : Path,
|
|
120
|
-
io.async((
|
|
113
|
+
new_in : (fn(parent : Path, io : IO) -> Impl(Future(TempFile, IOErr)))(
|
|
114
|
+
io.async((e) => {
|
|
121
115
|
// Build template: parent/yo_tmp_XXXXXX
|
|
122
116
|
template_path := parent.join(Path.new(`yo_tmp_XXXXXX`));
|
|
123
117
|
template_str := template_path.to_string();
|
|
@@ -130,7 +124,7 @@ impl(
|
|
|
130
124
|
cond(
|
|
131
125
|
(fd < i32(0)) => {
|
|
132
126
|
free(.Some(*(void)(buf)));
|
|
133
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - fd)));
|
|
127
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - fd)));
|
|
134
128
|
},
|
|
135
129
|
true => ()
|
|
136
130
|
);
|
|
@@ -142,8 +136,8 @@ impl(
|
|
|
142
136
|
})
|
|
143
137
|
),
|
|
144
138
|
// Create a temporary file in the system temp dir.
|
|
145
|
-
new : (fn(
|
|
146
|
-
TempFile.new_in(Path.new(_default_tmp_dir()))
|
|
139
|
+
new : (fn(io : IO) -> Impl(Future(TempFile, IOErr)))(
|
|
140
|
+
TempFile.new_in(Path.new(_default_tmp_dir()), io)
|
|
147
141
|
),
|
|
148
142
|
// Get the underlying File object.
|
|
149
143
|
file : (fn(self : Self) -> _file_mod.File)(
|
|
@@ -154,16 +148,16 @@ impl(
|
|
|
154
148
|
self._path
|
|
155
149
|
),
|
|
156
150
|
// Remove the temporary file.
|
|
157
|
-
remove : (fn(self : Self,
|
|
151
|
+
remove : (fn(self : Self, io : IO) -> Impl(Future(unit, IOErr)))({
|
|
158
152
|
self_file := self._file;
|
|
159
153
|
self_path := self._path;
|
|
160
154
|
io.async(
|
|
161
|
-
(
|
|
155
|
+
(e) =>
|
|
162
156
|
cond(
|
|
163
157
|
self._removed => (),
|
|
164
158
|
true => {
|
|
165
|
-
io.await(self_file.close());
|
|
166
|
-
io.await(_dir_mod.remove_file(self_path));
|
|
159
|
+
e.io.await(self_file.close(io), e);
|
|
160
|
+
e.io.await(_dir_mod.remove_file(self_path, io), e);
|
|
167
161
|
self._removed = true;
|
|
168
162
|
}
|
|
169
163
|
)
|
package/std/fs/walker.yo
CHANGED
|
@@ -5,14 +5,8 @@
|
|
|
5
5
|
//! ```rust
|
|
6
6
|
//! { walk, WalkEntry } :: import "std/fs/walker";
|
|
7
7
|
//!
|
|
8
|
-
//! main :: (fn(
|
|
9
|
-
//!
|
|
10
|
-
//! throw : (fn(forall(T : Type), error: AnyError) -> T)(
|
|
11
|
-
//! { println(error.to_string()); exit(i32(1)); }
|
|
12
|
-
//! )
|
|
13
|
-
//! };
|
|
14
|
-
//!
|
|
15
|
-
//! entries := io.await(walk(`/tmp`));
|
|
8
|
+
//! main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
9
|
+
//! entries := io.await(walk(Path.new(`/tmp`), io), { io, exn });
|
|
16
10
|
//! i := usize(0);
|
|
17
11
|
//! while runtime((i < entries.len())), {
|
|
18
12
|
//! e := entries.get(i).unwrap();
|
|
@@ -25,7 +19,7 @@
|
|
|
25
19
|
open(import("../string"));
|
|
26
20
|
{ Path } :: import("../path");
|
|
27
21
|
{ IOError } :: import("../sys/errors");
|
|
28
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
22
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
29
23
|
{ FileType } :: import("./dir");
|
|
30
24
|
{ DirEntry } :: import("./dir");
|
|
31
25
|
_dir :: import("./dir");
|
|
@@ -67,9 +61,9 @@ _join_path :: (fn(base : String, name : String) -> String)(
|
|
|
67
61
|
// Walk functions
|
|
68
62
|
// ============================================================================
|
|
69
63
|
// Walk a directory tree with custom options.
|
|
70
|
-
walk_with :: (fn(root : Path, options : WalkOptions,
|
|
64
|
+
walk_with :: (fn(root : Path, options : WalkOptions, io : IO) -> Impl(Future(ArrayList(WalkEntry), IOErr)))({
|
|
71
65
|
root_s := root.to_string();
|
|
72
|
-
io.async((
|
|
66
|
+
io.async((e) => {
|
|
73
67
|
results := ArrayList(WalkEntry).new();
|
|
74
68
|
// Stack of (path, depth) pairs to process
|
|
75
69
|
stack := ArrayList(struct(path : String, depth : u32)).new();
|
|
@@ -86,7 +80,7 @@ walk_with :: (fn(root : Path, options : WalkOptions, using(io : IO)) -> Impl(Fut
|
|
|
86
80
|
);
|
|
87
81
|
cond(
|
|
88
82
|
should_continue => {
|
|
89
|
-
entries := io.await(_dir.read_dir(Path.new(cur_path)));
|
|
83
|
+
entries := e.io.await(_dir.read_dir(Path.new(cur_path), e.io), e);
|
|
90
84
|
i := usize(0);
|
|
91
85
|
while(runtime(i < entries.len()), {
|
|
92
86
|
entry := entries.get(i).unwrap();
|
|
@@ -130,10 +124,10 @@ walk_with :: (fn(root : Path, options : WalkOptions, using(io : IO)) -> Impl(Fut
|
|
|
130
124
|
results
|
|
131
125
|
})
|
|
132
126
|
});
|
|
133
|
-
walk_with_cstr :: (fn(root : *(u8), options : WalkOptions,
|
|
134
|
-
walk_with(Path.from_cstr(root), options)
|
|
127
|
+
walk_with_cstr :: (fn(root : *(u8), options : WalkOptions, io : IO) -> Impl(Future(ArrayList(WalkEntry), IOErr)))(
|
|
128
|
+
walk_with(Path.from_cstr(root), options, io)
|
|
135
129
|
);
|
|
136
130
|
/// Walk a directory tree with default options.
|
|
137
|
-
walk :: (fn(root : Path,
|
|
138
|
-
walk_cstr :: (fn(root : *(u8),
|
|
131
|
+
walk :: (fn(root : Path, io : IO) -> Impl(Future(ArrayList(WalkEntry), IOErr)))(walk_with(root, WalkOptions.defaults(), io));
|
|
132
|
+
walk_cstr :: (fn(root : *(u8), io : IO) -> Impl(Future(ArrayList(WalkEntry), IOErr)))(walk(Path.from_cstr(root), io));
|
|
139
133
|
export(walk, walk_cstr, walk_with, walk_with_cstr);
|
package/std/http/client.yo
CHANGED
|
@@ -8,12 +8,8 @@
|
|
|
8
8
|
// { fetch, HttpResponse } :: import "std/http";
|
|
9
9
|
// { Exception } :: import "std/error";
|
|
10
10
|
//
|
|
11
|
-
// main :: (fn(
|
|
12
|
-
//
|
|
13
|
-
// println(err.message());
|
|
14
|
-
// escape ();
|
|
15
|
-
// }));
|
|
16
|
-
// resp := io.await(fetch(`http://example.com/api/data`, using(io)));
|
|
11
|
+
// main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
12
|
+
// resp := io.await(fetch(`http://example.com/api/data`, io), { io, exn });
|
|
17
13
|
// println(resp.body);
|
|
18
14
|
// });
|
|
19
15
|
open(import("../string"));
|
|
@@ -21,7 +17,7 @@ open(import("../string"));
|
|
|
21
17
|
{ GlobalAllocator } :: import("../allocator");
|
|
22
18
|
{ malloc, free } :: GlobalAllocator;
|
|
23
19
|
open(import("../fmt"));
|
|
24
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
20
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
25
21
|
{ TcpStream } :: import("../net/tcp");
|
|
26
22
|
{ IpAddr, SocketAddr } :: import("../net/addr");
|
|
27
23
|
{ lookup_host } :: import("../net/dns");
|
|
@@ -179,14 +175,14 @@ _find_content_length :: (fn(data : ArrayList(u8), header_end : usize) -> i32)({
|
|
|
179
175
|
// ============================================================================
|
|
180
176
|
// Internal: read full HTTP response from a TCP stream
|
|
181
177
|
// ============================================================================
|
|
182
|
-
_read_http_response :: (fn(stream : TcpStream,
|
|
178
|
+
_read_http_response :: (fn(stream : TcpStream, e : IOErr) -> String)({
|
|
183
179
|
buf_size := usize(8192);
|
|
184
180
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
185
181
|
result := ArrayList(u8).new();
|
|
186
182
|
// Read until connection closes or we've read the full response
|
|
187
183
|
done := false;
|
|
188
184
|
while(runtime(!(done)), {
|
|
189
|
-
n := io.await(stream.read(buf, buf_size,
|
|
185
|
+
n := e.io.await(stream.read(buf, buf_size, e.io), e);
|
|
190
186
|
cond(
|
|
191
187
|
(n <= i32(0)) => {
|
|
192
188
|
done = true;
|
|
@@ -243,15 +239,15 @@ _read_http_response :: (fn(stream : TcpStream, using(io : IO, exn : Exception))
|
|
|
243
239
|
///
|
|
244
240
|
/// ```rust
|
|
245
241
|
/// opts := FetchOptions.new().with_method(.POST).with_body(`{"key": "value"}`);
|
|
246
|
-
/// resp := io.await(fetch_with(`http://example.com/api`, opts,
|
|
242
|
+
/// resp := io.await(fetch_with(`http://example.com/api`, opts, io), { io, exn });
|
|
247
243
|
/// ```
|
|
248
244
|
fetch_with :: (
|
|
249
|
-
fn(url_str : String, opts : FetchOptions,
|
|
250
|
-
Impl(Future(HttpResponse,
|
|
245
|
+
fn(url_str : String, opts : FetchOptions, io : IO) ->
|
|
246
|
+
Impl(Future(HttpResponse, IOErr))
|
|
251
247
|
)(
|
|
252
|
-
io.async((
|
|
248
|
+
io.async((e) => {
|
|
253
249
|
// Parse URL
|
|
254
|
-
url := Url.parse(url_str.as_str(),
|
|
250
|
+
url := Url.parse(url_str.as_str(), e.exn);
|
|
255
251
|
// Validate scheme
|
|
256
252
|
scheme := url.scheme();
|
|
257
253
|
is_http := (scheme == `http`);
|
|
@@ -259,7 +255,7 @@ fetch_with :: (
|
|
|
259
255
|
cond(
|
|
260
256
|
(is_http || is_https) => (),
|
|
261
257
|
true => {
|
|
262
|
-
exn.throw(dyn(HttpError.UnsupportedScheme(scheme)));
|
|
258
|
+
e.exn.throw(dyn(HttpError.UnsupportedScheme(scheme)));
|
|
263
259
|
}
|
|
264
260
|
);
|
|
265
261
|
// Extract host
|
|
@@ -267,7 +263,7 @@ fetch_with :: (
|
|
|
267
263
|
url.host(),
|
|
268
264
|
.Some(h) => h,
|
|
269
265
|
.None => {
|
|
270
|
-
exn.throw(dyn(HttpError.InvalidUrl(`missing host`)));
|
|
266
|
+
e.exn.throw(dyn(HttpError.InvalidUrl(`missing host`)));
|
|
271
267
|
`_` // unreachable
|
|
272
268
|
}
|
|
273
269
|
);
|
|
@@ -281,17 +277,17 @@ fetch_with :: (
|
|
|
281
277
|
)
|
|
282
278
|
);
|
|
283
279
|
// Resolve hostname to IP
|
|
284
|
-
addrs := io.await(lookup_host(host,
|
|
280
|
+
addrs := e.io.await(lookup_host(host, e.io), e);
|
|
285
281
|
cond(
|
|
286
282
|
(addrs.len() == usize(0)) => {
|
|
287
|
-
exn.throw(dyn(HttpError.ConnectionFailed(`DNS resolution failed for ${host}`)));
|
|
283
|
+
e.exn.throw(dyn(HttpError.ConnectionFailed(`DNS resolution failed for ${host}`)));
|
|
288
284
|
},
|
|
289
285
|
true => ()
|
|
290
286
|
);
|
|
291
287
|
ip := addrs.get(usize(0)).unwrap();
|
|
292
288
|
addr := SocketAddr.new(ip, port);
|
|
293
289
|
// Connect
|
|
294
|
-
stream := io.await(TcpStream.connect(addr,
|
|
290
|
+
stream := e.io.await(TcpStream.connect(addr, e.io), e);
|
|
295
291
|
// Build the request path (include query string if present)
|
|
296
292
|
req_path := url.path();
|
|
297
293
|
cond(
|
|
@@ -329,17 +325,17 @@ fetch_with :: (
|
|
|
329
325
|
req.set_header(`Connection`, `close`);
|
|
330
326
|
// Send request
|
|
331
327
|
req_str := req.to_string();
|
|
332
|
-
io.await(stream.write_string(req_str,
|
|
328
|
+
e.io.await(stream.write_string(req_str, e.io), e);
|
|
333
329
|
// Read response
|
|
334
|
-
raw_response := _read_http_response(stream,
|
|
330
|
+
raw_response := _read_http_response(stream, e);
|
|
335
331
|
// Close connection
|
|
336
|
-
io.await(stream.close(
|
|
332
|
+
e.io.await(stream.close(e.io), e);
|
|
337
333
|
// Parse response
|
|
338
334
|
match(
|
|
339
335
|
parse_response(raw_response),
|
|
340
336
|
.Ok(resp) => resp,
|
|
341
|
-
.Err(
|
|
342
|
-
exn.throw(dyn(HttpError.Other(
|
|
337
|
+
.Err(err) => {
|
|
338
|
+
e.exn.throw(dyn(HttpError.Other(err)));
|
|
343
339
|
HttpResponse.new(i32(0), ``) // unreachable
|
|
344
340
|
}
|
|
345
341
|
)
|
|
@@ -352,15 +348,15 @@ export(fetch_with);
|
|
|
352
348
|
/// # Example
|
|
353
349
|
///
|
|
354
350
|
/// ```rust
|
|
355
|
-
/// resp := io.await(fetch(`http://example.com`,
|
|
351
|
+
/// resp := io.await(fetch(`http://example.com`, io), { io, exn });
|
|
356
352
|
/// cond(resp.is_ok() => println(resp.body), true => println(`Error`));
|
|
357
353
|
/// ```
|
|
358
354
|
fetch :: (
|
|
359
|
-
fn(url_str : String,
|
|
360
|
-
Impl(Future(HttpResponse,
|
|
355
|
+
fn(url_str : String, io : IO) ->
|
|
356
|
+
Impl(Future(HttpResponse, IOErr))
|
|
361
357
|
)(
|
|
362
|
-
io.async((
|
|
363
|
-
return(io.await(fetch_with(url_str, FetchOptions.new(),
|
|
358
|
+
io.async((e) => {
|
|
359
|
+
return(e.io.await(fetch_with(url_str, FetchOptions.new(), e.io), e));
|
|
364
360
|
})
|
|
365
361
|
);
|
|
366
362
|
export(fetch);
|
package/std/http/index.yo
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
// { HttpRequest, HttpResponse, fetch } :: import "std/http";
|
|
6
6
|
// { Exception } :: import "std/error";
|
|
7
7
|
//
|
|
8
|
-
// main :: (fn(
|
|
9
|
-
//
|
|
8
|
+
// main :: (fn(io : IO) -> unit)({
|
|
9
|
+
// exn := Exception(throw : ((err) -> {
|
|
10
10
|
// println(err.message());
|
|
11
|
-
//
|
|
11
|
+
// unwind ();
|
|
12
12
|
// }));
|
|
13
|
-
// resp := io.await(fetch(`http://example.com`,
|
|
13
|
+
// resp := io.await(fetch(`http://example.com`, io));
|
|
14
14
|
// println(resp.body);
|
|
15
15
|
// });
|
|
16
16
|
_http :: import("./http.yo");
|
package/std/io/reader.yo
CHANGED
|
@@ -5,6 +5,6 @@ Reader :: trait(
|
|
|
5
5
|
/// Read up to `size` bytes into buffer `buf`.
|
|
6
6
|
/// Returns the number of bytes actually read (0 at end-of-stream).
|
|
7
7
|
read :
|
|
8
|
-
fn(self : *(Self), buf : *(u8), size : usize,
|
|
8
|
+
fn(self : *(Self), buf : *(u8), size : usize, exn : Exception) -> usize
|
|
9
9
|
);
|
|
10
10
|
export(Reader);
|
package/std/io/writer.yo
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
Writer :: trait(
|
|
5
5
|
/// Write bytes from buffer. Returns number of bytes written.
|
|
6
6
|
write :
|
|
7
|
-
fn(self : *(Self), buf : *(u8), size : usize,
|
|
7
|
+
fn(self : *(Self), buf : *(u8), size : usize, exn : Exception) -> usize,
|
|
8
8
|
/// Flush any buffered data to the underlying destination.
|
|
9
9
|
flush :
|
|
10
|
-
fn(self : *(Self),
|
|
10
|
+
fn(self : *(Self), exn : Exception) -> unit
|
|
11
11
|
);
|
|
12
12
|
export(Writer);
|
package/std/net/addr.yo
CHANGED
|
@@ -33,7 +33,7 @@ impl(
|
|
|
33
33
|
IpAddr,
|
|
34
34
|
/// Parse an IPv4 address from a dotted-decimal `String` (e.g. "127.0.0.1").
|
|
35
35
|
/// Throws on invalid input.
|
|
36
|
-
parse_v4 : (fn(s : String,
|
|
36
|
+
parse_v4 : (fn(s : String, exn : Exception) -> IpAddr)({
|
|
37
37
|
bytes := s.as_bytes();
|
|
38
38
|
parts := Array(u8, usize(4)).fill(u8(0));
|
|
39
39
|
part_idx := usize(0);
|
package/std/net/dns.yo
CHANGED
|
@@ -9,12 +9,8 @@
|
|
|
9
9
|
// { IpAddr } :: import "std/net/addr";
|
|
10
10
|
// { Exception } :: import "std/error";
|
|
11
11
|
//
|
|
12
|
-
// main :: (fn(
|
|
13
|
-
//
|
|
14
|
-
// println(err.message());
|
|
15
|
-
// escape ();
|
|
16
|
-
// }));
|
|
17
|
-
// addrs := io.await(lookup_host(`localhost`));
|
|
12
|
+
// main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
13
|
+
// addrs := io.await(lookup_host(`localhost`, io), { io, exn });
|
|
18
14
|
// i := usize(0);
|
|
19
15
|
// while runtime((i < addrs.len())), {
|
|
20
16
|
// println(addrs.get(i).unwrap().to_string());
|
|
@@ -28,23 +24,23 @@ open(import("../string"));
|
|
|
28
24
|
open(import("../fmt"));
|
|
29
25
|
{ NetError } :: import("./errors");
|
|
30
26
|
{ IpAddr, SocketAddr } :: import("./addr");
|
|
31
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
27
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
32
28
|
IO_dns :: import("../sys/dns");
|
|
33
29
|
{ AF_INET, AF_INET6 } :: import("../sys/socket");
|
|
34
30
|
// ============================================================================
|
|
35
31
|
// DNS lookup
|
|
36
32
|
// ============================================================================
|
|
37
33
|
/// Resolve a hostname to a list of IP addresses.
|
|
38
|
-
lookup_host :: (fn(host : String,
|
|
39
|
-
io.async((
|
|
34
|
+
lookup_host :: (fn(host : String, io : IO) -> Impl(Future(ArrayList(IpAddr), IOErr)))(
|
|
35
|
+
io.async((e) => {
|
|
40
36
|
host_cstr_bytes := host.to_cstr();
|
|
41
37
|
host_cstr := host_cstr_bytes.ptr().unwrap();
|
|
42
38
|
result_ptr := IO_dns.alloc_result();
|
|
43
|
-
ret := io.await(IO_dns.getaddrinfo(host_cstr,.None,.None, result_ptr));
|
|
39
|
+
ret := e.io.await(IO_dns.getaddrinfo(host_cstr,.None,.None, result_ptr), e.io);
|
|
44
40
|
cond(
|
|
45
41
|
(ret != i32(0)) => {
|
|
46
42
|
IO_dns.free_result(result_ptr);
|
|
47
|
-
exn.throw(dyn(NetError.DNSFailed(host)));
|
|
43
|
+
e.exn.throw(dyn(NetError.DNSFailed(host)));
|
|
48
44
|
},
|
|
49
45
|
true => ()
|
|
50
46
|
);
|
|
@@ -86,9 +82,9 @@ lookup_host :: (fn(host : String, using(io : IO)) -> Impl(Future(ArrayList(IpAdd
|
|
|
86
82
|
})
|
|
87
83
|
);
|
|
88
84
|
/// Resolve a hostname and port to a list of socket addresses.
|
|
89
|
-
resolve :: (fn(host : String, port : u16,
|
|
90
|
-
io.async((
|
|
91
|
-
addrs := io.await(lookup_host(host,
|
|
85
|
+
resolve :: (fn(host : String, port : u16, io : IO) -> Impl(Future(ArrayList(SocketAddr), IOErr)))(
|
|
86
|
+
io.async((e) => {
|
|
87
|
+
addrs := e.io.await(lookup_host(host, io), e);
|
|
92
88
|
result := ArrayList(SocketAddr).new();
|
|
93
89
|
i := usize(0);
|
|
94
90
|
while(runtime(i < addrs.len()), {
|
package/std/net/errors.yo
CHANGED
|
@@ -84,7 +84,7 @@ impl(
|
|
|
84
84
|
NetError,
|
|
85
85
|
/// Check a raw syscall result and throw on error.
|
|
86
86
|
/// Positive values are returned as-is; negative values are converted to a `NetError` and thrown.
|
|
87
|
-
check : (fn(result : i32,
|
|
87
|
+
check : (fn(result : i32, exn : Exception) -> i32)(
|
|
88
88
|
cond(
|
|
89
89
|
(result >= i32(0)) => result,
|
|
90
90
|
true => exn.throw(dyn(Self.from_io(IOError.from_errno(i32(0) - result))))
|