@shd101wyy/yo 0.0.26 → 0.0.28

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 (63) hide show
  1. package/README.md +7 -6
  2. package/out/cjs/index.cjs +568 -563
  3. package/out/cjs/yo-cli.cjs +686 -556
  4. package/out/esm/index.mjs +509 -504
  5. package/out/types/src/build-runner.d.ts +22 -0
  6. package/out/types/src/cache.d.ts +3 -0
  7. package/out/types/src/codegen/async/state-machine.d.ts +1 -1
  8. package/out/types/src/codegen/codegen-c.d.ts +3 -0
  9. package/out/types/src/codegen/exprs/await.d.ts +1 -0
  10. package/out/types/src/codegen/exprs/return.d.ts +1 -0
  11. package/out/types/src/codegen/exprs/while.d.ts +1 -1
  12. package/out/types/src/codegen/functions/context.d.ts +6 -18
  13. package/out/types/src/codegen/functions/declarations.d.ts +10 -2
  14. package/out/types/src/codegen/index.d.ts +4 -0
  15. package/out/types/src/codegen/utils/index.d.ts +3 -0
  16. package/out/types/src/evaluator/async/await-analysis.d.ts +1 -0
  17. package/out/types/src/evaluator/builtins/build.d.ts +135 -0
  18. package/out/types/src/evaluator/context.d.ts +1 -0
  19. package/out/types/src/expr.d.ts +18 -0
  20. package/out/types/src/fetch-command.d.ts +6 -0
  21. package/out/types/src/fetch.d.ts +10 -0
  22. package/out/types/src/function-value.d.ts +1 -0
  23. package/out/types/src/init.d.ts +5 -0
  24. package/out/types/src/install-command.d.ts +6 -0
  25. package/out/types/src/lock-file.d.ts +16 -0
  26. package/out/types/src/module-manager.d.ts +3 -1
  27. package/out/types/src/pkg-config.d.ts +11 -0
  28. package/out/types/src/target.d.ts +28 -0
  29. package/out/types/src/tests/build-system.test.d.ts +1 -0
  30. package/out/types/src/types/creators.d.ts +2 -1
  31. package/out/types/src/types/definitions.d.ts +2 -1
  32. package/out/types/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +1 -1
  34. package/std/build.yo +287 -0
  35. package/std/crypto/random.yo +27 -15
  36. package/std/encoding/base64.yo +24 -49
  37. package/std/encoding/hex.yo +25 -22
  38. package/std/encoding/json.yo +25 -3
  39. package/std/encoding/utf16.yo +6 -5
  40. package/std/fs/dir.yo +107 -104
  41. package/std/fs/file.yo +122 -158
  42. package/std/fs/metadata.yo +23 -22
  43. package/std/fs/temp.yo +42 -48
  44. package/std/fs/walker.yo +48 -55
  45. package/std/net/addr.yo +8 -7
  46. package/std/net/dns.yo +27 -33
  47. package/std/net/errors.yo +13 -8
  48. package/std/net/tcp.yo +92 -113
  49. package/std/net/udp.yo +50 -54
  50. package/std/os/env.yo +5 -5
  51. package/std/os/signal.yo +21 -16
  52. package/std/path.yo +2 -2
  53. package/std/prelude.yo +23 -2
  54. package/std/process.yo +23 -43
  55. package/std/sys/clock.yo +1 -1
  56. package/std/sys/constants.yo +3 -3
  57. package/std/sys/errors.yo +45 -33
  58. package/std/sys/mmap.yo +2 -2
  59. package/std/sys/signals.yo +4 -4
  60. package/std/sys/socket.yo +25 -25
  61. package/std/sys/sysinfo.yo +4 -4
  62. package/std/url/url.yo +19 -32
  63. package/out/types/src/codegen/effects/effect-state-machine.d.ts +0 -34
package/std/fs/file.yo CHANGED
@@ -1,20 +1,24 @@
1
1
  // std/fs/file.yo - High-level file object
2
2
  //
3
3
  // Wraps a file descriptor with typed async I/O operations.
4
+ // Uses Exception effect for error handling.
4
5
  //
5
6
  // Example:
