@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/prelude.yo CHANGED
@@ -3822,11 +3822,23 @@ impl(FutureState, Eq(FutureState)(
3822
3822
  ));
3823
3823
  export FutureState;
3824
3824
 
3825
+ // JoinHandle(T) — a handle to a spawned async task.
3826
+ // Wraps a raw pointer to the spawned future's state machine.
3827
+ // Generic over T, the return type of the spawned task.
3828
+ // NOTE: __future uses *(T) (not *(void)) so that the type parameter T is visible
3829
+ // in the struct fields for generic impl matching to extract T from JoinHandle(T).
3830
+ JoinHandle :: (fn(comptime(T) : Type) -> comptime(Type))(
3831
+ struct(
3832
+ __future : *(T)
3833
+ )
3834
+ );
3835
+ export JoinHandle;
3836
+
3825
3837
  IO :: module(
3826
3838
  async : (fn(forall(T : Type, ...(E)), action : Impl(Fn(using(...(E))) -> T)) -> Impl(Future(T, ...(E)))),
3827
3839
  await : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> T),
3828
3840
  state : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E)))) -> FutureState),
3829
- spawn : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> unit)
3841
+ spawn : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> JoinHandle(T))
3830
3842
  );
3831
3843
  export IO;
3832
3844
 
@@ -3834,7 +3846,7 @@ extern "Yo",
3834
3846
  __yo_io_async : (fn(forall(T : Type, ...(E)), action : Impl(Fn(using(...(E))) -> T)) -> Impl(Future(T, ...(E)))),
3835
3847
  __yo_io_await : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> T),
3836
3848
  __yo_io_state : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E)))) -> FutureState),
3837
- __yo_io_spawn : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> unit)
3849
+ __yo_io_spawn : (fn(forall(T : Type, ...(E)), fut : Impl(Future(T, ...(E))), using(...(E))) -> JoinHandle(T))
3838
3850
  ;
3839
3851
 
3840
3852
  // It's intended not to use `given` here.
@@ -3848,18 +3860,11 @@ __yo_builtin_io :: IO(
3848
3860
  );
3849
3861
  export __yo_builtin_io;
3850
3862
 
