@shd101wyy/yo 0.0.25 → 0.0.27

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 (47) hide show
  1. package/README.md +9 -9
  2. package/out/cjs/index.cjs +568 -563
  3. package/out/cjs/yo-cli.cjs +569 -564
  4. package/out/esm/index.mjs +487 -482
  5. package/out/types/src/codegen/async/state-machine.d.ts +1 -1
  6. package/out/types/src/codegen/exprs/await.d.ts +1 -0
  7. package/out/types/src/codegen/exprs/downcast.d.ts +3 -0
  8. package/out/types/src/codegen/exprs/return.d.ts +1 -0
  9. package/out/types/src/codegen/exprs/typeid.d.ts +3 -0
  10. package/out/types/src/codegen/exprs/while.d.ts +1 -1
  11. package/out/types/src/codegen/functions/context.d.ts +6 -18
  12. package/out/types/src/codegen/functions/declarations.d.ts +10 -2
  13. package/out/types/src/codegen/types/dyn.d.ts +1 -0
  14. package/out/types/src/codegen/types/generation.d.ts +1 -1
  15. package/out/types/src/codegen/utils/index.d.ts +1 -0
  16. package/out/types/src/evaluator/async/await-analysis.d.ts +1 -0
  17. package/out/types/src/evaluator/builtins/downcast.d.ts +8 -0
  18. package/out/types/src/evaluator/builtins/rc-fns.d.ts +5 -0
  19. package/out/types/src/evaluator/builtins/typeid.d.ts +8 -0
  20. package/out/types/src/evaluator/context.d.ts +2 -0
  21. package/out/types/src/expr.d.ts +3 -0
  22. package/out/types/src/function-value.d.ts +1 -0
  23. package/out/types/src/types/creators.d.ts +3 -1
  24. package/out/types/src/types/definitions.d.ts +3 -1
  25. package/out/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +1 -1
  27. package/std/crypto/random.yo +25 -13
  28. package/std/encoding/base64.yo +24 -49
  29. package/std/encoding/hex.yo +25 -22
  30. package/std/encoding/json.yo +25 -3
  31. package/std/encoding/utf16.yo +6 -5
  32. package/std/error.yo +39 -23
  33. package/std/fs/dir.yo +106 -103
  34. package/std/fs/file.yo +122 -158
  35. package/std/fs/metadata.yo +23 -22
  36. package/std/fs/temp.yo +41 -47
  37. package/std/fs/walker.yo +48 -55
  38. package/std/net/addr.yo +8 -7
  39. package/std/net/dns.yo +27 -33
  40. package/std/net/errors.yo +13 -8
  41. package/std/net/tcp.yo +92 -113
  42. package/std/net/udp.yo +50 -54
  43. package/std/os/signal.yo +13 -8
  44. package/std/prelude.yo +21 -16
  45. package/std/sys/errors.yo +45 -33
  46. package/std/url/url.yo +19 -32
  47. package/out/types/src/codegen/effects/effect-state-machine.d.ts +0 -34
package/std/fs/temp.yo CHANGED
@@ -7,14 +7,15 @@
7
7
  // { TempDir } :: import "std/fs/temp";
8
8
  //
9
9
  // main :: (fn(using(io : IO)) -> unit)({
10
- // td := io.await(TempDir.new());
11
- // match(td,
12
- // .Ok(dir) => {
13
- // println(dir.path());
14
- // io.await(dir.remove());
15
- // },
16
- // .Err(e) => println(e.to_string())
17
- // );
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
+ // dir := io.await(TempDir.new());
17
+ // println(dir.path());
18
+ // io.await(dir.remove());
18
19
  // });
19
20
 
20
21
  { GlobalAllocator } :: import "../allocator";
@@ -23,6 +24,7 @@ open import "../string";
23
24
  open import "../fmt";
24
25
  { Path } :: import "../path";
25
26
  { IOError } :: import "../sys/errors";
27
+ { Error, AnyError, Exception } :: import "../error";
26
28
  _file_mod :: import "./file";
27
29
  _dir_mod :: import "./dir";
28
30
  IO_temp :: import "../sys/temp";
