@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/package.json
CHANGED
package/std/async.yo
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//! Async utilities for cooperative task scheduling.
|
|
2
2
|
/// Suspend the current async task, allowing other tasks to run on the event loop.
|
|
3
3
|
/// Implemented as an immediately-completing async block that forces a suspension point.
|
|
4
|
-
yield :: (fn(
|
|
4
|
+
yield :: (fn(io : IO) -> Impl(Future(unit)))(
|
|
5
5
|
io.async(() => {
|
|
6
6
|
return(());
|
|
7
7
|
})
|
package/std/crypto/random.yo
CHANGED
|
@@ -54,7 +54,7 @@ extern(
|
|
|
54
54
|
// ============================================================================
|
|
55
55
|
// Fill a buffer with cryptographically secure random bytes.
|
|
56
56
|
// ============================================================================
|
|
57
|
-
random_bytes :: (fn(buf : *(u8), size : usize,
|
|
57
|
+
random_bytes :: (fn(buf : *(u8), size : usize, exn : Exception) -> unit)(
|
|
58
58
|
cond(
|
|
59
59
|
(platform == Platform.Macos) => {
|
|
60
60
|
__yo_arc4random_buf(buf, size);
|
|
@@ -104,7 +104,7 @@ export(random_bytes);
|
|
|
104
104
|
// ============================================================================
|
|
105
105
|
// Typed helpers
|
|
106
106
|
// ============================================================================
|
|
107
|
-
random_u32 :: (fn(
|
|
107
|
+
random_u32 :: (fn(exn : Exception) -> u32)({
|
|
108
108
|
buf := Array(u8, usize(4)).fill(u8(0));
|
|
109
109
|
buf_ptr := &(buf(usize(0)));
|
|
110
110
|
random_bytes(buf_ptr, usize(4));
|
|
@@ -113,16 +113,16 @@ random_u32 :: (fn(using(exn : Exception)) -> u32)({
|
|
|
113
113
|
(u32(buf(usize(2))) << u32(16)) |
|
|
114
114
|
(u32(buf(usize(3))) << u32(24))
|
|
115
115
|
});
|
|
116
|
-
random_u64 :: (fn(
|
|
116
|
+
random_u64 :: (fn(exn : Exception) -> u64)({
|
|
117
117
|
lo := u64(random_u32());
|
|
118
118
|
hi := u64(random_u32());
|
|
119
119
|
lo | (hi << u64(32))
|
|
120
120
|
});
|
|
121
|
-
random_f64 :: (fn(
|
|
121
|
+
random_f64 :: (fn(exn : Exception) -> f64)(
|
|
122
122
|
f64(random_u64()) / f64(18446744073709551615.0)
|
|
123
123
|
);
|
|
124
124
|
// Return a random integer in the half-open range [min, max).
|
|
125
|
-
random_range :: (fn(min : i64, max : i64,
|
|
125
|
+
random_range :: (fn(min : i64, max : i64, exn : Exception) -> i64)({
|
|
126
126
|
span := (max - min);
|
|
127
127
|
cond(
|
|
128
128
|
(span <= i64(0)) => min,
|
|
@@ -137,7 +137,7 @@ export(random_u32, random_u64, random_f64, random_range);
|
|
|
137
137
|
// UUID v4
|
|
138
138
|
// ============================================================================
|
|
139
139
|
// Generate a random UUID v4 string: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
|
140
|
-
uuid_v4 :: (fn(
|
|
140
|
+
uuid_v4 :: (fn(exn : Exception) -> String)({
|
|
141
141
|
bytes := ArrayList(u8).with_capacity(usize(16));
|
|
142
142
|
buf := Array(u8, usize(16)).fill(u8(0));
|
|
143
143
|
buf_ptr := &(buf(usize(0)));
|
package/std/encoding/base64.yo
CHANGED
|
@@ -64,7 +64,7 @@ export(base64_encode, base64_encode_url);
|
|
|
64
64
|
// ============================================================================
|
|
65
65
|
// Decoding
|
|
66
66
|
// ============================================================================
|
|
67
|
-
_decode_char :: (fn(c : u8, alpha : str,
|
|
67
|
+
_decode_char :: (fn(c : u8, alpha : str, exn : Exception) -> u8)({
|
|
68
68
|
i := usize(0);
|
|
69
69
|
while(i < usize(64), i = (i + usize(1)), {
|
|
70
70
|
cond(
|
|
@@ -76,7 +76,7 @@ _decode_char :: (fn(c : u8, alpha : str, using(exn : Exception)) -> u8)({
|
|
|
76
76
|
});
|
|
77
77
|
exn.throw(dyn(EncodingError.InvalidChar(c)))
|
|
78
78
|
});
|
|
79
|
-
_decode_with :: (fn(s : str, alpha : str,
|
|
79
|
+
_decode_with :: (fn(s : str, alpha : str, exn : Exception) -> ArrayList(u8))({
|
|
80
80
|
// Strip trailing padding
|
|
81
81
|
len := s.len();
|
|
82
82
|
while((len > usize(0)) && (s.bytes(len - usize(1)) == _PAD), len = (len - usize(1)), ());
|
|
@@ -107,11 +107,11 @@ _decode_with :: (fn(s : str, alpha : str, using(exn : Exception)) -> ArrayList(u
|
|
|
107
107
|
out
|
|
108
108
|
});
|
|
109
109
|
/// Decode a standard base64 string to bytes. Throws via `Exception` on invalid input.
|
|
110
|
-
base64_decode :: (fn(s : str,
|
|
110
|
+
base64_decode :: (fn(s : str, exn : Exception) -> ArrayList(u8))(
|
|
111
111
|
_decode_with(s, _STD_ALPHA)
|
|
112
112
|
);
|
|
113
113
|
/// Decode a URL-safe base64 string to bytes. Throws via `Exception` on invalid input.
|
|
114
|
-
base64_decode_url :: (fn(s : str,
|
|
114
|
+
base64_decode_url :: (fn(s : str, exn : Exception) -> ArrayList(u8))(
|
|
115
115
|
_decode_with(s, _URL_ALPHA)
|
|
116
116
|
);
|
|
117
117
|
export(base64_decode, base64_decode_url);
|
package/std/encoding/hex.yo
CHANGED
|
@@ -64,7 +64,7 @@ export(hex_encode);
|
|
|
64
64
|
// ============================================================================
|
|
65
65
|
// Decoding
|
|
66
66
|
// ============================================================================
|
|
67
|
-
_hex_nibble :: (fn(c : u8,
|
|
67
|
+
_hex_nibble :: (fn(c : u8, exn : Exception) -> u8)(
|
|
68
68
|
cond(
|
|
69
69
|
((c >= u8(48)) && (c <= u8(57))) => (c - u8(48)),
|
|
70
70
|
// '0'-'9'
|
|
@@ -76,7 +76,7 @@ _hex_nibble :: (fn(c : u8, using(exn : Exception)) -> u8)(
|
|
|
76
76
|
)
|
|
77
77
|
);
|
|
78
78
|
/// Decode a hexadecimal string to bytes. Throws via `Exception` on invalid input.
|
|
79
|
-
hex_decode :: (fn(s : str,
|
|
79
|
+
hex_decode :: (fn(s : str, exn : Exception) -> ArrayList(u8))({
|
|
80
80
|
cond(
|
|
81
81
|
((s.len() % usize(2)) != usize(0)) => {
|
|
82
82
|
exn.throw(dyn(EncodingError.OddLength));
|
package/std/encoding/json.yo
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
//! { json_parse, json_stringify, JsonValue } :: import "std/encoding/json";
|
|
9
9
|
//! { Exception } :: import "std/error";
|
|
10
10
|
//!
|
|
11
|
-
//!
|
|
11
|
+
//! exn := Exception(throw : ((err) -> { unwind (); }));
|
|
12
12
|
//! v := json_parse(`{"x": 1}`);
|
|
13
13
|
//! println(json_stringify(v));
|
|
14
14
|
//! ```
|
|
@@ -30,7 +30,7 @@ JsonError :: enum(
|
|
|
30
30
|
InvalidNumber,
|
|
31
31
|
/// Invalid escape sequence in a string.
|
|
32
32
|
InvalidEscape,
|
|
33
|
-
/// Invalid Unicode
|
|
33
|
+
/// Invalid Unicode unwind in a string.
|
|
34
34
|
InvalidUnicode,
|
|
35
35
|
/// Other error with a descriptive message.
|
|
36
36
|
Other(msg : String)
|
|
@@ -553,7 +553,7 @@ _parse_value :: (fn(p : _Parser) -> Result(JsonValue, JsonError))({
|
|
|
553
553
|
// Public API
|
|
554
554
|
// ============================================================================
|
|
555
555
|
/// Parse a JSON string into a `JsonValue` tree. Throws via `Exception` on invalid input.
|
|
556
|
-
json_parse :: (fn(s : str,
|
|
556
|
+
json_parse :: (fn(s : str, exn : Exception) -> JsonValue)({
|
|
557
557
|
p := _Parser.new(s);
|
|
558
558
|
match(
|
|
559
559
|
_parse_value(p),
|
package/std/encoding/utf16.yo
CHANGED
|
@@ -68,7 +68,7 @@ export(utf8_to_utf16);
|
|
|
68
68
|
///
|
|
69
69
|
/// Decodes surrogate pairs back into supplementary code points.
|
|
70
70
|
/// Throws via `Exception` on unpaired surrogates.
|
|
71
|
-
utf16_to_utf8 :: (fn(data : ArrayList(u16),
|
|
71
|
+
utf16_to_utf8 :: (fn(data : ArrayList(u16), exn : Exception) -> String)({
|
|
72
72
|
out := ArrayList(u8).new();
|
|
73
73
|
i := usize(0);
|
|
74
74
|
while(i < data.len(), {
|
package/std/error.yo
CHANGED
|
@@ -15,15 +15,27 @@ export(AnyError);
|
|
|
15
15
|
impl(String, Error());
|
|
16
16
|
/// Non-resumable exception handling effect record.
|
|
17
17
|
/// Use `throw` to raise an `AnyError` and abort the current computation.
|
|
18
|
+
/// `throw` is `ctl(...)` — handler body may contain `unwind`, and the
|
|
19
|
+
/// handler value is frame-bound (see plans/EXPLICIT_EFFECTS.md §4).
|
|
18
20
|
Exception :: struct(
|
|
19
|
-
throw : (
|
|
21
|
+
throw : (ctl(forall(ResumeType : Type), error : AnyError) -> ResumeType)
|
|
20
22
|
);
|
|
21
23
|
export(Exception);
|
|
22
24
|
/// Creates a resumable exception effect record parameterized by the resume type.
|
|
23
25
|
/// Unlike `Exception`, the handler can return a value to resume the computation.
|
|
26
|
+
/// `throw` is still `ctl(...)` because the handler MAY choose to unwind;
|
|
27
|
+
/// regular `fn` returns are also valid via subtyping `fn <: ctl`.
|
|
24
28
|
ResumableException :: (fn(comptime(ResumeType) : Type) -> comptime(Type))(
|
|
25
29
|
struct(
|
|
26
|
-
throw : (
|
|
30
|
+
throw : (ctl(error : AnyError) -> ResumeType)
|
|
27
31
|
)
|
|
28
32
|
);
|
|
29
33
|
export(ResumableException);
|
|
34
|
+
/// Common effect bundle: IO + Exception.
|
|
35
|
+
/// Used as the effect parameter for Futures that perform IO and may throw.
|
|
36
|
+
/// Construct with `{ io, exn }`; project with `e.io` or `e.exn`.
|
|
37
|
+
IOErr :: struct(
|
|
38
|
+
io : IO,
|
|
39
|
+
exn : Exception
|
|
40
|
+
);
|
|
41
|
+
export(IOErr);
|
package/std/fs/dir.yo
CHANGED
|
@@ -8,16 +8,10 @@
|
|
|
8
8
|
//! { create_dir, remove_dir, read_dir } :: import "std/fs/dir";
|
|
9
9
|
//! { Path } :: import "std/path";
|
|
10
10
|
//!
|
|
11
|
-
//! main :: (fn(
|
|
12
|
-
//!
|
|
13
|
-
//!
|
|
14
|
-
//!
|
|
15
|
-
//! )
|
|
16
|
-
//! };
|
|
17
|
-
//!
|
|
18
|
-
//! io.await(create_dir(Path.new(`/tmp/yo_test`)));
|
|
19
|
-
//! entries := io.await(read_dir(Path.new(`/tmp/yo_test`)));
|
|
20
|
-
//! io.await(remove_dir(Path.new(`/tmp/yo_test`)));
|
|
11
|
+
//! main :: (fn(io : IO, exn : Exception) -> unit)({
|
|
12
|
+
//! io.await(create_dir(Path.new(`/tmp/yo_test`), io), { io, exn });
|
|
13
|
+
//! entries := io.await(read_dir(Path.new(`/tmp/yo_test`), io), { io, exn });
|
|
14
|
+
//! io.await(remove_dir(Path.new(`/tmp/yo_test`), io), { io, exn });
|
|
21
15
|
//! });
|
|
22
16
|
//! ```
|
|
23
17
|
{ GlobalAllocator } :: import("../allocator");
|
|
@@ -26,7 +20,7 @@
|
|
|
26
20
|
open(import("../string"));
|
|
27
21
|
{ Path } :: import("../path");
|
|
28
22
|
{ IOError } :: import("../sys/errors");
|
|
29
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
23
|
+
{ Error, AnyError, Exception, IOErr } :: import("../error");
|
|
30
24
|
{ EEXIST, ENOENT } :: import("../libc/errno");
|
|
31
25
|
IO_dir :: import("../sys/dir");
|
|
32
26
|
IO_file :: import("../sys/file");
|
|
@@ -61,30 +55,30 @@ export(DirEntry);
|
|
|
61
55
|
// Directory operations
|
|
62
56
|
// ============================================================================
|
|
63
57
|
/// Create a directory at the given path.
|
|
64
|
-
create_dir :: (fn(path : Path,
|
|
65
|
-
io.async((
|
|
58
|
+
create_dir :: (fn(path : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
59
|
+
io.async((e) => {
|
|
66
60
|
cstr_bytes := path.to_string().to_cstr();
|
|
67
61
|
cstr := cstr_bytes.ptr().unwrap();
|
|
68
|
-
result := io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)));
|
|
62
|
+
result := e.io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)), e.io);
|
|
69
63
|
cond(
|
|
70
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
64
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
71
65
|
true => ()
|
|
72
66
|
)
|
|
73
67
|
})
|
|
74
68
|
);
|
|
75
69
|
/// Create a directory (`str` path variant).
|
|
76
|
-
create_dir_str :: (fn(path : str,
|
|
77
|
-
create_dir(Path.new(String.from(path)))
|
|
70
|
+
create_dir_str :: (fn(path : str, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
71
|
+
create_dir(Path.new(String.from(path)), io)
|
|
78
72
|
);
|
|
79
73
|
/// Create a directory and all missing parent directories.
|
|
80
74
|
/// Does not error if the directory already exists.
|
|
81
|
-
create_dir_all :: (fn(path : Path,
|
|
82
|
-
io.async((
|
|
75
|
+
create_dir_all :: (fn(path : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
76
|
+
io.async((e) => {
|
|
83
77
|
path_s := path.to_string();
|
|
84
78
|
cstr_bytes := path_s.to_cstr();
|
|
85
79
|
cstr := cstr_bytes.ptr().unwrap();
|
|
86
80
|
// Try creating the directory directly first
|
|
87
|
-
result := io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)));
|
|
81
|
+
result := e.io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)), e.io);
|
|
88
82
|
cond(
|
|
89
83
|
(result >= i32(0)) => (),
|
|
90
84
|
true => {
|
|
@@ -126,11 +120,11 @@ create_dir_all :: (fn(path : Path, using(io : IO)) -> Impl(Future(unit, IO, Exce
|
|
|
126
120
|
prefix := path_s.substring(usize(0), i);
|
|
127
121
|
prefix_cstr_bytes := prefix.to_cstr();
|
|
128
122
|
prefix_cstr := prefix_cstr_bytes.ptr().unwrap();
|
|
129
|
-
r := io.await(IO_dir.mkdir(AT_FDCWD, prefix_cstr, i32(DEFAULT_DIR_MODE)));
|
|
123
|
+
r := e.io.await(IO_dir.mkdir(AT_FDCWD, prefix_cstr, i32(DEFAULT_DIR_MODE)), e.io);
|
|
130
124
|
// Ignore EEXIST errors
|
|
131
125
|
cond(
|
|
132
126
|
((r < i32(0)) && ((i32(0) - r) != i32(EEXIST))) => {
|
|
133
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - r)));
|
|
127
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - r)));
|
|
134
128
|
},
|
|
135
129
|
true => ()
|
|
136
130
|
);
|
|
@@ -140,114 +134,114 @@ create_dir_all :: (fn(path : Path, using(io : IO)) -> Impl(Future(unit, IO, Exce
|
|
|
140
134
|
i = (i + usize(1));
|
|
141
135
|
});
|
|
142
136
|
// Create the final directory
|
|
143
|
-
final_result := io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)));
|
|
137
|
+
final_result := e.io.await(IO_dir.mkdir(AT_FDCWD, cstr, i32(DEFAULT_DIR_MODE)), e.io);
|
|
144
138
|
cond(
|
|
145
139
|
(final_result >= i32(0)) => (),
|
|
146
140
|
true => {
|
|
147
141
|
final_errno := (i32(0) - final_result);
|
|
148
142
|
cond(
|
|
149
143
|
(final_errno == i32(EEXIST)) => (),
|
|
150
|
-
true => exn.throw(dyn(IOError.from_errno(final_errno)))
|
|
144
|
+
true => e.exn.throw(dyn(IOError.from_errno(final_errno)))
|
|
151
145
|
)
|
|
152
146
|
}
|
|
153
147
|
)
|
|
154
148
|
},
|
|
155
|
-
true => exn.throw(dyn(IOError.from_errno(errno)))
|
|
149
|
+
true => e.exn.throw(dyn(IOError.from_errno(errno)))
|
|
156
150
|
)
|
|
157
151
|
}
|
|
158
152
|
)
|
|
159
153
|
})
|
|
160
154
|
);
|
|
161
155
|
/// Create a directory and all missing parents (`str` path variant).
|
|
162
|
-
create_dir_all_str :: (fn(path : str,
|
|
163
|
-
create_dir_all(Path.new(String.from(path)))
|
|
156
|
+
create_dir_all_str :: (fn(path : str, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
157
|
+
create_dir_all(Path.new(String.from(path)), io)
|
|
164
158
|
);
|
|
165
159
|
/// Remove an empty directory. Throws if the directory is not empty.
|
|
166
|
-
remove_dir :: (fn(path : Path,
|
|
167
|
-
io.async((
|
|
160
|
+
remove_dir :: (fn(path : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
161
|
+
io.async((e) => {
|
|
168
162
|
cstr_bytes := path.to_string().to_cstr();
|
|
169
163
|
cstr := cstr_bytes.ptr().unwrap();
|
|
170
|
-
result := io.await(IO_dir.unlink(AT_FDCWD, cstr, AT_REMOVEDIR));
|
|
164
|
+
result := e.io.await(IO_dir.unlink(AT_FDCWD, cstr, AT_REMOVEDIR), e.io);
|
|
171
165
|
cond(
|
|
172
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
166
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
173
167
|
true => ()
|
|
174
168
|
)
|
|
175
169
|
})
|
|
176
170
|
);
|
|
177
|
-
remove_dir_str :: (fn(path : str,
|
|
178
|
-
remove_dir(Path.new(String.from(path)))
|
|
171
|
+
remove_dir_str :: (fn(path : str, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
172
|
+
remove_dir(Path.new(String.from(path)), io)
|
|
179
173
|
);
|
|
180
174
|
/// Remove a file at the given path.
|
|
181
|
-
remove_file :: (fn(path : Path,
|
|
182
|
-
io.async((
|
|
175
|
+
remove_file :: (fn(path : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
176
|
+
io.async((e) => {
|
|
183
177
|
cstr_bytes := path.to_string().to_cstr();
|
|
184
178
|
cstr := cstr_bytes.ptr().unwrap();
|
|
185
|
-
result := io.await(IO_dir.unlink(AT_FDCWD, cstr, i32(0)));
|
|
179
|
+
result := e.io.await(IO_dir.unlink(AT_FDCWD, cstr, i32(0)), e.io);
|
|
186
180
|
cond(
|
|
187
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
181
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
188
182
|
true => ()
|
|
189
183
|
)
|
|
190
184
|
})
|
|
191
185
|
);
|
|
192
|
-
remove_file_str :: (fn(path : str,
|
|
186
|
+
remove_file_str :: (fn(path : str, io : IO) -> Impl(Future(unit, IOErr)))(remove_file(Path.new(String.from(path)), io));
|
|
193
187
|
/// Rename or move a file or directory from `from` to `to`.
|
|
194
|
-
rename :: (fn(from : Path, to : Path,
|
|
195
|
-
io.async((
|
|
188
|
+
rename :: (fn(from : Path, to : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
189
|
+
io.async((e) => {
|
|
196
190
|
from_cstr_bytes := from.to_string().to_cstr();
|
|
197
191
|
from_cstr := from_cstr_bytes.ptr().unwrap();
|
|
198
192
|
to_cstr_bytes := to.to_string().to_cstr();
|
|
199
193
|
to_cstr := to_cstr_bytes.ptr().unwrap();
|
|
200
|
-
result := io.await(IO_dir.rename(AT_FDCWD, from_cstr, AT_FDCWD, to_cstr));
|
|
194
|
+
result := e.io.await(IO_dir.rename(AT_FDCWD, from_cstr, AT_FDCWD, to_cstr), e.io);
|
|
201
195
|
cond(
|
|
202
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
196
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
203
197
|
true => ()
|
|
204
198
|
)
|
|
205
199
|
})
|
|
206
200
|
);
|
|
207
|
-
rename_str :: (fn(from : str, to : str,
|
|
201
|
+
rename_str :: (fn(from : str, to : str, io : IO) -> Impl(Future(unit, IOErr)))(rename(Path.new(String.from(from)), Path.new(String.from(to)), io));
|
|
208
202
|
/// Create a hard link from `src` to `dst`.
|
|
209
|
-
hard_link :: (fn(src : Path, dst : Path,
|
|
210
|
-
io.async((
|
|
203
|
+
hard_link :: (fn(src : Path, dst : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
204
|
+
io.async((e) => {
|
|
211
205
|
src_cstr_bytes := src.to_string().to_cstr();
|
|
212
206
|
src_cstr := src_cstr_bytes.ptr().unwrap();
|
|
213
207
|
dst_cstr_bytes := dst.to_string().to_cstr();
|
|
214
208
|
dst_cstr := dst_cstr_bytes.ptr().unwrap();
|
|
215
|
-
result := io.await(IO_dir.link(AT_FDCWD, src_cstr, AT_FDCWD, dst_cstr, i32(0)));
|
|
209
|
+
result := e.io.await(IO_dir.link(AT_FDCWD, src_cstr, AT_FDCWD, dst_cstr, i32(0)), e.io);
|
|
216
210
|
cond(
|
|
217
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
211
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
218
212
|
true => ()
|
|
219
213
|
)
|
|
220
214
|
})
|
|
221
215
|
);
|
|
222
|
-
hard_link_str :: (fn(src : str, dst : str,
|
|
216
|
+
hard_link_str :: (fn(src : str, dst : str, io : IO) -> Impl(Future(unit, IOErr)))(hard_link(Path.new(String.from(src)), Path.new(String.from(dst)), io));
|
|
223
217
|
/// Create a symbolic link at `dst` pointing to `src`.
|
|
224
|
-
symlink :: (fn(src : Path, dst : Path,
|
|
225
|
-
io.async((
|
|
218
|
+
symlink :: (fn(src : Path, dst : Path, io : IO) -> Impl(Future(unit, IOErr)))(
|
|
219
|
+
io.async((e) => {
|
|
226
220
|
src_cstr_bytes := src.to_string().to_cstr();
|
|
227
221
|
src_cstr := src_cstr_bytes.ptr().unwrap();
|
|
228
222
|
dst_cstr_bytes := dst.to_string().to_cstr();
|
|
229
223
|
dst_cstr := dst_cstr_bytes.ptr().unwrap();
|
|
230
|
-
result := io.await(IO_dir.symlink(src_cstr, AT_FDCWD, dst_cstr));
|
|
224
|
+
result := e.io.await(IO_dir.symlink(src_cstr, AT_FDCWD, dst_cstr), e.io);
|
|
231
225
|
cond(
|
|
232
|
-
(result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
226
|
+
(result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - result))),
|
|
233
227
|
true => ()
|
|
234
228
|
)
|
|
235
229
|
})
|
|
236
230
|
);
|
|
237
|
-
symlink_str :: (fn(src : str, dst : str,
|
|
231
|
+
symlink_str :: (fn(src : str, dst : str, io : IO) -> Impl(Future(unit, IOErr)))(symlink(Path.new(String.from(src)), Path.new(String.from(dst)), io));
|
|
238
232
|
// ============================================================================
|
|
239
233
|
// Directory listing
|
|
240
234
|
// ============================================================================
|
|
241
235
|
/// Read all entries from a directory, returning an `ArrayList(DirEntry)`.
|
|
242
236
|
/// Skips the `.` and `..` entries.
|
|
243
|
-
read_dir :: (fn(path : Path,
|
|
244
|
-
io.async((
|
|
237
|
+
read_dir :: (fn(path : Path, io : IO) -> Impl(Future(ArrayList(DirEntry), IOErr)))(
|
|
238
|
+
io.async((e) => {
|
|
245
239
|
cstr_bytes := path.to_string().to_cstr();
|
|
246
240
|
cstr := cstr_bytes.ptr().unwrap();
|
|
247
241
|
// Open the directory
|
|
248
|
-
fd_result := io.await(IO_file.openat(AT_FDCWD, cstr, O_RDONLY | O_DIRECTORY, i32(0)));
|
|
242
|
+
fd_result := e.io.await(IO_file.openat(AT_FDCWD, cstr, O_RDONLY | O_DIRECTORY, i32(0)), e.io);
|
|
249
243
|
cond(
|
|
250
|
-
(fd_result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - fd_result))),
|
|
244
|
+
(fd_result < i32(0)) => e.exn.throw(dyn(IOError.from_errno(i32(0) - fd_result))),
|
|
251
245
|
true => ()
|
|
252
246
|
);
|
|
253
247
|
fd := fd_result;
|
|
@@ -255,12 +249,12 @@ read_dir :: (fn(path : Path, using(io : IO)) -> Impl(Future(ArrayList(DirEntry),
|
|
|
255
249
|
buf_size := u32(4096);
|
|
256
250
|
buf := *(u8)(malloc(usize(buf_size)).unwrap());
|
|
257
251
|
while(runtime(true), {
|
|
258
|
-
n := io.await(IO_dir.getdents(fd, buf, buf_size));
|
|
252
|
+
n := e.io.await(IO_dir.getdents(fd, buf, buf_size), e.io);
|
|
259
253
|
cond(
|
|
260
254
|
(n < i32(0)) => {
|
|
261
255
|
free(.Some(*(void)(buf)));
|
|
262
|
-
io.await(IO_file.close(fd));
|
|
263
|
-
exn.throw(dyn(IOError.from_errno(i32(0) - n)));
|
|
256
|
+
e.io.await(IO_file.close(fd), e.io);
|
|
257
|
+
e.exn.throw(dyn(IOError.from_errno(i32(0) - n)));
|
|
264
258
|
},
|
|
265
259
|
(n == i32(0)) => {
|
|
266
260
|
break;
|
|
@@ -297,11 +291,11 @@ read_dir :: (fn(path : Path, using(io : IO)) -> Impl(Future(ArrayList(DirEntry),
|
|
|
297
291
|
);
|
|
298
292
|
});
|
|
299
293
|
free(.Some(*(void)(buf)));
|
|
300
|
-
io.await(IO_file.close(fd));
|
|
294
|
+
e.io.await(IO_file.close(fd), e.io);
|
|
301
295
|
entries
|
|
302
296
|
})
|
|
303
297
|
);
|
|
304
|
-
read_dir_str :: (fn(path : str,
|
|
298
|
+
read_dir_str :: (fn(path : str, io : IO) -> Impl(Future(ArrayList(DirEntry), IOErr)))(read_dir(Path.new(String.from(path)), io));
|
|
305
299
|
export(
|
|
306
300
|
create_dir,
|
|
307
301
|
create_dir_str,
|