@shd101wyy/yo 0.1.28 → 0.1.30

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 (183) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +15 -15
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +118 -121
  3. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +33 -13
  4. package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +1 -1
  5. package/.github/skills/yo-syntax/SKILL.md +2 -2
  6. package/.github/skills/yo-syntax/syntax-cheatsheet.md +108 -96
  7. package/README.md +6 -3
  8. package/out/cjs/index.cjs +812 -706
  9. package/out/cjs/yo-cli.cjs +1023 -907
  10. package/out/cjs/yo-lsp.cjs +836 -730
  11. package/out/esm/index.mjs +757 -651
  12. package/out/types/src/codegen/exprs/async.d.ts +2 -0
  13. package/out/types/src/codegen/exprs/await.d.ts +1 -0
  14. package/out/types/src/codegen/exprs/closures.d.ts +4 -0
  15. package/out/types/src/codegen/functions/context.d.ts +6 -0
  16. package/out/types/src/codegen/functions/declarations.d.ts +1 -1
  17. package/out/types/src/doc/model.d.ts +0 -1
  18. package/out/types/src/env.d.ts +2 -2
  19. package/out/types/src/evaluator/builtins/pragma.d.ts +9 -0
  20. package/out/types/src/evaluator/builtins/unsafe.d.ts +8 -0
  21. package/out/types/src/evaluator/context.d.ts +3 -1
  22. package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
  23. package/out/types/src/evaluator/index.d.ts +1 -1
  24. package/out/types/src/evaluator/memory-safety.d.ts +14 -0
  25. package/out/types/src/evaluator/types/flowability.d.ts +6 -0
  26. package/out/types/src/evaluator/types/function.d.ts +1 -2
  27. package/out/types/src/evaluator/utils.d.ts +0 -1
  28. package/out/types/src/expr-traversal.d.ts +1 -0
  29. package/out/types/src/expr.d.ts +9 -7
  30. package/out/types/src/public-safe-report.d.ts +19 -0
  31. package/out/types/src/tests/comptime-ref-gate.test.d.ts +1 -0
  32. package/out/types/src/tests/pragma-validation.test.d.ts +1 -0
  33. package/out/types/src/tests/public-safe-report.test.d.ts +1 -0
  34. package/out/types/src/tests/type-representation-pointer.test.d.ts +1 -0
  35. package/out/types/src/tests/unsafe-gate.test.d.ts +1 -0
  36. package/out/types/src/tests/unsafe-report-classify.test.d.ts +1 -0
  37. package/out/types/src/types/creators.d.ts +4 -6
  38. package/out/types/src/types/definitions.d.ts +9 -16
  39. package/out/types/src/types/guards.d.ts +1 -2
  40. package/out/types/src/types/tags.d.ts +0 -1
  41. package/out/types/src/types/utils.d.ts +5 -0
  42. package/out/types/src/unsafe-report.d.ts +29 -0
  43. package/out/types/src/value.d.ts +1 -0
  44. package/out/types/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +1 -1
  46. package/scripts/add-pragma-for-pointer-decls.ts +134 -0
  47. package/scripts/add-pragma.ts +58 -0
  48. package/scripts/migrate-amp-method-calls.ts +186 -0
  49. package/scripts/migrate-clone-calls.ts +93 -0
  50. package/scripts/migrate-get-unwrap.ts +166 -0
  51. package/scripts/migrate-index-patterns.ts +210 -0
  52. package/scripts/migrate-index-trait.ts +142 -0
  53. package/scripts/migrate-iterator.ts +150 -0
  54. package/scripts/migrate-self-ptr.ts +220 -0
  55. package/scripts/migrate-skip-pragmas.ts +109 -0
  56. package/scripts/migrate-tostring.ts +134 -0
  57. package/scripts/trim-pragma.ts +130 -0
  58. package/scripts/wrap-extern-calls.ts +161 -0
  59. package/std/alg/hash.yo +3 -2
  60. package/std/allocator.yo +6 -5
  61. package/std/async.yo +2 -2
  62. package/std/collections/array_list.yo +59 -40
  63. package/std/collections/btree_map.yo +19 -18
  64. package/std/collections/deque.yo +9 -8
  65. package/std/collections/hash_map.yo +101 -13
  66. package/std/collections/hash_set.yo +5 -4
  67. package/std/collections/linked_list.yo +39 -4
  68. package/std/collections/ordered_map.yo +3 -3
  69. package/std/collections/priority_queue.yo +14 -13
  70. package/std/crypto/md5.yo +2 -1
  71. package/std/crypto/random.yo +21 -20
  72. package/std/crypto/sha256.yo +2 -1
  73. package/std/encoding/base64.yo +18 -18
  74. package/std/encoding/hex.yo +5 -5
  75. package/std/encoding/json.yo +62 -13
  76. package/std/encoding/punycode.yo +24 -23
  77. package/std/encoding/toml.yo +4 -3
  78. package/std/encoding/utf16.yo +3 -3
  79. package/std/env.yo +43 -28
  80. package/std/error.yo +15 -3
  81. package/std/fmt/display.yo +2 -2
  82. package/std/fmt/index.yo +6 -5
  83. package/std/fmt/to_string.yo +39 -38
  84. package/std/fmt/writer.yo +9 -8
  85. package/std/fs/dir.yo +61 -66
  86. package/std/fs/file.yo +121 -126
  87. package/std/fs/metadata.yo +13 -18
  88. package/std/fs/temp.yo +35 -30
  89. package/std/fs/walker.yo +14 -19
  90. package/std/gc.yo +1 -0
  91. package/std/glob.yo +7 -7
  92. package/std/http/client.yo +33 -36
  93. package/std/http/http.yo +6 -6
  94. package/std/http/index.yo +4 -4
  95. package/std/imm/list.yo +33 -0
  96. package/std/imm/map.yo +2 -1
  97. package/std/imm/set.yo +1 -0
  98. package/std/imm/sorted_map.yo +1 -0
  99. package/std/imm/sorted_set.yo +1 -0
  100. package/std/imm/string.yo +27 -23
  101. package/std/imm/vec.yo +18 -2
  102. package/std/io/reader.yo +2 -1
  103. package/std/io/writer.yo +3 -2
  104. package/std/libc/assert.yo +1 -0
  105. package/std/libc/ctype.yo +1 -0
  106. package/std/libc/dirent.yo +1 -0
  107. package/std/libc/errno.yo +1 -0
  108. package/std/libc/fcntl.yo +1 -0
  109. package/std/libc/float.yo +1 -0
  110. package/std/libc/limits.yo +1 -0
  111. package/std/libc/math.yo +1 -0
  112. package/std/libc/signal.yo +1 -0
  113. package/std/libc/stdatomic.yo +1 -0
  114. package/std/libc/stdint.yo +1 -0
  115. package/std/libc/stdio.yo +1 -0
  116. package/std/libc/stdlib.yo +1 -0
  117. package/std/libc/string.yo +1 -0
  118. package/std/libc/sys/stat.yo +1 -0
  119. package/std/libc/time.yo +1 -0
  120. package/std/libc/unistd.yo +1 -0
  121. package/std/libc/wctype.yo +1 -0
  122. package/std/libc/windows.yo +2 -0
  123. package/std/log.yo +7 -6
  124. package/std/net/addr.yo +6 -5
  125. package/std/net/dns.yo +13 -16
  126. package/std/net/errors.yo +9 -9
  127. package/std/net/tcp.yo +71 -74
  128. package/std/net/udp.yo +40 -43
  129. package/std/os/signal.yo +5 -5
  130. package/std/path.yo +1 -0
  131. package/std/prelude.yo +377 -200
  132. package/std/process/command.yo +57 -46
  133. package/std/process/index.yo +2 -1
  134. package/std/regex/compiler.yo +10 -9
  135. package/std/regex/index.yo +41 -41
  136. package/std/regex/match.yo +2 -2
  137. package/std/regex/parser.yo +31 -31
  138. package/std/regex/vm.yo +42 -41
  139. package/std/string/string.yo +95 -40
  140. package/std/string/string_builder.yo +9 -9
  141. package/std/string/unicode.yo +50 -49
  142. package/std/sync/channel.yo +2 -1
  143. package/std/sync/cond.yo +5 -4
  144. package/std/sync/mutex.yo +4 -3
  145. package/std/sys/advise.yo +1 -0
  146. package/std/sys/bufio/buf_reader.yo +27 -26
  147. package/std/sys/bufio/buf_writer.yo +22 -21
  148. package/std/sys/clock.yo +1 -0
  149. package/std/sys/copy.yo +1 -0
  150. package/std/sys/dir.yo +10 -9
  151. package/std/sys/dns.yo +6 -5
  152. package/std/sys/errors.yo +12 -12
  153. package/std/sys/events.yo +1 -0
  154. package/std/sys/externs.yo +38 -37
  155. package/std/sys/file.yo +17 -16
  156. package/std/sys/future.yo +4 -3
  157. package/std/sys/iov.yo +1 -0
  158. package/std/sys/mmap.yo +1 -0
  159. package/std/sys/path.yo +1 -0
  160. package/std/sys/perm.yo +2 -1
  161. package/std/sys/pipe.yo +1 -0
  162. package/std/sys/process.yo +5 -4
  163. package/std/sys/signal.yo +1 -0
  164. package/std/sys/socketpair.yo +1 -0
  165. package/std/sys/sockinfo.yo +1 -0
  166. package/std/sys/statfs.yo +2 -1
  167. package/std/sys/statx.yo +1 -0
  168. package/std/sys/sysinfo.yo +1 -0
  169. package/std/sys/tcp.yo +15 -14
  170. package/std/sys/temp.yo +1 -0
  171. package/std/sys/time.yo +2 -1
  172. package/std/sys/timer.yo +6 -6
  173. package/std/sys/tty.yo +2 -1
  174. package/std/sys/udp.yo +13 -12
  175. package/std/sys/unix.yo +12 -11
  176. package/std/testing/bench.yo +4 -3
  177. package/std/thread.yo +7 -6
  178. package/std/time/datetime.yo +18 -15
  179. package/std/time/duration.yo +11 -10
  180. package/std/time/instant.yo +4 -4
  181. package/std/time/sleep.yo +1 -0
  182. package/std/url/index.yo +5 -5
  183. package/std/worker.yo +4 -3