@@ -61,8 +63,8 @@ TempDir :: object(
61
63
 
62
64
  impl(TempDir,
63
65
  // Create a temporary directory in the given parent directory.
64
- new_in : (fn(parent: Path, using(io : IO)) -> Impl(Future(Result(TempDir, IOError), IO)))(
65
- io.async((using(io : IO)) => {
66
+ new_in : (fn(parent: Path, using(io : IO)) -> Impl(Future(TempDir, IO, Exception)))(
67
+ io.async((using(io, exn)) => {
66
68
  // Build template: parent/yo_tmp_XXXXXX
67
69
  template_path := parent.join(Path.new(`yo_tmp_XXXXXX`));
68
70
  template_str := template_path.to_string();
@@ -76,22 +78,19 @@ impl(TempDir,
76
78
  cond(
77
79
  (result < i32(0)) => {
78
80
  free(.Some(*(void)(buf)));
79
- (ret : Result(TempDir, IOError)) = .Err(IOError.from_errno((i32(0) - result)));
80
- return ret;
81
+ exn.throw(dyn IOError.from_errno((i32(0) - result)));
81
82
  },
82
- true => {
83
- path_str := String.from_cstr(buf).unwrap();
84
- free(.Some(*(void)(buf)));
85
- (ret : Result(TempDir, IOError)) = .Ok(TempDir(_path: Path.new(path_str), _removed: false));
86
- return ret;
87
- }
88
- )
83
+ true => ()
84
+ );
85
+ path_str := String.from_cstr(buf).unwrap();
86
+ free(.Some(*(void)(buf)));
87
+ TempDir(_path: Path.new(path_str), _removed: false)
89
88
  })
90
89
  ),
91
90
 
92
91
  // Create a temporary directory in the system temp dir.
93
- new : (fn(using(io : IO)) -> Impl(Future(Result(TempDir, IOError), IO)))(
94
- TempDir.new_in(Path.new(_default_tmp_dir()), using(io))
92
+ new : (fn(using(io : IO)) -> Impl(Future(TempDir, IO, Exception)))(
93
+ TempDir.new_in(Path.new(_default_tmp_dir()))
95
94
  ),
96
95
 
97
96
  // Get the path of the temporary directory.
@@ -100,15 +99,14 @@ impl(TempDir,
100
99
  ),
101
100
 
102
101
  // Remove the temporary directory.
103
- remove : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))({
102
+ remove : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
104
103
  self_path := self._path;
105
- io.async((using(io : IO)) =>
104
+ io.async((using(io, exn)) =>
106
105
  cond(
107
- self._removed => .Ok(()),
106
+ self._removed => (),
108
107
  true => {
109
- result := io.await(_dir_mod.remove_dir(self_path, using(io)));
108
+ io.await(_dir_mod.remove_dir(self_path));
110
109
  self._removed = true;
111
- return result;
112
110
  }
113
111
  )
114
112
  )
@@ -129,8 +127,8 @@ TempFile :: object(
129
127
 
130
128
  impl(TempFile,
131
129
  // Create a temporary file in the given parent directory.
132
- new_in : (fn(parent: Path, using(io : IO)) -> Impl(Future(Result(TempFile, IOError), IO)))(
133
- io.async((using(io : IO)) => {
130
+ new_in : (fn(parent: Path, using(io : IO)) -> Impl(Future(TempFile, IO, Exception)))(
131
+ io.async((using(io, exn)) => {
134
132
  // Build template: parent/yo_tmp_XXXXXX
135
133
  template_path := parent.join(Path.new(`yo_tmp_XXXXXX`));
136
134
  template_str := template_path.to_string();
@@ -143,24 +141,21 @@ impl(TempFile,
143
141
  cond(
144
142
  (fd < i32(0)) => {
145
143
  free(.Some(*(void)(buf)));
146
- (ret : Result(TempFile, IOError)) = .Err(IOError.from_errno((i32(0) - fd)));
147
- return ret;
144
+ exn.throw(dyn IOError.from_errno((i32(0) - fd)));
148
145
  },
149
- true => {
150
- path_str := String.from_cstr(buf).unwrap();
151
- free(.Some(*(void)(buf)));
152
- path := Path.new(path_str);
153
- file := _file_mod.File(_fd: fd, _path: path, _is_closed: false);
154
- (ret : Result(TempFile, IOError)) = .Ok(TempFile(_file: file, _path: path, _removed: false));
155
- return ret;
156
- }
157
- )
146
+ true => ()
147
+ );
148
+ path_str := String.from_cstr(buf).unwrap();
149
+ free(.Some(*(void)(buf)));
150
+ path := Path.new(path_str);
151
+ file := _file_mod.File(_fd: fd, _path: path, _is_closed: false);
152
+ TempFile(_file: file, _path: path, _removed: false)
158
153
  })
159
154
  ),
160
155
 
161
156
  // Create a temporary file in the system temp dir.
162
- new : (fn(using(io : IO)) -> Impl(Future(Result(TempFile, IOError), IO)))(
163
- TempFile.new_in(Path.new(_default_tmp_dir()), using(io))
157
+ new : (fn(using(io : IO)) -> Impl(Future(TempFile, IO, Exception)))(
158
+ TempFile.new_in(Path.new(_default_tmp_dir()))
164
159
  ),
165
160
 
166
161
  // Get the underlying File object.
@@ -174,17 +169,16 @@ impl(TempFile,
174
169
  ),
175
170
 
176
171
  // Remove the temporary file.
177
- remove : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(unit, IOError), IO)))({
172
+ remove : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
178
173
  self_file := self._file;
179
174
  self_path := self._path;
180
- io.async((using(io : IO)) =>
175
+ io.async((using(io, exn)) =>
181
176
  cond(
182
- self._removed => .Ok(()),
177
+ self._removed => (),
183
178
  true => {
184
- io.await(self_file.close(using(io)));
185
- result := io.await(_dir_mod.remove_file(self_path, using(io)));
179
+ io.await(self_file.close());
180
+ io.await(_dir_mod.remove_file(self_path));
186
181
  self._removed = true;
187
- return result;
188
182
  }
189
183
  )
190
184
  )
package/std/fs/walker.yo CHANGED
@@ -6,24 +6,26 @@
6
6
  // { walk, WalkEntry } :: import "std/fs/walker";
7
7
  //
8
8
  // main :: (fn(using(io : IO)) -> unit)({
9
+ // given(exn) : Exception = {
10
+ // throw : (fn(forall(T : Type), error: AnyError) -> T)(
11
+ // { println(error.to_string()); exit(i32(1)); }
12
+ // )
13
+ // };
14
+ //
9
15
  // entries := io.await(walk(`/tmp`));
10
- // match(entries,
11
- // .Ok(list) => {
12
- // i := usize(0);
13
- // while runtime((i < list.len())), {
14
- // e := list.get(i).unwrap();
15
- // println(e.path);
16
- // i = (i + usize(1));
17
- // };
18
- // },
19
- // .Err(e) => println(e.to_string())
20
- // );
16
+ // i := usize(0);
17
+ // while runtime((i < entries.len())), {
18
+ // e := entries.get(i).unwrap();
19
+ // println(e.path);
20
+ // i = (i + usize(1));
21
+ // };
21
22
  // });
22
23
 
23
24
  { ArrayList } :: import "../collections/array_list";
24
25
  open import "../string";
25
26
  { Path } :: import "../path";
26
27
  { IOError } :: import "../sys/errors";
28
+ { Error, AnyError, Exception } :: import "../error";
27
29
  { FileType } :: import "./dir";
28
30
  { DirEntry } :: import "./dir";
29
31
  _dir :: import "./dir";
@@ -79,9 +81,9 @@ _join_path :: (fn(base: String, name: String) -> String)(
79
81
  // ============================================================================
80
82
 
81
83
  // Walk a directory tree with custom options.
82
- walk_with :: (fn(root: Path, options: WalkOptions, using(io : IO)) -> Impl(Future(Result(ArrayList(WalkEntry), IOError), IO)))({
84
+ walk_with :: (fn(root: Path, options: WalkOptions, using(io : IO)) -> Impl(Future(ArrayList(WalkEntry), IO, Exception)))({
83
85
  root_s := root.to_string();
84
- io.async((using(io : IO)) => {
86
+ io.async((using(io, exn)) => {
85
87
  results := ArrayList(WalkEntry).new();
86
88
  // Stack of (path, depth) pairs to process
87
89
  stack := ArrayList(struct(path: String, depth: u32)).new();
@@ -100,67 +102,58 @@ walk_with :: (fn(root: Path, options: WalkOptions, using(io : IO)) -> Impl(Futur
100
102
 
101
103
  cond(
102
104
  should_continue => {
103
- dir_result := io.await(_dir.read_dir(Path.new(cur_path), using(io)));
104
- match(dir_result,
105
- .Ok(entries) => {
106
- i := usize(0);
107
- while runtime((i < entries.len())), {
108
- entry := entries.get(i).unwrap();
109
- entry_path := _join_path(cur_path, entry.name);
110
- match(entry.file_type,
111
- .Directory => {
112
- cond(
113
- options.include_dirs => {
114
- results.push(WalkEntry(
115
- path: Path.new(entry_path),
116
- name: entry.name,
117
- depth: cur_depth,
118
- file_type: .Directory
119
- ));
120
- },
121
- true => ()
122
- );
123
- // Push subdirectory for processing
124
- stack.push({ path: entry_path, depth: (cur_depth + u32(1)) });
125
- },
126
- _ => {
105
+ entries := io.await(_dir.read_dir(Path.new(cur_path)));
106
+ i := usize(0);
107
+ while runtime((i < entries.len())), {
108
+ entry := entries.get(i).unwrap();
109
+ entry_path := _join_path(cur_path, entry.name);
110
+ match(entry.file_type,
111
+ .Directory => {
112
+ cond(
113
+ options.include_dirs => {
127
114
  results.push(WalkEntry(
128
115
  path: Path.new(entry_path),
129
116
  name: entry.name,
130
117
  depth: cur_depth,
131
- file_type: entry.file_type
118
+ file_type: .Directory
132
119
  ));
133
- }
120
+ },
121
+ true => ()
134
122
  );
135
- i = (i + usize(1));
136
- };
137
- },
138
- .Err(e) => {
139
- (ret : Result(ArrayList(WalkEntry), IOError)) = .Err(e);
140
- return ret;
141
- }
142
- );
123
+ // Push subdirectory for processing
124
+ stack.push({ path: entry_path, depth: (cur_depth + u32(1)) });
125
+ },
126
+ _ => {
127
+ results.push(WalkEntry(
128
+ path: Path.new(entry_path),
129
+ name: entry.name,
130
+ depth: cur_depth,
131
+ file_type: entry.file_type
132
+ ));
133
+ }
134
+ );
135
+ i = (i + usize(1));
136
+ };
143
137
  },
144
138
  true => ()
145
139
  );
146
140
  };
147
141
 
148
- (ret : Result(ArrayList(WalkEntry), IOError)) = .Ok(results);
149
- return ret;
142
+ results
150
143
  })
151
144
  });
152
145
 
153
- walk_with_cstr :: (fn(root: *(u8), options: WalkOptions, using(io : IO)) -> Impl(Future(Result(ArrayList(WalkEntry), IOError), IO)))(
154
- walk_with(Path.from_cstr(root), options, using(io))
146
+ walk_with_cstr :: (fn(root: *(u8), options: WalkOptions, using(io : IO)) -> Impl(Future(ArrayList(WalkEntry), IO, Exception)))(
147
+ walk_with(Path.from_cstr(root), options)
155
148
  );
156
149
 
157
150
  // Walk a directory tree with default options.
158
- walk :: (fn(root: Path, using(io : IO)) -> Impl(Future(Result(ArrayList(WalkEntry), IOError), IO)))
159
- walk_with(root, WalkOptions.defaults(), using(io))
151
+ walk :: (fn(root: Path, using(io : IO)) -> Impl(Future(ArrayList(WalkEntry), IO, Exception)))
152
+ walk_with(root, WalkOptions.defaults())
160
153
  ;
161
154
 
162
- walk_cstr :: (fn(root: *(u8), using(io : IO)) -> Impl(Future(Result(ArrayList(WalkEntry), IOError), IO)))
163
- walk(Path.from_cstr(root), using(io))
155
+ walk_cstr :: (fn(root: *(u8), using(io : IO)) -> Impl(Future(ArrayList(WalkEntry), IO, Exception)))
156
+ walk(Path.from_cstr(root))
164
157
  ;
165
158
 
166
159
  export walk, walk_cstr, walk_with, walk_with_cstr;
package/std/net/addr.yo CHANGED
@@ -14,6 +14,7 @@ open import "../string";
14
14
  { snprintf } :: import "../libc/stdio";
15
15
  { GlobalAllocator } :: import "../allocator";
16
16
  { malloc, free } :: GlobalAllocator;
17
+ { Error, AnyError, Exception } :: import "../error";
17
18
 
18
19
  // ============================================================================
19
20
  // IpAddr
@@ -32,7 +33,7 @@ IpAddr :: enum(
32
33
  impl(IpAddr,
33
34
  // Parse an IPv4 address from a String like "127.0.0.1".
34
35
  // Only supports IPv4 dotted-decimal notation.
35
- parse_v4 : (fn(s: String) -> Result(IpAddr, NetError))({
36
+ parse_v4 : (fn(s: String, using(exn : Exception)) -> IpAddr)({
36
37
  bytes := s.as_bytes();
37
38
  parts := Array(u8, usize(4)).fill(u8(0));
38
39
  part_idx := usize(0);
@@ -45,13 +46,13 @@ impl(IpAddr,
45
46
  // '.' separator
46
47
  cond(
47
48
  (part_idx >= usize(3)) => {
48
- return .Err(.Other(String.from("invalid IPv4 address")));
49
+ exn.throw(dyn NetError.Other(String.from("invalid IPv4 address")));
49
50
  },
50
51
  true => ()
51
52
  );
52
53
  cond(
53
54
  (val > u32(255)) => {
54
- return .Err(.Other(String.from("IPv4 octet out of range")));
55
+ exn.throw(dyn NetError.Other(String.from("IPv4 octet out of range")));
55
56
  },
56
57
  true => ()
57
58
  );
@@ -64,25 +65,25 @@ impl(IpAddr,
64
65
  val = ((val * u32(10)) + u32((ch - _ASCII_ZERO)));
65
66
  },
66
67
  true => {
67
- return .Err(.Other(String.from("invalid character in IPv4 address")));
68
+ exn.throw(dyn NetError.Other(String.from("invalid character in IPv4 address")));
68
69
  }
69
70
  );
70
71
  i = (i + usize(1));
71
72
  };
72
73
  cond(
73
74
  (part_idx != usize(3)) => {
74
- return .Err(.Other(String.from("invalid IPv4 address")));
75
+ exn.throw(dyn NetError.Other(String.from("invalid IPv4 address")));
75
76
  },
76
77
  true => ()
77
78
  );
78
79
  cond(
79
80
  (val > u32(255)) => {
80
- return .Err(.Other(String.from("IPv4 octet out of range")));
81
+ exn.throw(dyn NetError.Other(String.from("IPv4 octet out of range")));
81
82
  },
82
83
  true => ()
83
84
  );
84
85
  parts(usize(3)) = u8(val);
85
- return .Ok(.V4(parts(usize(0)), parts(usize(1)), parts(usize(2)), parts(usize(3))));
86
+ .V4(parts(usize(0)), parts(usize(1)), parts(usize(2)), parts(usize(3)))
86
87
  }),
87
88
 
88
89
  // IPv4 loopback address (127.0.0.1).
package/std/net/dns.yo CHANGED
@@ -1,23 +1,24 @@
1
1
  // std/net/dns.yo - High-level DNS resolution
2
2
  //
3
3
  // Wraps std/sys/dns with typed DNS lookup functions.
4
+ // Uses the Exception effect for error handling.
4
5
  //
5
6
  // Example:
6
7
  // { lookup_host } :: import "std/net/dns";
7
8
  // { IpAddr } :: import "std/net/addr";
9
+ // { Exception } :: import "std/error";
8
10
  //
9
11
  // main :: (fn(using(io : IO)) -> unit)({
12
+ // given(exn) := Exception(throw : ((err) -> {
13
+ // println(err.message());
14
+ // escape ();
15
+ // }));
10
16
  // addrs := io.await(lookup_host(`localhost`));
11
- // match(addrs,
12
- // .Ok(list) => {
13
- // i := usize(0);
14
- // while runtime((i < list.len())), {
15
- // println(list.get(i).unwrap().to_string());
16
- // i = (i + usize(1));
17
- // };
18
- // },
19
- // .Err(e) => println(e.to_string())
20
- // );
17
+ // i := usize(0);
18
+ // while runtime((i < addrs.len())), {
19
+ // println(addrs.get(i).unwrap().to_string());
20
+ // i = (i + usize(1));
21
+ // };
21
22
  // });
22
23
 
23
24
  { GlobalAllocator } :: import "../allocator";
@@ -27,6 +28,7 @@ open import "../string";
27
28
  open import "../fmt";
28
29
  { NetError } :: import "./errors";
29
30
  { IpAddr, SocketAddr } :: import "./addr";
31
+ { Error, AnyError, Exception } :: import "../error";
30
32
  IO_dns :: import "../sys/dns";
31
33
  { AF_INET, AF_INET6 } :: import "../sys/socket";
32
34
 
@@ -35,8 +37,8 @@ IO_dns :: import "../sys/dns";
35
37
  // ============================================================================
36
38
 
37
39
  // Resolve a hostname to a list of IP addresses.
38
- lookup_host :: (fn(host: String, using(io : IO)) -> Impl(Future(Result(ArrayList(IpAddr), NetError), IO)))(
39
- io.async((using(io : IO)) => {
40
+ lookup_host :: (fn(host: String, using(io : IO)) -> Impl(Future(ArrayList(IpAddr), IO, Exception)))(
41
+ io.async((using(io : IO, exn : Exception)) => {
40
42
  host_cstr_bytes := host.to_cstr();
41
43
  host_cstr := host_cstr_bytes.ptr().unwrap();
42
44
  result_ptr := IO_dns.alloc_result();
@@ -44,8 +46,7 @@ lookup_host :: (fn(host: String, using(io : IO)) -> Impl(Future(Result(ArrayList
44
46
  cond(
45
47
  (ret != i32(0)) => {
46
48
  IO_dns.free_result(result_ptr);
47
- (err_ret : Result(ArrayList(IpAddr), NetError)) = .Err(.DNSFailed(host));
48
- return err_ret;
49
+ exn.throw(dyn NetError.DNSFailed(host));
49
50
  },
50
51
  true => ()
51
52
  );
@@ -79,29 +80,22 @@ lookup_host :: (fn(host: String, using(io : IO)) -> Impl(Future(Result(ArrayList
79
80
  .None => ()
80
81
  );
81
82
  IO_dns.free_result(result_ptr);
82
- (ok_ret : Result(ArrayList(IpAddr), NetError)) = .Ok(addrs);
83
- return ok_ret;
83
+ return addrs;
84
84
  })
85
85
  );
86
86
 
87
87
  // Resolve a hostname and port to a list of socket addresses.
88
- resolve :: (fn(host: String, port: u16, using(io : IO)) -> Impl(Future(Result(ArrayList(SocketAddr), NetError), IO)))(
89
- io.async((using(io : IO)) => {
90
- addrs_result := io.await(lookup_host(host, using(io)));
91
- (ret : Result(ArrayList(SocketAddr), NetError)) = match(addrs_result,
92
- .Ok(addrs) => {
93
- result := ArrayList(SocketAddr).new();
94
- i := usize(0);
95
- while runtime((i < addrs.len())), {
96
- ip := addrs.get(i).unwrap();
97
- result.push(SocketAddr.new(ip, port));
98
- i = (i + usize(1));
99
- };
100
- .Ok(result)
101
- },
102
- .Err(e) => .Err(e)
103
- );
104
- return ret;
88
+ resolve :: (fn(host: String, port: u16, using(io : IO)) -> Impl(Future(ArrayList(SocketAddr), IO, Exception)))(
89
+ io.async((using(io : IO, exn : Exception)) => {
90
+ addrs := io.await(lookup_host(host, using(io)));
91
+ result := ArrayList(SocketAddr).new();
92
+ i := usize(0);
93
+ while runtime((i < addrs.len())), {
94
+ ip := addrs.get(i).unwrap();
95
+ result.push(SocketAddr.new(ip, port));
96
+ i = (i + usize(1));
97
+ };
98
+ return result;
105
99
  })
106
100
  );
107
101
 
package/std/net/errors.yo CHANGED
@@ -8,6 +8,7 @@
8
8
  open import "../string";
9
9
  { IOError } :: import "../sys/errors";
10
10
  { ToString } :: import "../fmt";
11
+ { Error, AnyError, Exception } :: import "../error";
11
12
 
12
13
  // ============================================================================
13
14
  // NetError
@@ -41,14 +42,6 @@ impl(NetError,
41
42
  .NetworkUnreachable => .NetworkUnreachable,
42
43
  _ => .IO(err)
43
44
  )
44
- ),
45
-
46
- // Convert a raw result (positive = ok, negative = -errno) to Result.
47
- from_result : (fn(result: i32) -> Result(i32, Self))(
48
- cond(
49
- (result >= i32(0)) => .Ok(result),
50
- true => .Err(Self.from_io(IOError.from_errno((i32(0) - result))))
51
- )
52
45
  )
53
46
  );
54
47
 
@@ -71,4 +64,16 @@ impl(NetError, ToString(
71
64
  })
72
65
  ));
73
66
 
67
+ impl(NetError, Error());
68
+
69
+ impl(NetError,
70
+ // Check a raw result (positive = ok, negative = -errno) and throw on error.
71
+ check : (fn(result: i32, using(exn : Exception)) -> i32)(
72
+ cond(
73
+ (result >= i32(0)) => result,
74
+ true => exn.throw(dyn Self.from_io(IOError.from_errno((i32(0) - result))))
75
+ )
76
+ )
77
+ );
78
+
74
79
  export NetError;