@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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shd101wyy/yo",
3
3
  "displayName": "Yo",
4
- "version": "0.0.25",
4
+ "version": "0.0.27",
5
5
  "main": "./out/cjs/index.cjs",
6
6
  "module": "./out/esm/index.mjs",
7
7
  "types": "./out/types/src/index.d.ts",
@@ -15,6 +15,8 @@
15
15
  open import "../string";
16
16
  { snprintf } :: import "../libc/stdio";
17
17
  { hex_encode } :: import "../encoding/hex";
18
+ { Error, AnyError, Exception } :: import "../error";
19
+ { ToString } :: import "../fmt";
18
20
 
19
21
  // ============================================================================
20
22
  // Error type
@@ -25,6 +27,17 @@ CryptoError :: enum(
25
27
  Other(msg: String)
26
28
  );
27
29
 
30
+ impl(CryptoError, ToString(
31
+ to_string : (self ->
32
+ match(self,
33
+ .Unavailable => `crypto: platform random unavailable`,
34
+ .Other(msg) => `crypto error: ${msg}`
35
+ )
36
+ )
37
+ ));
38
+
39
+ impl(CryptoError, Error());
40
+
28
41
  export CryptoError;
29
42
 
30
43
  // ============================================================================
@@ -41,26 +54,25 @@ extern "Yo",
41
54
  // Fill a buffer with cryptographically secure random bytes.
42
55
  // ============================================================================
43
56
 
44
- random_bytes :: (fn(buf: *(u8), size: usize) -> Result(unit, CryptoError))(
57
+ random_bytes :: (fn(buf: *(u8), size: usize, using(exn : Exception)) -> unit)(
45
58
  cond(
46
59
  (platform == Platform.Darwin) => {
47
60
  __yo_arc4random_buf(buf, size);
48
- .Ok(())
49
61
  },
50
62
  (platform == Platform.Win32) => {
51
63
  r := __yo_bcrypt_gen_random(buf, u32(size));
52
64
  cond(
53
- (r == i32(0)) => .Ok(()),
54
- true => .Err(.Unavailable)
55
- )
65
+ (r == i32(0)) => (),
66
+ true => { exn.throw(dyn CryptoError.Unavailable); }
67
+ );
56
68
  },
57
69
  true => {
58
70
  // Linux: getrandom syscall
59
71
  ret := __yo_getrandom(buf, size, u32(0));
60
72
  cond(
61
- (ret < isize(0)) => .Err(.Unavailable),
62
- true => .Ok(())
63
- )
73
+ (ret < isize(0)) => { exn.throw(dyn CryptoError.Unavailable); },
74
+ true => ()
75
+ );
64
76
  }
65
77
  )
66
78
  );
@@ -71,7 +83,7 @@ export random_bytes;
71
83
  // Typed helpers
72
84
  // ============================================================================
73
85
 