3851
- /// === Exception ===
3852
- // Example (function that may throw):
3853
- //
3854
- // safe_div :: (fn(x: i32, y: i32, using(exception : Exception(String))) -> i32)(
3855
- // cond(
3856
- // (y == i32(0)) => exception.throw(`division by zero`)),
3857
- // true => (x / y)
3858
- // )
3859
- // );
3860
- Exception :: (fn(comptime(ErrorType) : Type) -> comptime(Module))(
3861
- module(
3862
- throw : (fn(forall(ResumeType : Type), error : ErrorType) -> ResumeType)
3863
- )
3863
+ // JoinHandle methods — defined after IO so using(io : IO) resolves
3864
+ extern "Yo",
3865
+ __yo_join_handle_await : (fn(forall(T : Type), self : JoinHandle(T), using(io : IO)) -> Option(T))
3866
+ ;
3867
+
3868
+ impl(forall(T : Type), JoinHandle(T),
3869
+ await : __yo_join_handle_await
3864
3870
  );
3865
- export Exception;
package/std/sys/errors.yo CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  { String } :: import "../string";
6
6
  { ToString } :: import "../fmt";
7
+ { Error, Exception } :: import "../error";
7
8
  {
8
9
  ENOENT, EPERM, EACCES, EEXIST, ENOTDIR, EISDIR, ENOTEMPTY, EPIPE,
9
10
  EAGAIN, EWOULDBLOCK, EINVAL, EINTR, EMFILE, ENFILE, EFBIG, ENOSPC,
@@ -107,42 +108,53 @@ impl(IOError,
107
108
  impl(IOError, ToString(
108
109
  to_string : (self -> {
109
110
  s := match(self,
110
- .NotFound => String.from_cstr("file or directory not found").unwrap(),
111
- .PermissionDenied => String.from_cstr("permission denied").unwrap(),
112
- .AlreadyExists => String.from_cstr("file or directory already exists").unwrap(),
113
- .NotADirectory => String.from_cstr("not a directory").unwrap(),
114
- .IsADirectory => String.from_cstr("is a directory").unwrap(),
115
- .DirectoryNotEmpty => String.from_cstr("directory not empty").unwrap(),
116
- .BrokenPipe => String.from_cstr("broken pipe").unwrap(),
117
- .WouldBlock => String.from_cstr("operation would block").unwrap(),
118
- .InvalidInput => String.from_cstr("invalid input").unwrap(),
119
- .Interrupted => String.from_cstr("operation interrupted").unwrap(),
120
- .TooManyOpenFiles => String.from_cstr("too many open files").unwrap(),
121
- .FileTooLarge => String.from_cstr("file too large").unwrap(),
122
- .NoSpace => String.from_cstr("no space left on device").unwrap(),
123
- .ReadOnlyFilesystem => String.from_cstr("read-only filesystem").unwrap(),
124
- .CrossDeviceLink => String.from_cstr("cross-device link").unwrap(),
125
- .TooManyLinks => String.from_cstr("too many links").unwrap(),
126
- .NameTooLong => String.from_cstr("name too long").unwrap(),
127
- .NotSupported => String.from_cstr("operation not supported").unwrap(),
128
- .TimedOut => String.from_cstr("operation timed out").unwrap(),
129
- .Busy => String.from_cstr("resource busy").unwrap(),
130
- .BadFileDescriptor => String.from_cstr("bad file descriptor").unwrap(),
131
- .IOError => String.from_cstr("I/O error").unwrap(),
132
- .ConnectionRefused => String.from_cstr("connection refused").unwrap(),
133
- .ConnectionReset => String.from_cstr("connection reset by peer").unwrap(),
134
- .ConnectionAborted => String.from_cstr("connection aborted").unwrap(),
135
- .NotConnected => String.from_cstr("socket not connected").unwrap(),
136
- .AddressInUse => String.from_cstr("address already in use").unwrap(),
137
- .AddressNotAvailable => String.from_cstr("address not available").unwrap(),
138
- .NetworkUnreachable => String.from_cstr("network unreachable").unwrap(),
139
- .HostUnreachable => String.from_cstr("host unreachable").unwrap(),
140
- .NetworkDown => String.from_cstr("network is down").unwrap(),
141
- .AlreadyConnected => String.from_cstr("socket already connected").unwrap(),
142
- .Other(errno) => String.from_cstr("unknown I/O error").unwrap()
111
+ .NotFound => String.from("file or directory not found"),
112
+ .PermissionDenied => String.from("permission denied"),
113
+ .AlreadyExists => String.from("file or directory already exists"),
114
+ .NotADirectory => String.from("not a directory"),
115
+ .IsADirectory => String.from("is a directory"),
116
+ .DirectoryNotEmpty => String.from("directory not empty"),
117
+ .BrokenPipe => String.from("broken pipe"),
118
+ .WouldBlock => String.from("operation would block"),
119
+ .InvalidInput => String.from("invalid input"),
120
+ .Interrupted => String.from("operation interrupted"),
121
+ .TooManyOpenFiles => String.from("too many open files"),
122
+ .FileTooLarge => String.from("file too large"),
123
+ .NoSpace => String.from("no space left on device"),
124
+ .ReadOnlyFilesystem => String.from("read-only filesystem"),
125
+ .CrossDeviceLink => String.from("cross-device link"),
126
+ .TooManyLinks => String.from("too many links"),
127
+ .NameTooLong => String.from("name too long"),
128
+ .NotSupported => String.from("operation not supported"),
129
+ .TimedOut => String.from("operation timed out"),
130
+ .Busy => String.from("resource busy"),
131
+ .BadFileDescriptor => String.from("bad file descriptor"),
132
+ .IOError => String.from("I/O error"),
133
+ .ConnectionRefused => String.from("connection refused"),
134
+ .ConnectionReset => String.from("connection reset by peer"),
135
+ .ConnectionAborted => String.from("connection aborted"),
136
+ .NotConnected => String.from("socket not connected"),
137
+ .AddressInUse => String.from("address already in use"),
138
+ .AddressNotAvailable => String.from("address not available"),
139
+ .NetworkUnreachable => String.from("network unreachable"),
140
+ .HostUnreachable => String.from("host unreachable"),
141
+ .NetworkDown => String.from("network is down"),
142
+ .AlreadyConnected => String.from("socket already connected"),
143
+ .Other(errno) => String.from("unknown I/O error")
143
144
  );
144
145
  return s;
145
146
  })
146
147
  ));
148
+ impl(IOError, Error());
149
+
150
+ impl(IOError,
151
+ // Check a raw result code, throwing on error via Exception effect.
152
+ check : (fn(result: i32, using(exn : Exception)) -> i32)(
153
+ cond(
154
+ (result >= i32(0)) => result,
155
+ true => exn.throw(dyn Self.from_errno(i32(0) - result))
156
+ )
157
+ )
158
+ );
147
159
 
148
160
  export IOError;
package/std/url/url.yo CHANGED
@@ -17,6 +17,7 @@
17
17
  open import "../string";
18
18
  { ArrayList } :: import "../collections/array_list";
19
19
  { ToString } :: import "../fmt";
20
+ { Error, AnyError, Exception } :: import "../error";
20
21
 
21
22
  // ============================================================================
22
23
  // UrlError
@@ -42,6 +43,8 @@ impl(UrlError, ToString(
42
43
  )
43
44
  ));
44
45
 
46
+ impl(UrlError, Error());
47
+
45
48
  // ============================================================================
46
49
  // Url
47
50
  // ============================================================================
@@ -68,10 +71,10 @@ _DOT :: u8(46); // '.'
68
71
  // Helper: parse port number from bytes
69
72
  // ============================================================================
70
73
 
71
- _parse_port :: (fn(s: str, start: usize, end: usize) -> Result(u16, UrlError))({
74
+ _parse_port :: (fn(s: str, start: usize, end: usize, using(exn : Exception)) -> u16)({
72
75
  cond(
73
76
  (start >= end) => {
74
- return .Err(.InvalidPort);
77
+ exn.throw(dyn UrlError.InvalidPort);
75
78
  },
76
79
  true => ()
77
80
  );
@@ -84,18 +87,18 @@ _parse_port :: (fn(s: str, start: usize, end: usize) -> Result(u16, UrlError))({
84
87
  val = ((val * u32(10)) + u32((ch - _ZERO)));
85
88
  cond(
86
89
  (val > u32(65535)) => {
87
- return .Err(.InvalidPort);
90
+ exn.throw(dyn UrlError.InvalidPort);
88
91
  },
89
92
  true => ()
90
93
  );
91
94
  },
92
95
  true => {
93
- return .Err(.InvalidPort);
96
+ exn.throw(dyn UrlError.InvalidPort);
94
97
  }
95
98
  );
96
99
  i = (i + usize(1));
97
100
  };
98
- .Ok(u16(val))
101
+ u16(val)
99
102
  });
100
103
 
101
104
  Url :: object(
@@ -112,10 +115,10 @@ impl(Url,
112
115
  // Parse a URL string.
113
116
  // Supports: scheme://[userinfo@]host[:port]/path[?query][#fragment]
114
117
  // Also supports scheme:path (opaque URIs like mailto:user@example.com)
115
- parse : (fn(s: str) -> Result(Url, UrlError))({
118
+ parse : (fn(s: str, using(exn : Exception)) -> Url)({
116
119
  cond(
117
120
  (s.len() == usize(0)) => {
118
- return .Err(.EmptyInput);
121
+ exn.throw(dyn UrlError.EmptyInput);
119
122
  },
120
123
  true => ()
121
124
  );
@@ -128,7 +131,7 @@ impl(Url,
128
131
  scheme_end := usize(0);
129
132
  cond(
130
133
  (src_len == usize(0)) => {
131
- return .Err(.MissingScheme);
134
+ exn.throw(dyn UrlError.MissingScheme);
132
135
  },
133
136
  true => ()
134
137
  );
@@ -138,7 +141,7 @@ impl(Url,
138
141
  cond(
139
142
  ((((first >= _LOWER_A) && (first <= _LOWER_Z)) || ((first >= _UPPER_A) && (first <= _UPPER_Z)))) => (),
140
143
  true => {
141
- return .Err(.MissingScheme);
144
+ exn.throw(dyn UrlError.MissingScheme);
142
145
  }
143
146
  );
144
147
 
@@ -154,14 +157,14 @@ impl(Url,
154
157
  },
155
158
  (((((first >= _LOWER_A) && (first <= _LOWER_Z)) || ((first >= _UPPER_A) && (first <= _UPPER_Z))) || (((ch >= _LOWER_A) && (ch <= _LOWER_Z)) || ((ch >= _UPPER_A) && (ch <= _UPPER_Z)))) || ((((ch >= _ZERO) && (ch <= _NINE)) || (ch == _PLUS)) || ((ch == _MINUS) || (ch == _DOT)))) => (),
156
159
  true => {
157
- return .Err(.MissingScheme);
160
+ exn.throw(dyn UrlError.MissingScheme);
158
161
  }
159
162
  );
160
163
  i = (i + usize(1));
161
164
  };
162
165
  cond(
163
166
  (!(found_colon)) => {
164
- return .Err(.MissingScheme);
167
+ exn.throw(dyn UrlError.MissingScheme);
165
168
  },
166
169
  true => ()
167
170
  );
@@ -261,15 +264,7 @@ impl(Url,
261
264
  after_bracket := (bracket_end + usize(1));
262
265
  cond(
263
266
  ((after_bracket < auth_end) && (s.bytes(after_bracket) == _COLON)) => {
264
- port_result := _parse_port(s, (after_bracket + usize(1)), auth_end);
265
- cond(
266
- port_result.is_err() => {
267
- return .Err(.InvalidPort);
268
- },
269
- true => {
270
- port = .Some(port_result.unwrap());
271
- }
272
- );
267
+ port = .Some(_parse_port(s, (after_bracket + usize(1)), auth_end));
273
268
  },
274
269
  true => ()
275
270
  );
@@ -300,15 +295,7 @@ impl(Url,
300
295
  };
301
296
  host = .Some(String.from_bytes(host_b));
302
297
 
303
- port_result := _parse_port(s, (cp_val + usize(1)), auth_end);
304
- cond(
305
- port_result.is_err() => {
306
- return .Err(.InvalidPort);
307
- },
308
- true => {
309
- port = .Some(port_result.unwrap());
310
- }
311
- );
298
+ port = .Some(_parse_port(s, (cp_val + usize(1)), auth_end));
312
299
  },
313
300
  .None => {
314
301
  // No port, entire range is host
@@ -414,12 +401,12 @@ impl(Url,
414
401
  // Ensure authority-based URLs have a path starting with "/" or empty
415
402
  cond(
416
403
  (has_authority && ((!(path_str.is_empty())) && (path_str.as_bytes().get(usize(0)).unwrap() != _SLASH))) => {
417
- return .Err(.Other(`authority path must start with '/'`));
404
+ exn.throw(dyn UrlError.Other(`authority path must start with '/'`));
418
405
  },
419
406
  true => ()
420
407
  );
421
408
 
422
- .Ok(Self(
409
+ Self(
423
410
  _scheme: scheme,
424
411
  _host: host,
425
412
  _port: port,
@@ -427,7 +414,7 @@ impl(Url,
427
414
  _query: query,
428
415
  _fragment: fragment,
429
416
  _userinfo: userinfo
430
- ))
417
+ )
431
418
  }),
432
419
 
433
420
  // --- Accessors ---
@@ -1,34 +0,0 @@
1
- import type { EffectAnalysisResult } from "../../evaluator/effects/effect-analysis-types";
2
- import { type Expr } from "../../expr";
3
- import type { FunctionValue } from "../../function-value";
4
- import type { FunctionType, Type } from "../../types/definitions";
5
- import type { FunctionGenerationContext } from "../functions/context";
6
- export declare function handlerBodyContainsExplicitReturn(expr: Expr): boolean;
7
- export interface EffectSmTypeInfo {
8
- yieldTypeCNames: string[];
9
- resumeTypeCName: string;
10
- }
11
- export interface EffectStateMachineInfo {
12
- structName: string;
13
- resumeFunctionName: string;
14
- analysis: EffectAnalysisResult;
15
- functionType: FunctionType;
16
- returnTypeCName: string;
17
- yieldTypeCNames: string[];
18
- resumeTypeCName: string;
19
- effectInfos?: EffectSmTypeInfo[];
20
- isClosure?: boolean;
21
- closureCaptureTypeCName?: string;
22
- closureCapturedVarNames?: Set<string>;
23
- }
24
- export declare function generateEffectStateMachineStruct(info: EffectStateMachineInfo, context: FunctionGenerationContext): void;
25
- export declare function generateEffectResumeFunctionDeclaration(info: EffectStateMachineInfo, context: FunctionGenerationContext): void;
26
- export declare function generateEffectResumeFunction(bodyExpr: Expr, info: EffectStateMachineInfo, context: FunctionGenerationContext, functionValue?: FunctionValue): void;
27
- export declare function generateEffectCallSite(info: EffectStateMachineInfo, argCodes: string[], functionType: FunctionType, handlerBody: Expr, handlerType: FunctionType, handlerHasResume: boolean, callerReturnType: Type | undefined, tempVar: string | undefined, indent: string, context: FunctionGenerationContext, closureContextCode?: string): string;
28
- export interface EffectCallSiteHandler {
29
- handlerBody: Expr;
30
- handlerType: FunctionType;
31
- hasResume: boolean;
32
- effectIndex: number;
33
- }
34
- export declare function generateMultiEffectCallSite(info: EffectStateMachineInfo, argCodes: string[], functionType: FunctionType, handlers: EffectCallSiteHandler[], tempVar: string | undefined, indent: string, context: FunctionGenerationContext): string;