6
- // { File, read_to_string, write_file, OpenMode } :: import "std/fs/file";
7
+ // { File, read_string, write_file, OpenMode } :: import "std/fs/file";
7
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); panic("Exception found."); }
13
+ // )
14
+ // );
15
+ //
9
16
  // // Write a file
10
17
  // io.await(write_file(Path.new(`test.txt`), `hello world`));
11
18
  //
12
19
  // // Read it back
13
- // content := io.await(read_to_string(Path.new(`test.txt`)));
14
- // match(content,
15
- // .Ok(s) => println(s),
16
- // .Err(e) => println(e.to_string())
17
- // );
20
+ // content := io.await(read_string(Path.new(`test.txt`)));
21
+ // println(content);
18
22
  //
19
23
  // // Open with OpenMode
20
24
  // f := io.await(File.open(Path.new(`test.txt`), .Read));
@@ -27,13 +31,15 @@ open import "../string";
27
31
  open import "../fmt";
28
32
  { Path } :: import "../path";
29
33
  { IOError } :: import "../sys/errors";
34
+ { Error, AnyError, Exception } :: import "../error";
30
35
  { Metadata } :: import "./metadata";
31
36
  _metadata_mod :: import "./metadata";
32
37
  { OpenMode, FilePermission, _open_mode_to_flags, _open_mode_needs_perm } :: import "./types";
33
38
  IO_file :: import "../sys/file";
34
39
  IO_seek :: import "../sys/seek";
35
40
  {
36
- AT_FDCWD, O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_APPEND,
41
+ AT_FDCWD, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS,
42
+ O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_APPEND,
37
43
  O_CLOEXEC, DEFAULT_FILE_MODE
38
44
  } :: import "../sys/constants";
39
45
 