package/std/fs/file.yo CHANGED
@@ -8,32 +8,27 @@
8
8
  //! ```rust
9
9
  //! { File, read_string, write_file, OpenMode } :: import "std/fs/file";
10
10
  //!
11
- //! main :: (fn(using(io : IO)) -> unit)({
12
- //! given(exn) := Exception(
13
- //! throw : (fn(forall(T : Type), error: AnyError) -> T)(
14
- //! { println(error); panic("Exception found."); }
15
- //! )
16
- //! );
17
- //!
11
+ //! main :: (fn(io : Io, exn : Exception) -> unit)({
18
12
  //! // Write a file
19
- //! io.await(write_file(Path.new(`test.txt`), `hello world`));
13
+ //! io.await(write_file(Path.new(`test.txt`), `hello world`, io), { io, exn });
20
14
  //!
21
15
  //! // Read it back
22
- //! content := io.await(read_string(Path.new(`test.txt`)));
16
+ //! content := io.await(read_string(Path.new(`test.txt`), io), { io, exn });
23
17
  //! println(content);
24
18
  //!
25
19
  //! // Open with OpenMode
26
- //! f := io.await(File.open(Path.new(`test.txt`), .Read));
20
+ //! f := io.await(File.open(Path.new(`test.txt`), .Read, io), { io, exn });
27
21
  //! });