74
- random_u32 :: (fn() -> u32)({
86
+ random_u32 :: (fn(using(exn : Exception)) -> u32)({
75
87
  buf := Array(u8, usize(4)).fill(u8(0));
76
88
  buf_ptr := &(buf(usize(0)));
77
89
  random_bytes(buf_ptr, usize(4));
@@ -81,18 +93,18 @@ random_u32 :: (fn() -> u32)({
81
93
  (u32(buf(usize(3))) << u32(24)))
82
94
  });
83
95
 
84
- random_u64 :: (fn() -> u64)({
96
+ random_u64 :: (fn(using(exn : Exception)) -> u64)({
85
97
  lo := u64(random_u32());
86
98
  hi := u64(random_u32());
87
99
  (lo | (hi << u64(32)))
88
100
  });
89
101
 
90
- random_f64 :: (fn() -> f64)(
102
+ random_f64 :: (fn(using(exn : Exception)) -> f64)(
91
103
  (f64(random_u64()) / f64(18446744073709551615.0))
92
104
  );
93
105
 
94
106
  // Return a random integer in the half-open range [min, max).
95
- random_range :: (fn(min: i64, max: i64) -> i64)({
107
+ random_range :: (fn(min: i64, max: i64, using(exn : Exception)) -> i64)({
96
108
  span := (max - min);
97
109
  cond(
98
110
  (span <= i64(0)) => min,
@@ -110,7 +122,7 @@ export random_u32, random_u64, random_f64, random_range;
110
122
  // ============================================================================
111
123
 
112
124
  // Generate a random UUID v4 string: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
113
- uuid_v4 :: (fn() -> String)({
125
+ uuid_v4 :: (fn(using(exn : Exception)) -> String)({
114
126
  bytes := ArrayList(u8).with_capacity(usize(16));
115
127
  buf := Array(u8, usize(16)).fill(u8(0));
116
128
  buf_ptr := &(buf(usize(0)));
@@ -11,6 +11,7 @@
11
11
  open import "../string";
12
12
  { ArrayList } :: import "../collections/array_list";
13
13
  { EncodingError } :: import "./hex";
14
+ { Error, AnyError, Exception } :: import "../error";
14
15
 
15
16
  // ============================================================================
16
17
  // Standard alphabet
@@ -73,81 +74,55 @@ export base64_encode, base64_encode_url;
73
74
  // Decoding
74
75
  // ============================================================================
75
76
 
76
- _decode_char :: (fn(c: u8, alpha: str) -> Result(u8, EncodingError))({
77
+ _decode_char :: (fn(c: u8, alpha: str, using(exn : Exception)) -> u8)({
77
78
  i := usize(0);
78
79
  while (i < usize(64)), (i = (i + usize(1))), {
79
80
  cond(
80
- (alpha.bytes(i) == c) => { return .Ok(u8(i)); },
81
+ (alpha.bytes(i) == c) => { return u8(i); },
81
82
  true => ()
82
83
  );
83
84
  };
84
- .Err(.InvalidChar(c))
85
+ exn.throw(dyn EncodingError.InvalidChar(c))
85
86
  });
86
87
 
87
- _decode_with :: (fn(s: str, alpha: str) -> Result(ArrayList(u8), EncodingError))({
88
+ _decode_with :: (fn(s: str, alpha: str, using(exn : Exception)) -> ArrayList(u8))({
88
89
  // Strip trailing padding
89
90
  len := s.len();
90
91
  while ((len > usize(0)) && (s.bytes((len - usize(1))) == _PAD)), (len = (len - usize(1))), ();
91
92
  out := ArrayList(u8).with_capacity(((len * usize(3)) / usize(4)));
92
93
  i := usize(0);
93
94
  while (i < len), (i = (i + usize(4))), {
94
- c0_r := _decode_char(s.bytes(i), alpha);
95
- c1_r := cond(
95
+ c0 := _decode_char(s.bytes(i), alpha);
96
+ c1 := cond(
96
97
  ((i + usize(1)) < len) => _decode_char(s.bytes((i + usize(1))), alpha),
97
- true => Result(u8, EncodingError).Ok(u8(0))
98
+ true => u8(0)
98
99
  );
99
- c2_r := cond(
100
- ((i + usize(2)) < len) => _decode_char(s.bytes((i + usize(2))), alpha),
101
- true => Result(u8, EncodingError).Ok(u8(0))
102
- );
103
- c3_r := cond(
104
- ((i + usize(3)) < len) => _decode_char(s.bytes((i + usize(3))), alpha),
105
- true => Result(u8, EncodingError).Ok(u8(0))
106
- );
107
- match(c0_r,
108
- .Err(e) => { return .Err(e); },
109
- .Ok(c0) => {
110
- match(c1_r,
111
- .Err(e) => { return .Err(e); },
112
- .Ok(c1) => {
113
- out.push(((c0 << u8(2)) | (c1 >> u8(4))));
114
- cond(
115
- ((i + usize(2)) < len) => {
116
- match(c2_r,
117
- .Err(e) => { return .Err(e); },
118
- .Ok(c2) => {
119
- out.push((((c1 & u8(15)) << u8(4)) | (c2 >> u8(2))));
120
- cond(
121
- ((i + usize(3)) < len) => {
122
- match(c3_r,
123
- .Err(e) => { return .Err(e); },
124
- .Ok(c3) => {
125
- out.push((((c2 & u8(3)) << u8(6)) | c3));
126
- }
127
- );
128
- },
129
- true => ()
130
- );
131
- }
132
- );
133
- },
134
- true => ()
135
- );
136
- }
100
+ out.push(((c0 << u8(2)) | (c1 >> u8(4))));
101
+ cond(
102
+ ((i + usize(2)) < len) => {
103
+ c2 := _decode_char(s.bytes((i + usize(2))), alpha);
104
+ out.push((((c1 & u8(15)) << u8(4)) | (c2 >> u8(2))));
105
+ cond(
106
+ ((i + usize(3)) < len) => {
107
+ c3 := _decode_char(s.bytes((i + usize(3))), alpha);
108
+ out.push((((c2 & u8(3)) << u8(6)) | c3));
109
+ },
110
+ true => ()
137
111
  );
138
- }
112
+ },
113
+ true => ()
139
114
  );
140
115
  };
141
- .Ok(out)
116
+ out
142
117
  });
143
118
 
144
119
  // Decode standard base64.
145
- base64_decode :: (fn(s: str) -> Result(ArrayList(u8), EncodingError))(
120
+ base64_decode :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))(
146
121
  _decode_with(s, _STD_ALPHA)
147
122
  );
148
123
 
149
124
  // Decode URL-safe base64.
150
- base64_decode_url :: (fn(s: str) -> Result(ArrayList(u8), EncodingError))(
125
+ base64_decode_url :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))(
151
126
  _decode_with(s, _URL_ALPHA)
152
127
  );
153
128
 
@@ -6,10 +6,12 @@
6
6
  // { hex_encode, hex_decode } :: import "std/encoding/hex";
7
7
  //
8
8
  // s := hex_encode(data); // "deadbeef"
9
- // b := hex_decode("deadbeef").unwrap();
9
+ // b := hex_decode("deadbeef");
10
10
 
11
11
  open import "../string";
12
12
  { ArrayList } :: import "../collections/array_list";
13
+ { Error, AnyError, Exception } :: import "../error";
14
+ { ToString } :: import "../fmt";
13
15
 
14
16
  // ============================================================================
15
17
  // Error type
@@ -20,6 +22,17 @@ EncodingError :: enum(
20
22
  OddLength
21
23
  );
22
24
 
25
+ impl(EncodingError, ToString(
26
+ to_string : (self ->
27
+ match(self,
28
+ .InvalidChar(ch) => `encoding error: invalid character ${ch}`,
29
+ .OddLength => `encoding error: odd length`
30
+ )
31
+ )
32
+ ));
33
+
34
+ impl(EncodingError, Error());
35
+
23
36
  export EncodingError;
24
37
 
25
38
  // ============================================================================
@@ -52,41 +65,31 @@ export hex_encode;
52
65
  // Decoding
53
66
  // ============================================================================
54
67
 
55
- _hex_nibble :: (fn(c: u8) -> Result(u8, EncodingError))(
68
+ _hex_nibble :: (fn(c: u8, using(exn : Exception)) -> u8)(
56
69
  cond(
57
- ((c >= u8(48)) && (c <= u8(57))) => .Ok((c - u8(48))), // '0'-'9'
58
- ((c >= u8(97)) && (c <= u8(102))) => .Ok(((c - u8(97)) + u8(10))), // 'a'-'f'
59
- ((c >= u8(65)) && (c <= u8(70))) => .Ok(((c - u8(65)) + u8(10))), // 'A'-'F'
60
- true => .Err(.InvalidChar(c))
70
+ ((c >= u8(48)) && (c <= u8(57))) => (c - u8(48)), // '0'-'9'
71
+ ((c >= u8(97)) && (c <= u8(102))) => ((c - u8(97)) + u8(10)), // 'a'-'f'
72
+ ((c >= u8(65)) && (c <= u8(70))) => ((c - u8(65)) + u8(10)), // 'A'-'F'
73
+ true => exn.throw(dyn EncodingError.InvalidChar(c))
61
74
  )
62
75
  );
63
76
 
64
77
  // Decode a hexadecimal string into bytes.
65
- hex_decode :: (fn(s: str) -> Result(ArrayList(u8), EncodingError))({
78
+ hex_decode :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))({
66
79
  cond(
67
80
  (((s.len() % usize(2)) != usize(0))) => {
68
- return .Err(.OddLength);
81
+ exn.throw(dyn EncodingError.OddLength);
69
82
  },
70
83
  true => ()
71
84
  );
72
85
  out := ArrayList(u8).with_capacity((s.len() / usize(2)));
73
86
  i := usize(0);
74
87
  while (i < s.len()), (i = (i + usize(2))), {
75
- hi_r := _hex_nibble(s.bytes(i));
76
- lo_r := _hex_nibble(s.bytes((i + usize(1))));
77
- match(hi_r,
78
- .Err(e) => { return .Err(e); },
79
- .Ok(hi) => {
80
- match(lo_r,
81
- .Err(e) => { return .Err(e); },
82
- .Ok(lo) => {
83
- out.push(((hi << u8(4)) | lo));
84
- }
85
- );
86
- }
87
- );
88
+ hi := _hex_nibble(s.bytes(i));
89
+ lo := _hex_nibble(s.bytes((i + usize(1))));
90
+ out.push(((hi << u8(4)) | lo));
88
91
  };
89
- .Ok(out)
92
+ out
90
93
  });
91
94
 
92
95
  export hex_decode;
@@ -4,13 +4,17 @@
4
4
  //
5
5
  // Example:
6
6
  // { json_parse, json_stringify, JsonValue } :: import "std/encoding/json";
7
+ // { Exception } :: import "std/error";
7
8
  //
8
- // v := json_parse(`{"x": 1}`).unwrap();
9
+ // given(exn) := Exception(throw : ((err) -> { escape (); }));
10
+ // v := json_parse(`{"x": 1}`);
9
11
  // println(json_stringify(v));
10
12
 
11
13
  open import "../string";
12
14
  { ArrayList } :: import "../collections/array_list";
13
15
  { snprintf } :: import "../libc/stdio";
16
+ { Error, AnyError, Exception } :: import "../error";
17
+ { ToString } :: import "../fmt";
14
18
 
15
19
  // ============================================================================
16
20
  // JsonError
@@ -25,6 +29,21 @@ JsonError :: enum(
25
29
  Other(msg: String)
26
30
  );
27
31
 
32
+ impl(JsonError, ToString(
33
+ to_string : (self ->
34
+ match(self,
35
+ .UnexpectedChar(ch, pos) => `unexpected character at position ${pos}`,
36
+ .UnexpectedEnd => `unexpected end of input`,
37
+ .InvalidNumber => `invalid number`,
38
+ .InvalidEscape => `invalid escape sequence`,
39
+ .InvalidUnicode => `invalid unicode`,
40
+ .Other(msg) => `JSON error: ${msg}`
41
+ )
42
+ )
43
+ ));
44
+
45
+ impl(JsonError, Error());
46
+
28
47
  export JsonError;
29
48
 
30
49
  // ============================================================================
@@ -449,9 +468,12 @@ _parse_value :: (fn(p: _Parser) -> Result(JsonValue, JsonError))({
449
468
  // Public API
450
469
  // ============================================================================
451
470
 
452
- json_parse :: (fn(s: str) -> Result(JsonValue, JsonError))({
471
+ json_parse :: (fn(s: str, using(exn : Exception)) -> JsonValue)({
453
472
  p := _Parser.new(s);
454
- _parse_value(p)
473
+ match(_parse_value(p),
474
+ .Ok(v) => v,
475
+ .Err(e) => exn.throw(dyn e)
476
+ )
455
477
  });
456
478
 
457
479
  export json_parse;
@@ -6,11 +6,12 @@
6
6
  // { utf8_to_utf16, utf16_to_utf8 } :: import "std/encoding/utf16";
7
7
  //
8
8
  // words := utf8_to_utf16("hello");
9
- // s := utf16_to_utf8(words).unwrap();
9
+ // s := utf16_to_utf8(words);
10
10
 
11
11
  open import "../string";
12
12
  { ArrayList } :: import "../collections/array_list";
13
13
  { EncodingError } :: import "./hex";
14
+ { Error, AnyError, Exception } :: import "../error";
14
15
 
15
16
  // ============================================================================
16
17
  // UTF-8 → UTF-16
@@ -63,7 +64,7 @@ export utf8_to_utf16;
63
64
  // UTF-16 → UTF-8
64
65
  // ============================================================================
65
66
 
66
- utf16_to_utf8 :: (fn(data: ArrayList(u16)) -> Result(String, EncodingError))({
67
+ utf16_to_utf8 :: (fn(data: ArrayList(u16), using(exn : Exception)) -> String)({
67
68
  out := ArrayList(u8).new();
68
69
  i := usize(0);
69
70
  while (i < data.len()), {
@@ -73,14 +74,14 @@ utf16_to_utf8 :: (fn(data: ArrayList(u16)) -> Result(String, EncodingError))({
73
74
  ((w >= u32(0xD800)) && (w <= u32(0xDBFF))) => {
74
75
  cond(
75
76
  ((i + usize(1)) >= data.len()) => {
76
- return .Err(.InvalidChar(u8(0)));
77
+ exn.throw(dyn EncodingError.InvalidChar(u8(0)));
77
78
  },
78
79
  true => ()
79
80
  );
80
81
  w2 := u32(data.get((i + usize(1))).unwrap());
81
82
  cond(
82
83
  ((w2 < u32(0xDC00)) || (w2 > u32(0xDFFF))) => {
83
- return .Err(.InvalidChar(u8(0)));
84
+ exn.throw(dyn EncodingError.InvalidChar(u8(0)));
84
85
  },
85
86
  true => ()
86
87
  );
@@ -109,7 +110,7 @@ utf16_to_utf8 :: (fn(data: ArrayList(u16)) -> Result(String, EncodingError))({
109
110
  }
110
111
  );
111
112
  };
112
- .Ok(String.from_bytes(out))
113
+ String.from_bytes(out)
113
114
  });
114
115
 
115
116
  export utf16_to_utf8;
package/std/error.yo CHANGED
@@ -2,33 +2,49 @@
2
2
  //
3
3
  // Provides a standard Error trait for typed error propagation.
4
4
  // All error types in the standard library should implement this trait.
5
- //
6
- // Example:
7
- // { Error } :: import "std/error";
8
- //
9
- // MyError :: enum(
10
- // NotFound(path: String),
11
- // PermissionDenied
12
- // );
13
- // impl(MyError, Error(
14
- // message : (self -> {
15
- // return match(self,
16
- // .NotFound(path) => `file not found: ${path}`,
17
- // .PermissionDenied => String.from("permission denied")
18
- // );
19
- // })
20
- // ));
21
-
22
5
  open import "./string";
6
+ open import "./fmt";
23
7
 
24
8
  // ============================================================================
25
9
  // Error trait
26
10
  // ============================================================================
27
11
 
28
- Error :: (fn(comptime(T) : Type) -> comptime(Type))
29
- trait(
30
- message :: (fn(self: *(T)) -> String)
31
- )
32
- ;
12
+ Error :: trait(
13
+ (source : (fn(self: *(Self)) -> Option(Dyn(SelfTrait)))) ?= ((self) -> .None),
14
+
15
+ where(Self <: ToString)
16
+ );
17
+ export Error;
18
+
19
+ AnyError :: Dyn(Error);
20
+ export AnyError;
21
+
22
+ // ============================================================================
23
+ // Error implementations for standard types
24
+ // ============================================================================
25
+
26
+ impl(String, Error());
27
+
28
+ /// === Exception ===
29
+ // This is a non-resumable exception handling.
30
+ //
31
+ // Example (function that may throw):
32
+ //
33
+ // safe_div :: (fn(x: i32, y: i32, using(exn : Exception)) -> i32)(
34
+ // cond(
35
+ // (y == i32(0)) => exn.throw(dyn `division by zero`)),
36
+ // true => (x / y)
37
+ // )
38
+ // );
39
+ Exception :: module(
40
+ throw : (fn(forall(ResumeType : Type), error : AnyError) -> ResumeType)
41
+ );
42
+ export Exception;
33
43
 
34
- export Error;
44
+
45
+ ResumableException :: (fn(comptime(ResumeType) : Type) -> comptime(Module))(
46
+ module(
47
+ throw : (fn(error : AnyError) -> ResumeType)
48
+ )
49
+ );
50
+ export ResumableException;