@@ -49,74 +55,72 @@ File :: object(
49
55
 
50
56
  impl(File,
51
57
  // Open a file with OpenMode and custom permissions.
52
- open_with : (fn(path: Path, mode: OpenMode, perm: FilePermission, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))({
58
+ open_with : (fn(path: Path, mode: OpenMode, perm: FilePermission, using(io : IO)) -> Impl(Future(File, IO, Exception)))({
53
59
  flags := _open_mode_to_flags(mode);
54
60
  file_mode := cond(
55
61
  _open_mode_needs_perm(mode) => i32(perm.mode),
56
62
  true => i32(0)
57
63
  );
58
- io.async((using(io : IO)) => {
64
+ io.async((using(io, exn)) => {
59
65
  path_str := path.to_string();
60
66
  cstr_bytes := path_str.to_cstr();
61
67
  cstr := cstr_bytes.ptr().unwrap();
62
68
  result := io.await(IO_file.openat(AT_FDCWD, cstr, flags, file_mode));
63
- cond(
64
- (result < i32(0)) => .Err(IOError.from_errno((i32(0) - result))),
65
- true => .Ok(File(
66
- _fd: result,
67
- _path: path,
68
- _is_closed: false
69
- ))
69
+ fd := IOError.check(result);
70
+ File(
71
+ _fd: fd,
72
+ _path: path,
73
+ _is_closed: false
70
74
  )
71
75
  })
72
76
  }),
73
77
 
74
78
  // Open a file from a str path with OpenMode and custom permissions.
75
- open_with_str : (fn(path: str, mode: OpenMode, perm: FilePermission, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))(
76
- File.open_with(Path.new(String.from(path)), mode, perm, using(io))
79
+ open_with_str : (fn(path: str, mode: OpenMode, perm: FilePermission, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
80
+ File.open_with(Path.new(String.from(path)), mode, perm)
77
81
  ),
78
82
 
79
83
  // Open a file from a C string path with OpenMode and custom permissions.
80
- open_with_cstr : (fn(path: *(u8), mode: OpenMode, perm: FilePermission, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))(
81
- File.open_with(Path.from_cstr(path), mode, perm, using(io))
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)
82
86
  ),
83
87
 
84
88
  // Open a file with OpenMode and default permissions.
85
- open : (fn(path: Path, mode: OpenMode, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))(
86
- File.open_with(path, mode, FilePermission.default(), using(io))
89
+ open : (fn(path: Path, mode: OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
90
+ File.open_with(path, mode, FilePermission.default())
87
91
  ),
88
92
 
89
93
  // Open a file from a str path with OpenMode and default permissions.
90
- open_str : (fn(path: str, mode: OpenMode, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))(
91
- File.open(Path.new(String.from(path)), mode, using(io))
94
+ open_str : (fn(path: str, mode: OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
95
+ File.open(Path.new(String.from(path)), mode)
92
96
  ),
93
97
 
94
98
  // Open a file from a C string path with OpenMode and default permissions.
95
- open_cstr : (fn(path: *(u8), mode: OpenMode, using(io : IO)) -> Impl(Future(Result(File, IOError), IO)))(
96
- File.open(Path.from_cstr(path), mode, using(io))
99
+ open_cstr : (fn(path: *(u8), mode: OpenMode, using(io : IO)) -> Impl(Future(File, IO, Exception)))(
100
+ File.open(Path.from_cstr(path), mode)
97
101
  ),
98
102
 
99
103
  // Read up to `size` bytes into buffer.
100
104
  // Returns number of bytes read.
101
- read : (fn(self: Self, buf: *(u8), size: u32, using(io : IO)) -> Impl(Future(Result(i32, IOError), IO)))({
105
+ read : (fn(self: Self, buf: *(u8), size: u32, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
102
106
  fd := self._fd;
103
- io.async((using(io : IO)) => {
107
+ io.async((using(io, exn)) => {
104
108
  result := io.await(IO_file.read(fd, buf, size, u64(0)));
105
- IOError.from_result(result)
109
+ IOError.check(result)
106
110
  })
107
111
  }),
108
112
 
109
113
  // Write a String to the file.
110
114
  // Returns number of bytes written.
111
- write : (fn(self: Self, data: String, using(io : IO)) -> Impl(Future(Result(i32, IOError), IO)))({
115
+ write_string : (fn(self: Self, data: String, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
112
116
  fd := self._fd;
113
- io.async((using(io : IO)) => {
117
+ io.async((using(io, exn)) => {
114
118
  data_bytes := data.as_bytes();
115
119
  cond(
116
- (data_bytes.len() == usize(0)) => .Ok(i32(0)),
120
+ (data_bytes.len() == usize(0)) => i32(0),
117
121
  true => {
118
122
  result := io.await(IO_file.write(fd, data_bytes.ptr().unwrap(), u32(data_bytes.len()), u64(0)));
119
- IOError.from_result(result)
123
+ IOError.check(result)
120
124
  }
121
125
  )
122
126
  })
@@ -124,34 +128,33 @@ impl(File,
124
128
 
125
129
  // Write bytes from an ArrayList to the file.
126
130
  // Returns number of bytes written.
127
- write_bytes : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(Result(i32, IOError), IO)))({
131
+ write_bytes : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
128
132
  fd := self._fd;
129
- io.async((using(io : IO)) =>
133
+ io.async((using(io, exn)) =>
130
134
  cond(
131
- (data.len() == usize(0)) => .Ok(i32(0)),
135
+ (data.len() == usize(0)) => i32(0),
132
136
  true => {
133
137
  result := io.await(IO_file.write(fd, data.ptr().unwrap(), u32(data.len()), u64(0)));
134
- IOError.from_result(result)
138
+ IOError.check(result)
135
139
  }
136
140
  )
137
141
  )
138
142
  }),
139
143
 
140
144
  // Read the entire file into a byte list.
141
- read_all : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(ArrayList(u8), IOError), IO)))({
145
+ read_bytes : (fn(self: Self, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))({
142
146
  fd := self._fd;
143
- io.async((using(io : IO)) => {
147
+ io.async((using(io, exn)) => {
144
148
  buf_size := usize(4096);
145
149
  buf := *(u8)(malloc(buf_size).unwrap());
146
150
  result := ArrayList(u8).new();
147
151
  offset := u64(0);
148
- (read_err : Option(IOError)) = .None;
149
152
  while runtime(true), {
150
153
  n := io.await(IO_file.read(fd, buf, u32(buf_size), offset));
151
154
  cond(
152
155
  (n < i32(0)) => {
153
- read_err = .Some(IOError.from_errno((i32(0) - n)));
154
- break;
156
+ free(.Some(*(void)(buf)));
157
+ exn.throw(dyn IOError.from_errno((i32(0) - n)));
155
158
  },
156
159
  (n == i32(0)) => break,
157
160
  true => {
@@ -165,43 +168,37 @@ impl(File,
165
168
  );
166
169
  };
167
170
  free(.Some(*(void)(buf)));
168
- match(read_err,
169
- .Some(e) => .Err(e),
170
- .None => .Ok(result)
171
- )
171
+ result
172
172
  })
173
173
  }),
174
174
 
175
175
  // Read the entire file into a String.
176
- read_to_string : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(String, IOError), IO)))(
177
- io.async((using(io : IO)) => {
178
- bytes_result := io.await(self.read_all(using(io)));
179
- match(bytes_result,
180
- .Ok(bytes) => .Ok(String.from_bytes(bytes)),
181
- .Err(e) => .Err(e)
182
- )
176
+ read_string : (fn(self: Self, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
177
+ io.async((using(io, exn)) => {
178
+ bytes := io.await(self.read_bytes());
179
+ String.from_bytes(bytes)
183
180
  })
184
181
  ),
185
182
 
186
183
  // Sync file data to disk.
187
- flush : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))({
184
+ flush : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
188
185
  fd := self._fd;
189
- io.async((using(io : IO)) => {
186
+ io.async((using(io, exn)) => {
190
187
  result := io.await(IO_file.fsync(fd));
191
188
  cond(
192
- (result < i32(0)) => .Err(IOError.from_errno((i32(0) - result))),
193
- true => .Ok(())
189
+ (result < i32(0)) => exn.throw(dyn IOError.from_errno((i32(0) - result))),
190
+ true => ()
194
191
  )
195
192
  })
196
193
  }),
197
194
 
198
195
  // Seek to a position. Returns the new absolute position.
199
196
  // whence: SEEK_SET(0), SEEK_CUR(1), SEEK_END(2)
200
- seek : (fn(self: Self, offset: i64, whence: i32) -> Result(i64, IOError))({
197
+ seek : (fn(self: Self, offset: i64, whence: i32, using(exn : Exception)) -> i64)({
201
198
  result := IO_seek.lseek(self._fd, offset, whence);
202
199
  cond(
203
- (result < i64(0)) => .Err(IOError.from_errno(i32((i64(0) - result)))),
204
- true => .Ok(result)
200
+ (result < i64(0)) => exn.throw(dyn IOError.from_errno(i32((i64(0) - result)))),
201
+ true => result
205
202
  )
206
203
  }),
207
204
 
@@ -216,17 +213,17 @@ impl(File,
216
213
  ),
217
214
 
218
215
  // Close the file.
219
- close : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))({
216
+ close : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
220
217
  fd := self._fd;
221
- io.async((using(io : IO)) =>
218
+ io.async((using(io, exn)) =>
222
219
  cond(
223
- self._is_closed => .Ok(()),
220
+ self._is_closed => (),
224
221
  true => {
225
222
  result := io.await(IO_file.close(fd));
226
223
  self._is_closed = true;
227
224
  cond(
228
- (result < i32(0)) => .Err(IOError.from_errno((i32(0) - result))),
229
- true => .Ok(())
225
+ (result < i32(0)) => exn.throw(dyn IOError.from_errno((i32(0) - result))),
226
+ true => ()
230
227
  )
231
228
  }
232
229
  )
@@ -244,8 +241,8 @@ impl(File,
244
241
  ),
245
242
 
246
243
  // Get file metadata.
247
- metadata : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))(
248
- _metadata_mod.metadata(self._path, using(io))
244
+ metadata : (fn(self: Self, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(
245
+ _metadata_mod.metadata(self._path)
249
246
  )
250
247
  );
251
248
 
@@ -268,150 +265,117 @@ export File, OpenMode, FilePermission;
268
265
  // ============================================================================
269
266
 
270
267
  // Read an entire file into a String (Path version).
271
- read_to_string :: (fn(path: Path, using(io : IO)) -> Impl(Future(Result(String, IOError), IO)))(
272
- io.async((using(io : IO)) => {
273
- file_result := io.await(File.open(path, .Read, using(io)));
274
- match(file_result,
275
- .Ok(file) => {
276
- content := io.await(file.read_to_string(using(io)));
277
- io.await(file.close(using(io)));
278
- return content;
279
- },
280
- .Err(e) => .Err(e)
281
- )
268
+ read_string :: (fn(path: Path, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
269
+ io.async((using(io, exn)) => {
270
+ file := io.await(File.open(path, .Read));
271
+ content := io.await(file.read_string());
272
+ io.await(file.close());
273
+ return content;
282
274
  })
283
275
  );
284
276
 
285
277
  // Read an entire file into a String (str version).
286
- read_to_string_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Result(String, IOError), IO)))(
287
- read_to_string(Path.new(String.from(path)), using(io))
278
+ read_string_str :: (fn(path: str, using(io : IO)) -> Impl(Future(String, IO, Exception)))(
279
+ read_string(Path.new(String.from(path)))
288
280
  );
289
281
 
290
282
  // Read an entire file into a String (C string version).
291
- read_to_string_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(Result(String, IOError), IO)))(
292
- read_to_string(Path.from_cstr(path), using(io))
283
+ read_string_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(String, IO, Exception)))(
284
+ read_string(Path.from_cstr(path))
293
285
  );
294
286
 
295
287
  // Read an entire file into bytes (Path version).
296
- read_file :: (fn(path: Path, using(io : IO)) -> Impl(Future(Result(ArrayList(u8), IOError), IO)))(
297
- io.async((using(io : IO)) => {
298
- file_result := io.await(File.open(path, .Read, using(io)));
299
- match(file_result,
300
- .Ok(file) => {
301
- content := io.await(file.read_all(using(io)));
302
- io.await(file.close(using(io)));
303
- return content;
304
- },
305
- .Err(e) => .Err(e)
306
- )
288
+ read_file :: (fn(path: Path, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
289
+ io.async((using(io, exn)) => {
290
+ file := io.await(File.open(path, .Read));
291
+ content := io.await(file.read_bytes());
292
+ io.await(file.close());
293
+ return content;
307
294
  })
308
295
  );
309
296
 
310
297
  // Read an entire file into bytes (str version).
311
- read_file_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Result(ArrayList(u8), IOError), IO)))(
312
- read_file(Path.new(String.from(path)), using(io))
298
+ read_file_str :: (fn(path: str, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
299
+ read_file(Path.new(String.from(path)))
313
300
  );
314
301
 
315
302
  // Read an entire file into bytes (C string version).
316
- read_file_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(Result(ArrayList(u8), IOError), IO)))(
317
- read_file(Path.from_cstr(path), using(io))
303
+ read_file_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))(
304
+ read_file(Path.from_cstr(path))
318
305
  );
319
306
 
320
- // Write a str to a file (creates or truncates) (Path version).
321
- write_file :: (fn(path: Path, data: str, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
322
- io.async((using(io : IO)) => {
323
- file_result := io.await(File.open(path, .Write, using(io)));
324
- match(file_result,
325
- .Ok(file) => {
326
- write_result := io.await(file.write(String.from(data), using(io)));
327
- io.await(file.close(using(io)));
328
- match(write_result,
329
- .Ok(_) => .Ok(()),
330
- .Err(e) => .Err(e)
331
- )
332
- },
333
- .Err(e) => .Err(e)
334
- )
307
+ // Write a String to a file (creates or truncates) (Path version).
308
+ write_file :: (fn(path: Path, data: String, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
309
+ io.async((using(io, exn)) => {
310
+ file := io.await(File.open(path, .Write));
311
+ io.await(file.write_string(data));
312
+ io.await(file.close());
335
313
  })
336
314
  );
337
315
 
338
316
  // Write a str to a file (creates or truncates) (str path version).
339
- write_file_str :: (fn(path: str, data: str, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
340
- write_file(Path.new(String.from(path)), data, using(io))
317
+ write_file_str :: (fn(path: str, data: str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
318
+ write_file(Path.new(String.from(path)), String.from(data))
341
319
  );
342
320
 
343
321
  // Write a str to a file (creates or truncates) (C string path version).
344
- write_file_cstr :: (fn(path: *(u8), data: str, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
345
- write_file(Path.from_cstr(path), data, using(io))
322
+ write_file_cstr :: (fn(path: *(u8), data: str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
323
+ write_file(Path.from_cstr(path), String.from(data))
346
324
  );
347
325
 
348
326
  // Write bytes to a file (creates or truncates) (Path version).
349
- write_bytes :: (fn(path: Path, data: ArrayList(u8), using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
350
- io.async((using(io : IO)) => {
351
- file_result := io.await(File.open(path, .Write, using(io)));
352
- match(file_result,
353
- .Ok(file) => {
354
- write_result := io.await(file.write_bytes(data, using(io)));
355
- io.await(file.close(using(io)));
356
- match(write_result,
357
- .Ok(_) => .Ok(()),
358
- .Err(e) => .Err(e)
359
- )
360
- },
361
- .Err(e) => .Err(e)
362
- )
327
+ write_bytes :: (fn(path: Path, data: ArrayList(u8), using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
328
+ io.async((using(io, exn)) => {
329
+ file := io.await(File.open(path, .Write));
330
+ io.await(file.write_bytes(data));
331
+ io.await(file.close());
363
332
  })
364
333
  );
365
334
 
366
335
  // Append a str to a file (creates if not exists) (Path version).
367
- append_file :: (fn(path: Path, data: str, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
368
- io.async((using(io : IO)) => {
369
- file_result := io.await(File.open(path, .Append, using(io)));
370
- match(file_result,
371
- .Ok(file) => {
372
- write_result := io.await(file.write(String.from(data), using(io)));
373
- io.await(file.close(using(io)));
374
- match(write_result,
375
- .Ok(_) => .Ok(()),
376
- .Err(e) => .Err(e)
377
- )
378
- },
379
- .Err(e) => .Err(e)
380
- )
336
+ append_file :: (fn(path: Path, data: String, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
337
+ io.async((using(io, exn)) => {
338
+ file := io.await(File.open(path, .Append));
339
+ io.await(file.write_string(data));
340
+ io.await(file.close());
381
341
  })
382
342
  );
383
343
 
384
344
  // Append a str to a file (str path version).
385
- append_file_str :: (fn(path: str, data: str, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))(
386
- append_file(Path.new(String.from(path)), data, using(io))
345
+ append_file_str :: (fn(path: str, data: str, using(io : IO)) -> Impl(Future(unit, IO, Exception)))(
346
+ append_file(Path.new(String.from(path)), String.from(data))
387
347
  );
388
348
 
349
+ extern "Yo",
350
+ __yo_statx_buf_size : (fn() -> usize)
351
+ ;
352
+
389
353
  // Check if a path exists (Path version).
390
- exists :: (fn(path: Path, using(io : IO)) -> Impl(Future(Result(bool, IOError), IO)))(
354
+ // Does NOT use Exception returns false for any error (including file not found).
355
+ exists :: (fn(path: Path, using(io : IO)) -> Impl(Future(bool, IO)))(
391
356
  io.async((using(io : IO)) => {
392
- meta_result := io.await(_metadata_mod.metadata(path, using(io)));
393
- match(meta_result,
394
- .Ok(_) => .Ok(true),
395
- .Err(e) => match(e,
396
- .NotFound => .Ok(false),
397
- _ => .Err(e)
398
- )
399
- )
357
+ cstr_bytes := path.to_string().to_cstr();
358
+ cstr := cstr_bytes.ptr().unwrap();
359
+ buf_size := __yo_statx_buf_size();
360
+ buf := *(u8)(malloc(buf_size).unwrap());
361
+ result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
362
+ free(.Some(*(void)(buf)));
363
+ (result >= i32(0))
400
364
  })
401
365
  );
402
366
 
403
367
  // Check if a path exists (str version).
404
- exists_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Result(bool, IOError), IO)))(
368
+ exists_str :: (fn(path: str, using(io : IO)) -> Impl(Future(bool, IO)))(
405
369
  exists(Path.new(String.from(path)), using(io))
406
370
  );
407
371
 
408
372
  // Check if a path exists (C string version).
409
- exists_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(Result(bool, IOError), IO)))(
373
+ exists_cstr :: (fn(path: *(u8), using(io : IO)) -> Impl(Future(bool, IO)))(
410
374
  exists(Path.from_cstr(path), using(io))
411
375
  );
412
376
 
413
377
  export
414
- read_to_string, read_to_string_str, read_to_string_cstr,
378
+ read_string, read_string_str, read_string_cstr,
415
379
  read_file, read_file_str, read_file_cstr,
416
380
  write_file, write_file_str, write_file_cstr,
417
381
  write_bytes,
@@ -1,19 +1,21 @@
1
1
  // std/fs/metadata.yo - File metadata
2
2
  //
3
3
  // Wraps the low-level statx buffer with ergonomic accessors.
4
+ // Uses Exception effect for error handling.
4
5
  //
5
6
  // Example:
6
7
  // { metadata } :: import "std/fs/metadata";
7
8
  //
8
9
  // main :: (fn(using(io : IO)) -> unit)({
9
- // m := io.await(metadata(`/tmp/test.txt`));
10
- // match(m,
11
- // .Ok(meta) => {
12
- // printf("size: %lld\n", meta.size());
13
- // printf("is file: %d\n", i32(meta.is_file()));
14
- // },
15
- // .Err(e) => printf("error\n")
16
- // );
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`)));
17
+ // printf("size: %lld\n", m.size());
18
+ // printf("is file: %d\n", i32(m.is_file()));
17
19
  // });
18
20
 
19
21
  { GlobalAllocator } :: import "../allocator";
@@ -21,6 +23,7 @@
21
23
  open import "../string";
22
24
  { Path } :: import "../path";
23
25
  { IOError } :: import "../sys/errors";
26
+ { Error, AnyError, Exception } :: import "../error";
24
27
  { Statx } :: import "../sys/statx";
25
28
  IO_file :: import "../sys/file";
26
29
  {
@@ -126,8 +129,8 @@ extern "Yo",
126
129
  // Internal helper to stat a path
127
130
  // ============================================================================
128
131
 
129
- _stat_path :: (fn(path: Path, flags: i32, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))(
130
- io.async((using(io)) => {
132
+ _stat_path :: (fn(path: Path, flags: i32, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))(
133
+ io.async((using(io, exn)) => {
131
134
  cstr_bytes := path.to_string().to_cstr();
132
135
  cstr := cstr_bytes.ptr().unwrap();
133
136
  buf_size := __yo_statx_buf_size();
@@ -136,34 +139,32 @@ _stat_path :: (fn(path: Path, flags: i32, using(io : IO)) -> Impl(Future(Result(
136
139
  cond(
137
140
  (result < i32(0)) => {
138
141
  free(.Some(*(void)(buf)));
139
- (ret : Result(Metadata, IOError)) = .Err(IOError.from_errno((i32(0) - result)));
140
- return ret;
142
+ exn.throw(dyn IOError.from_errno((i32(0) - result)))
141
143
  },
142
144
  true => {
143
145
  sx := Statx(_buf_ptr: buf, _buf_size: buf_size);
144
- (ret : Result(Metadata, IOError)) = .Ok(Metadata(_statx: sx, _buf_ptr: buf));
145
- return ret;
146
+ Metadata(_statx: sx, _buf_ptr: buf)
146
147
  }
147
148
  )
148
149
  })
149
150
  );
150
151
 
151
152
  // Get metadata for a path (follows symlinks).
152
- metadata :: (fn(path: Path, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))
153
- _stat_path(path, AT_STATX_SYNC_AS_STAT, using(io))
153
+ metadata :: (fn(path: Path, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))
154
+ _stat_path(path, AT_STATX_SYNC_AS_STAT)
154
155
  ;
155
156
 
156
- metadata_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))
157
- metadata(Path.new(String.from(path)), using(io))
157
+ metadata_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))
158
+ metadata(Path.new(String.from(path)))
158
159
  ;
159
160
 
160
161
  // Get metadata for a path (does NOT follow symlinks).
161
- symlink_metadata :: (fn(path: Path, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))
162
- _stat_path(path, (AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT), using(io))
162
+ symlink_metadata :: (fn(path: Path, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))
163
+ _stat_path(path, (AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT))
163
164
  ;
164
165
 
165
- symlink_metadata_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Result(Metadata, IOError), IO)))
166
- symlink_metadata(Path.new(String.from(path)), using(io))
166
+ symlink_metadata_str :: (fn(path: str, using(io : IO)) -> Impl(Future(Metadata, IO, Exception)))
167
+ symlink_metadata(Path.new(String.from(path)))
167
168
  ;
168
169
 
169
170
  export metadata, metadata_str, symlink_metadata, symlink_metadata_str;