28
22
  //! ```
23
+ pragma(Pragma.AllowUnsafe);
29
24
  { GlobalAllocator } :: import("../allocator");
30
25
  { malloc, free } :: GlobalAllocator;
31
26
  { ArrayList } :: import("../collections/array_list");
32
27
  open(import("../string"));
33
28
  open(import("../fmt"));
34
29
  { Path } :: import("../path");
35
- { IOError } :: import("../sys/errors");
36
- { Error, AnyError, Exception } :: import("../error");
30
+ { IoError } :: import("../sys/errors");
31
+ { Error, AnyError, Exception, IoExn } :: import("../error");
37
32
  { Metadata } :: import("./metadata");
38
33
  _metadata_mod :: import("./metadata");
39
34
  { Statx } :: import("../sys/statx");
@@ -57,18 +52,18 @@ File :: object(
57
52
  impl(
58
53
  File,
59
54
  /// Open a file at `path` with the given mode and custom permissions.
60
- open_with : (fn(path : Path, mode : OpenMode, perm : FilePermission, using(io : IO)) -> Impl(Future(File, IO, Exception)))({
55
+ open_with : (fn(path : Path, mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))({
61
56
  flags := _open_mode_to_flags(mode);
62
57
  file_mode := cond(
63
58
  _open_mode_needs_perm(mode) => i32(perm.mode),
64
59
  true => i32(0)
65
60
  );
66
- io.async((using(io, exn)) => {
61
+ io.async((e) => {
67
62
  path_str := path.to_string();
68
63
  cstr_bytes := path_str.to_cstr();
69
64
  cstr := cstr_bytes.ptr().unwrap();
70
- result := io.await(IO_file.openat(AT_FDCWD, cstr, flags, file_mode));
71
- fd := IOError.check(result);
65
+ result := e.io.await(IO_file.openat(AT_FDCWD, cstr, flags, file_mode), e.io);
66
+ fd := IoError.check(result, e.exn);
72
67
  File(
73
68
  _fd : fd,
74
69
  _path : path,
@@ -77,78 +72,78 @@ impl(
77
72
  })
78
73
  }),
79
74
  /// Open a file from a `str` path with the given mode and custom permissions.
80
- open_with_str : (fn(path : str, mode : OpenMode, perm : FilePermission, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
81
- File.open_with(Path.new(String.from(path)), mode, perm)
75
+ open_with_str : (fn(path : str, mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))(
76
+ File.open_with(Path.new(String.from(path)), mode, perm, io)
82
77
  ),
83
78
  /// Open a file from a C string path with the given mode and custom permissions.
84
- open_with_cstr : (fn(path : *(u8), mode : OpenMode, perm : FilePermission, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
85
- File.open_with(Path.from_cstr(path), mode, perm)
79
+ open_with_cstr : (fn(path : *(u8), mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))(
80
+ File.open_with(Path.from_cstr(path), mode, perm, io)
86
81
  ),
87
82
  /// Open a file at `path` with the given mode and default permissions (0o644).
88
- open : (fn(path : Path, mode : OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
89
- File.open_with(path, mode, FilePermission.default())
83
+ open : (fn(path : Path, mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
84
+ File.open_with(path, mode, FilePermission.default(), io)
90
85
  ),
91
86
  /// Open a file from a `str` path with the given mode and default permissions.
92
- open_str : (fn(path : str, mode : OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
93
- File.open(Path.new(String.from(path)), mode)
87
+ open_str : (fn(path : str, mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
88
+ File.open(Path.new(String.from(path)), mode, io)
94
89
  ),
95
90
  /// Open a file from a C string path with the given mode and default permissions.
96
- open_cstr : (fn(path : *(u8), mode : OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
97
- File.open(Path.from_cstr(path), mode)
91
+ open_cstr : (fn(path : *(u8), mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
92
+ File.open(Path.from_cstr(path), mode, io)
98
93
  ),
99
94
  /// Read up to `size` bytes into the buffer `buf`.
100
95
  /// Returns the number of bytes actually read.
101
- read : (fn(self : Self, buf : *(u8), size : u32, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
96
+ read : (fn(self : Self, buf : *(u8), size : u32, io : Io) -> Impl(Future(i32, IoExn)))({
102
97
  fd := self._fd;
103
- io.async((using(io, exn)) => {
104
- result := io.await(IO_file.read(fd, buf, size, u64(0)));
105
- IOError.check(result)
98
+ io.async((e) => {
99
+ result := e.io.await(IO_file.read(fd, buf, size, u64(0)), e.io);
100
+ IoError.check(result, e.exn)
106
101
  })
107
102
  }),
108
103
  /// Write a `String` to the file.
109
104
  /// Returns the number of bytes written.
110
- write_string : (fn(self : Self, data : String, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
105
+ write_string : (fn(self : Self, data : String, io : Io) -> Impl(Future(i32, IoExn)))({
111
106
  fd := self._fd;
112
- io.async((using(io, exn)) => {
107
+ io.async((e) => {
113
108
  data_bytes := data.as_bytes();
114
109
  cond(
115
110
  (data_bytes.len() == usize(0)) => i32(0),
116
111
  true => {
117
- result := io.await(IO_file.write(fd, data_bytes.ptr().unwrap(), u32(data_bytes.len()), u64(0)));
118
- IOError.check(result)
112
+ result := e.io.await(IO_file.write(fd, data_bytes.ptr().unwrap(), u32(data_bytes.len()), u64(0)), e.io);
113
+ IoError.check(result, e.exn)
119
114
  }
120
115
  )
121
116
  })
122
117
  }),
123
118
  /// Write bytes from an `ArrayList(u8)` to the file.
124
119
  /// Returns the number of bytes written.
125
- write_bytes : (fn(self : Self, data : ArrayList(u8), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
120
+ write_bytes : (fn(self : Self, data : ArrayList(u8), io : Io) -> Impl(Future(i32, IoExn)))({
126
121
  fd := self._fd;
127
122
  io.async(
128
- (using(io, exn)) =>
123
+ (e) =>
129
124
  cond(
130
125
  (data.len() == usize(0)) => i32(0),
131
126
  true => {
132
- result := io.await(IO_file.write(fd, data.ptr().unwrap(), u32(data.len()), u64(0)));
133
- IOError.check(result)
127
+ result := e.io.await(IO_file.write(fd, data.ptr().unwrap(), u32(data.len()), u64(0)), e.io);
128
+ IoError.check(result, e.exn)
134
129
  }
135
130
  )
136
131
  )
137
132
  }),
138
133
  /// Read the entire file contents into an `ArrayList(u8)`.
139
- read_bytes : (fn(self : Self, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))({
134
+ read_bytes : (fn(self : Self, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))({
140
135
  fd := self._fd;
141
- io.async((using(io, exn)) => {
136
+ io.async((e) => {
142
137
  buf_size := usize(4096);
143
138
  buf := *(u8)(malloc(buf_size).unwrap());
144
139
  result := ArrayList(u8).new();
145
140
  offset := u64(0);
146
141
  while(runtime(true), {
147
- n := io.await(IO_file.read(fd, buf, u32(buf_size), offset));
142
+ n := e.io.await(IO_file.read(fd, buf, u32(buf_size), offset), e.io);
148
143
  cond(
149
144
  (n < i32(0)) => {
150
145
  free(.Some(*(void)(buf)));
151
- exn.throw(dyn(IOError.from_errno(i32(0) - n)));
146
+ e.exn.throw(dyn(IoError.from_errno(i32(0) - n)));
152
147
  },
153
148
  (n == i32(0)) => break,
154
149
  true => {
@@ -166,28 +161,28 @@ impl(
166
161
  })
167
162
  }),
168
163
  /// Read the entire file contents into a `String`.
169
- read_string : (fn(self : Self, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
170
- io.async((using(io, exn)) => {
171
- bytes := io.await(self.read_bytes());
164
+ read_string : (fn(self : Self, io : Io) -> Impl(Future(String, IoExn)))(
165
+ io.async((e) => {
166
+ bytes := e.io.await(self.read_bytes(io), e);
172
167
  String.from_bytes(bytes)
173
168
  })
174
169
  ),
175
170
  /// Flush (fsync) file data to disk.
176
- flush : (fn(self : Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
171
+ flush : (fn(self : Self, io : Io) -> Impl(Future(unit, IoExn)))({
177
172
  fd := self._fd;
178
- io.async((using(io, exn)) => {
179
- result := io.await(IO_file.fsync(fd));
173
+ io.async((e) => {
174
+ result := e.io.await(IO_file.fsync(fd), e.io);
180
175
  cond(
181
- (result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
176
+ (result < i32(0)) => e.exn.throw(dyn(IoError.from_errno(i32(0) - result))),
182
177
  true => ()
183
178
  )
184
179
  })
185
180
  }),
186
181
  /// Seek to a position relative to `from`. Returns the new absolute byte offset.
187
- seek : (fn(self : Self, offset : i64, from : SeekFrom, using(exn : Exception)) -> i64)({
182
+ seek : (fn(self : Self, offset : i64, from : SeekFrom, exn : Exception) -> i64)({
188
183
  result := IO_seek.lseek(self._fd, offset, _seek_from_to_whence(from));
189
184
  cond(
190
- (result < i64(0)) => exn.throw(dyn(IOError.from_errno(i32(i64(0) - result)))),
185
+ (result < i64(0)) => exn.throw(dyn(IoError.from_errno(i32(i64(0) - result)))),
191
186
  true => result
192
187
  )
193
188
  }),
@@ -200,17 +195,17 @@ impl(
200
195
  IO_file.file_size(self._fd)
201
196
  ),
202
197
  /// Close the file descriptor. Safe to call multiple times.
203
- close : (fn(self : Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
198
+ close : (fn(self : Self, io : Io) -> Impl(Future(unit, IoExn)))({
204
199
  fd := self._fd;
205
200
  io.async(
206
- (using(io, exn)) =>
201
+ (e) =>
207
202
  cond(
208
203
  self._is_closed => (),
209
204
  true => {
210
- result := io.await(IO_file.close(fd));
205
+ result := e.io.await(IO_file.close(fd), e.io);
211
206
  self._is_closed = true;
212
207
  cond(
213
- (result < i32(0)) => exn.throw(dyn(IOError.from_errno(i32(0) - result))),
208
+ (result < i32(0)) => e.exn.throw(dyn(IoError.from_errno(i32(0) - result))),
214
209
  true => ()
215
210
  )
216
211
  }
@@ -226,8 +221,8 @@ impl(
226
221
  self._path
227
222
  ),
228
223
  /// Get file metadata (size, permissions, timestamps).
229
- metadata : (fn(self : Self, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(
230
- _metadata_mod.metadata(self._path)
224
+ metadata : (fn(self : Self, io : Io) -> Impl(Future(Metadata, IoExn)))(
225
+ _metadata_mod.metadata(self._path, io)
231
226
  )
232
227
  );
233
228
  impl(
@@ -249,74 +244,74 @@ export(File, OpenMode, FilePermission, SeekFrom);
249
244
  // Convenience functions
250
245
  // ============================================================================
251
246
  /// Read an entire file into a `String`.
252
- read_string :: (fn(path : Path, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
253
- io.async((using(io, exn)) => {
254
- file := io.await(File.open(path,.Read));
255
- content := io.await(file.read_string());
256
- io.await(file.close());
247
+ read_string :: (fn(path : Path, io : Io) -> Impl(Future(String, IoExn)))(
248
+ io.async((e) => {
249
+ file := e.io.await(File.open(path,.Read, io), e);
250
+ content := e.io.await(file.read_string(io), e);
251
+ e.io.await(file.close(io), e);
257
252
  return(content);
258
253
  })
259
254
  );
260
255
  /// Read an entire file into a `String` (`str` path variant).
261
- read_string_str :: (fn(path : str, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
262
- read_string(Path.new(String.from(path)))
256
+ read_string_str :: (fn(path : str, io : Io) -> Impl(Future(String, IoExn)))(
257
+ read_string(Path.new(String.from(path)), io)
263
258
  );
264
259
  /// Read an entire file into a `String` (C string path variant).
265
- read_string_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(String, IO, Exception)))(
266
- read_string(Path.from_cstr(path))
260
+ read_string_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(String, IoExn)))(
261
+ read_string(Path.from_cstr(path), io)
267
262
  );
268
263
  /// Read an entire file into a byte list (`ArrayList(u8)`).
269
- read_file :: (fn(path : Path, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
270
- io.async((using(io, exn)) => {
271
- file := io.await(File.open(path,.Read));
272
- content := io.await(file.read_bytes());
273
- io.await(file.close());
264
+ read_file :: (fn(path : Path, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
265
+ io.async((e) => {
266
+ file := e.io.await(File.open(path,.Read, io), e);
267
+ content := e.io.await(file.read_bytes(io), e);
268
+ e.io.await(file.close(io), e);
274
269
  return(content);
275
270
  })
276
271
  );
277
272
  /// Read an entire file into bytes (`str` path variant).
278
- read_file_str :: (fn(path : str, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
279
- read_file(Path.new(String.from(path)))
273
+ read_file_str :: (fn(path : str, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
274
+ read_file(Path.new(String.from(path)), io)
280
275
  );
281
276
  /// Read an entire file into bytes (C string path variant).
282
- read_file_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
283
- read_file(Path.from_cstr(path))
277
+ read_file_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
278
+ read_file(Path.from_cstr(path), io)
284
279
  );
285
280
  /// Write a `String` to a file, creating or truncating it.
286
- write_file :: (fn(path : Path, data : String, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
287
- io.async((using(io, exn)) => {
288
- file := io.await(File.open(path,.Write));
289
- io.await(file.write_string(data));
290
- io.await(file.close());
281
+ write_file :: (fn(path : Path, data : String, io : Io) -> Impl(Future(unit, IoExn)))(
282
+ io.async((e) => {
283
+ file := e.io.await(File.open(path,.Write, io), e);
284
+ e.io.await(file.write_string(data, io), e);
285
+ e.io.await(file.close(io), e);
291
286
  })
292
287
  );
293
288
  /// Write a `str` to a file, creating or truncating it (`str` path variant).
294
- write_file_str :: (fn(path : str, data : str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
295
- write_file(Path.new(String.from(path)), String.from(data))
289
+ write_file_str :: (fn(path : str, data : str, io : Io) -> Impl(Future(unit, IoExn)))(
290
+ write_file(Path.new(String.from(path)), String.from(data), io)
296
291
  );
297
292
  /// Write a `str` to a file, creating or truncating it (C string path variant).
298
- write_file_cstr :: (fn(path : *(u8), data : str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
299
- write_file(Path.from_cstr(path), String.from(data))
293
+ write_file_cstr :: (fn(path : *(u8), data : str, io : Io) -> Impl(Future(unit, IoExn)))(
294
+ write_file(Path.from_cstr(path), String.from(data), io)
300
295
  );
301
296
  /// Write bytes to a file, creating or truncating it.
302
- write_bytes :: (fn(path : Path, data : ArrayList(u8), using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
303
- io.async((using(io, exn)) => {
304
- file := io.await(File.open(path,.Write));
305
- io.await(file.write_bytes(data));
306
- io.await(file.close());
297
+ write_bytes :: (fn(path : Path, data : ArrayList(u8), io : Io) -> Impl(Future(unit, IoExn)))(
298
+ io.async((e) => {
299
+ file := e.io.await(File.open(path,.Write, io), e);
300
+ e.io.await(file.write_bytes(data, io), e);
301
+ e.io.await(file.close(io), e);
307
302
  })
308
303
  );
309
304
  /// Append a `String` to a file, creating it if it does not exist.
310
- append_file :: (fn(path : Path, data : String, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
311
- io.async((using(io, exn)) => {
312
- file := io.await(File.open(path,.Append));
313
- io.await(file.write_string(data));
314
- io.await(file.close());
305
+ append_file :: (fn(path : Path, data : String, io : Io) -> Impl(Future(unit, IoExn)))(
306
+ io.async((e) => {
307
+ file := e.io.await(File.open(path,.Append, io), e);
308
+ e.io.await(file.write_string(data, io), e);
309
+ e.io.await(file.close(io), e);
315
310
  })
316
311
  );
317
312
  /// Append a `str` to a file (`str` path variant).
318
- append_file_str :: (fn(path : str, data : str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
319
- append_file(Path.new(String.from(path)), String.from(data))
313
+ append_file_str :: (fn(path : str, data : str, io : Io) -> Impl(Future(unit, IoExn)))(
314
+ append_file(Path.new(String.from(path)), String.from(data), io)
320
315
  );
321
316
  extern(
322
317
  "Yo",
@@ -324,34 +319,34 @@ extern(
324
319
  );
325
320
  /// Check if a path exists. Returns `false` for any error including file not found.
326
321
  /// Does not use the `Exception` effect.
327
- exists :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
328
- io.async((using(io : IO)) => {
322
+ exists :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
323
+ io.async((io) => {
329
324
  cstr_bytes := path.to_string().to_cstr();
330
325
  cstr := cstr_bytes.ptr().unwrap();
331
326
  buf_size := __yo_statx_buf_size();
332
327
  buf := *(u8)(malloc(buf_size).unwrap());
333
- result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
328
+ result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
334
329
  free(.Some(*(void)(buf)));
335
330
  result >= i32(0)
336
331
  })
337
332
  );
338
333
  /// Check if a path exists (`str` path variant).
339
- exists_str :: (fn(path : str, using(io : IO)) -> Impl(Future(bool, IO)))(
340
- exists(Path.new(String.from(path)), using(io))
334
+ exists_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
335
+ exists(Path.new(String.from(path)), io)
341
336
  );
342
337
  /// Check if a path exists (C string path variant).
343
- exists_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(bool, IO)))(
344
- exists(Path.from_cstr(path), using(io))
338
+ exists_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
339
+ exists(Path.from_cstr(path), io)
345
340
  );
346
341
  /// Check if a path is a regular file. Returns `false` for any error.
347
- is_file :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
348
- io.async((using(io : IO)) => {
342
+ is_file :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
343
+ io.async((io) => {
349
344
  path_str := path.to_string();
350
345
  cstr_bytes := path_str.to_cstr();
351
346
  cstr := cstr_bytes.ptr().unwrap();
352
347
  buf_size := __yo_statx_buf_size();
353
348
  buf := *(u8)(malloc(buf_size).unwrap());
354
- result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
349
+ result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
355
350
  r := cond(
356
351
  (result < i32(0)) => false,
357
352
  true => {
@@ -364,22 +359,22 @@ is_file :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
364
359
  })
365
360
  );
366
361
  /// Check if a path is a regular file (`str` path variant).
367
- is_file_str :: (fn(path : str, using(io : IO)) -> Impl(Future(bool, IO)))(
368
- is_file(Path.new(String.from(path)), using(io))
362
+ is_file_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
363
+ is_file(Path.new(String.from(path)), io)
369
364
  );
370
365
  /// Check if a path is a regular file (C string path variant).
371
- is_file_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(bool, IO)))(
372
- is_file(Path.from_cstr(path), using(io))
366
+ is_file_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
367
+ is_file(Path.from_cstr(path), io)
373
368
  );
374
369
  /// Check if a path is a directory. Returns `false` for any error.
375
- is_dir :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
376
- io.async((using(io : IO)) => {
370
+ is_dir :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
371
+ io.async((io) => {
377
372
  path_str := path.to_string();
378
373
  cstr_bytes := path_str.to_cstr();
379
374
  cstr := cstr_bytes.ptr().unwrap();
380
375
  buf_size := __yo_statx_buf_size();
381
376
  buf := *(u8)(malloc(buf_size).unwrap());
382
- result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
377
+ result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
383
378
  r := cond(
384
379
  (result < i32(0)) => false,
385
380
  true => {
@@ -392,33 +387,33 @@ is_dir :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
392
387
  })
393
388
  );
394
389
  /// Check if a path is a directory (`str` path variant).
395
- is_dir_str :: (fn(path : str, using(io : IO)) -> Impl(Future(bool, IO)))(
396
- is_dir(Path.new(String.from(path)), using(io))
390
+ is_dir_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
391
+ is_dir(Path.new(String.from(path)), io)
397
392
  );
398
393
  /// Check if a path is a directory (C string path variant).
399
- is_dir_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(bool, IO)))(
400
- is_dir(Path.from_cstr(path), using(io))
394
+ is_dir_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
395
+ is_dir(Path.from_cstr(path), io)
401
396
  );
402
397
  /// Resolve a path to its canonical absolute form (resolves symlinks, `.` and `..`).
403
398
  /// Throws if the path does not exist.
404
- canonical :: (fn(path : Path, using(io : IO)) -> Impl(Future(Path, IO, Exception)))(
405
- io.async((using(io, exn)) => {
399
+ canonical :: (fn(path : Path, io : Io) -> Impl(Future(Path, IoExn)))(
400
+ io.async((e) => {
406
401
  path_str := path.to_string();
407
402
  cstr_bytes := path_str.to_cstr();
408
403
  cstr := cstr_bytes.ptr().unwrap();
409
404
  // Async stat to verify path exists (provides await point for proper RC cleanup)
410
405
  buf_size := __yo_statx_buf_size();
411
406
  stat_buf := *(u8)(malloc(buf_size).unwrap());
412
- stat_result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, stat_buf));
407
+ stat_result := e.io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, stat_buf), e.io);
413
408
  free(.Some(*(void)(stat_buf)));
414
- IOError.check(stat_result);
409
+ IoError.check(stat_result, e.exn);
415
410
  // Resolve the canonical path
416
411
  resolved_buf := *(u8)(malloc(usize(4096)).unwrap());
417
412
  rp_result := IO_path.realpath(cstr, resolved_buf);
418
413
  cond(
419
414
  (rp_result < i32(0)) => {
420
415
  free(.Some(*(void)(resolved_buf)));
421
- IOError.check(rp_result);
416
+ IoError.check(rp_result, e.exn);
422
417
  },
423
418
  true => ()
424
419
  );
@@ -428,12 +423,12 @@ canonical :: (fn(path : Path, using(io : IO)) -> Impl(Future(Path, IO, Exception
428
423
  })
429
424
  );
430
425
  /// Resolve a path to its canonical absolute form (`str` path variant).
431
- canonical_str :: (fn(path : str, using(io : IO)) -> Impl(Future(Path, IO, Exception)))(
432
- canonical(Path.new(String.from(path)))
426
+ canonical_str :: (fn(path : str, io : Io) -> Impl(Future(Path, IoExn)))(
427
+ canonical(Path.new(String.from(path)), io)
433
428
  );
434
429
  /// Resolve a path to its canonical absolute form (C string path variant).
435
- canonical_cstr :: (fn(path : *(u8), using(io : IO)) -> Impl(Future(Path, IO, Exception)))(
436
- canonical(Path.from_cstr(path))
430
+ canonical_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(Path, IoExn)))(
431
+ canonical(Path.from_cstr(path), io)
437
432
  );
438
433
  export(
439
434
  read_string,
@@ -6,24 +6,19 @@
6
6
  //! ```rust
7
7
  //! { metadata } :: import "std/fs/metadata";
8
8
  //!
9
- //! main :: (fn(using(io : IO)) -> unit)({
10
- //! given(exn) : Exception = {
11
- //! throw : (fn(forall(T : Type), error: AnyError) -> T)(
12
- //! { println(error.to_string()); exit(i32(1)); }
13
- //! )
14
- //! };
15
- //!
16
- //! m := io.await(metadata(Path.new(`/tmp/test.txt`)));
9
+ //! main :: (fn(io : Io, exn : Exception) -> unit)({
10
+ //! m := io.await(metadata(Path.new(`/tmp/test.txt`), io), { io, exn });
17
11
  //! printf("size: %lld\n", m.size());
18
12
  //! printf("is file: %d\n", i32(m.is_file()));
19
13
  //! });
20
14
  //! ```
15
+ pragma(Pragma.AllowUnsafe);
21
16
  { GlobalAllocator } :: import("../allocator");
22
17
  { malloc, free } :: GlobalAllocator;
23
18
  open(import("../string"));
24
19
  { Path } :: import("../path");
25
- { IOError } :: import("../sys/errors");
26
- { Error, AnyError, Exception } :: import("../error");
20
+ { IoError } :: import("../sys/errors");
21
+ { Error, AnyError, Exception, IoExn } :: import("../error");
27
22
  { Statx } :: import("../sys/statx");
28
23
  IO_file :: import("../sys/file");
29
24
  { AT_FDCWD, AT_SYMLINK_NOFOLLOW, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK, S_IWUSR, S_IWGRP, S_IWOTH } :: import("../sys/constants");
@@ -107,17 +102,17 @@ extern(
107
102
  // ============================================================================
108
103
  // Internal helper to stat a path
109
104
  // ============================================================================
110
- _stat_path :: (fn(path : Path, flags : i32, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(
111
- io.async((using(io, exn)) => {
105
+ _stat_path :: (fn(path : Path, flags : i32, io : Io) -> Impl(Future(Metadata, IoExn)))(
106
+ io.async((e) => {
112
107
  cstr_bytes := path.to_string().to_cstr();
113
108
  cstr := cstr_bytes.ptr().unwrap();
114
109
  buf_size := __yo_statx_buf_size();
115
110
  buf := *(u8)(malloc(buf_size).unwrap());
116
- result := io.await(IO_file.statx(AT_FDCWD, cstr, flags, STATX_BASIC_STATS, buf));
111
+ result := e.io.await(IO_file.statx(AT_FDCWD, cstr, flags, STATX_BASIC_STATS, buf), e.io);
117
112
  cond(
118
113
  (result < i32(0)) => {
119
114
  free(.Some(*(void)(buf)));
120
- exn.throw(dyn(IOError.from_errno(i32(0) - result)))
115
+ e.exn.throw(dyn(IoError.from_errno(i32(0) - result)))
121
116
  },
122
117
  true => {
123
118
  sx := Statx(_buf_ptr : buf, _buf_size : buf_size);
@@ -127,11 +122,11 @@ _stat_path :: (fn(path : Path, flags : i32, using(io : IO)) -> Impl(Future(Metad
127
122
  })
128
123
  );
129
124
  /// Get metadata for a path (follows symlinks).
130
- metadata :: (fn(path : Path, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(_stat_path(path, AT_STATX_SYNC_AS_STAT));
125
+ metadata :: (fn(path : Path, io : Io) -> Impl(Future(Metadata, IoExn)))(_stat_path(path, AT_STATX_SYNC_AS_STAT, io));
131
126
  /// Get metadata for a path given as a raw string (follows symlinks).
132
- metadata_str :: (fn(path : str, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(metadata(Path.new(String.from(path))));
127
+ metadata_str :: (fn(path : str, io : Io) -> Impl(Future(Metadata, IoExn)))(metadata(Path.new(String.from(path)), io));
133
128
  /// Get metadata for a path (does NOT follow symlinks).
134
- symlink_metadata :: (fn(path : Path, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(_stat_path(path, AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT));
129
+ symlink_metadata :: (fn(path : Path, io : Io) -> Impl(Future(Metadata, IoExn)))(_stat_path(path, AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT, io));
135
130
  /// Get metadata for a path given as a raw string (does NOT follow symlinks).
136
- symlink_metadata_str :: (fn(path : str, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(symlink_metadata(Path.new(String.from(path))));
131
+ symlink_metadata_str :: (fn(path : str, io : Io) -> Impl(Future(Metadata, IoExn)))(symlink_metadata(Path.new(String.from(path)), io));
137
132
  export(metadata, metadata_str, symlink_metadata, symlink_metadata_str);