@shd101wyy/yo 0.1.25 → 0.1.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 (194) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +4 -4
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +40 -40
  3. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  4. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +30 -26
  5. package/.github/skills/yo-project-workflow/SKILL.md +6 -3
  6. package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +34 -11
  7. package/.github/skills/yo-syntax/SKILL.md +7 -6
  8. package/.github/skills/yo-syntax/syntax-cheatsheet.md +78 -60
  9. package/.github/skills/yo-wasm-integration/wasm-integration-cheatsheet.md +3 -3
  10. package/README.md +10 -8
  11. package/out/cjs/index.cjs +583 -567
  12. package/out/cjs/yo-cli.cjs +664 -632
  13. package/out/cjs/yo-lsp.cjs +510 -485
  14. package/out/esm/index.mjs +538 -522
  15. package/out/types/src/codegen/codegen-c.d.ts +2 -2
  16. package/out/types/src/codegen/functions/collection.d.ts +2 -2
  17. package/out/types/src/codegen/functions/context.d.ts +3 -2
  18. package/out/types/src/codegen/types/collection.d.ts +2 -2
  19. package/out/types/src/codegen/utils/index.d.ts +3 -1
  20. package/out/types/src/doc/builder.d.ts +2 -2
  21. package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
  22. package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
  23. package/out/types/src/evaluator/context.d.ts +8 -9
  24. package/out/types/src/evaluator/index.d.ts +3 -3
  25. package/out/types/src/evaluator/types/record.d.ts +14 -0
  26. package/out/types/src/evaluator/types/validation.d.ts +2 -2
  27. package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
  28. package/out/types/src/evaluator/values/impl.d.ts +1 -1
  29. package/out/types/src/expr.d.ts +1 -4
  30. package/out/types/src/formatter.d.ts +11 -0
  31. package/out/types/src/function-value.d.ts +1 -1
  32. package/out/types/src/lsp/document-manager.d.ts +1 -1
  33. package/out/types/src/lsp/formatting.d.ts +2 -0
  34. package/out/types/src/module-manager.d.ts +3 -3
  35. package/out/types/src/tests/formatter.test.d.ts +1 -0
  36. package/out/types/src/types/creators.d.ts +3 -4
  37. package/out/types/src/types/definitions.d.ts +8 -19
  38. package/out/types/src/types/guards.d.ts +3 -3
  39. package/out/types/src/types/tags.d.ts +0 -1
  40. package/out/types/src/types/utils.d.ts +1 -1
  41. package/out/types/src/value-tag.d.ts +0 -1
  42. package/out/types/src/value.d.ts +6 -13
  43. package/out/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +1 -1
  45. package/std/alg/hash.yo +13 -21
  46. package/std/allocator.yo +25 -40
  47. package/std/async.yo +3 -7
  48. package/std/build.yo +105 -151
  49. package/std/cli/arg_parser.yo +184 -169
  50. package/std/collections/array_list.yo +350 -314
  51. package/std/collections/btree_map.yo +142 -131
  52. package/std/collections/deque.yo +132 -128
  53. package/std/collections/hash_map.yo +542 -566
  54. package/std/collections/hash_set.yo +623 -687
  55. package/std/collections/linked_list.yo +275 -293
  56. package/std/collections/ordered_map.yo +113 -85
  57. package/std/collections/priority_queue.yo +73 -73
  58. package/std/crypto/md5.yo +191 -95
  59. package/std/crypto/random.yo +56 -64
  60. package/std/crypto/sha256.yo +151 -107
  61. package/std/encoding/base64.yo +87 -81
  62. package/std/encoding/hex.yo +43 -50
  63. package/std/encoding/html.yo +56 -81
  64. package/std/encoding/html_char_utils.yo +7 -13
  65. package/std/encoding/html_entities.yo +2248 -2253
  66. package/std/encoding/json.yo +316 -224
  67. package/std/encoding/punycode.yo +86 -116
  68. package/std/encoding/toml.yo +67 -66
  69. package/std/encoding/utf16.yo +37 -44
  70. package/std/env.yo +62 -91
  71. package/std/error.yo +12 -20
  72. package/std/fmt/display.yo +5 -9
  73. package/std/fmt/index.yo +8 -14
  74. package/std/fmt/to_string.yo +330 -315
  75. package/std/fmt/writer.yo +58 -87
  76. package/std/fs/dir.yo +83 -102
  77. package/std/fs/file.yo +147 -180
  78. package/std/fs/metadata.yo +45 -78
  79. package/std/fs/temp.yo +55 -65
  80. package/std/fs/types.yo +27 -40
  81. package/std/fs/walker.yo +53 -68
  82. package/std/gc.yo +5 -8
  83. package/std/glob.yo +30 -43
  84. package/std/http/client.yo +107 -120
  85. package/std/http/http.yo +106 -96
  86. package/std/http/index.yo +4 -6
  87. package/std/imm/list.yo +88 -93
  88. package/std/imm/map.yo +528 -464
  89. package/std/imm/set.yo +52 -57
  90. package/std/imm/sorted_map.yo +340 -286
  91. package/std/imm/sorted_set.yo +57 -63
  92. package/std/imm/string.yo +404 -345
  93. package/std/imm/vec.yo +173 -181
  94. package/std/io/reader.yo +3 -6
  95. package/std/io/writer.yo +4 -8
  96. package/std/libc/assert.yo +5 -9
  97. package/std/libc/ctype.yo +32 -22
  98. package/std/libc/dirent.yo +26 -25
  99. package/std/libc/errno.yo +164 -90
  100. package/std/libc/fcntl.yo +52 -45
  101. package/std/libc/float.yo +66 -44
  102. package/std/libc/limits.yo +42 -33
  103. package/std/libc/math.yo +53 -82
  104. package/std/libc/signal.yo +72 -47
  105. package/std/libc/stdatomic.yo +217 -188
  106. package/std/libc/stdint.yo +5 -29
  107. package/std/libc/stdio.yo +5 -29
  108. package/std/libc/stdlib.yo +32 -39
  109. package/std/libc/string.yo +5 -23
  110. package/std/libc/sys/stat.yo +58 -56
  111. package/std/libc/time.yo +5 -19
  112. package/std/libc/unistd.yo +5 -20
  113. package/std/libc/wctype.yo +6 -9
  114. package/std/libc/windows.yo +26 -30
  115. package/std/log.yo +41 -55
  116. package/std/net/addr.yo +102 -97
  117. package/std/net/dns.yo +27 -28
  118. package/std/net/errors.yo +50 -49
  119. package/std/net/tcp.yo +113 -124
  120. package/std/net/udp.yo +55 -66
  121. package/std/os/env.yo +35 -33
  122. package/std/os/signal.yo +15 -25
  123. package/std/path.yo +276 -311
  124. package/std/prelude.yo +6316 -4333
  125. package/std/process/command.yo +87 -103
  126. package/std/process/index.yo +12 -31
  127. package/std/regex/compiler.yo +196 -95
  128. package/std/regex/flags.yo +58 -39
  129. package/std/regex/index.yo +157 -173
  130. package/std/regex/match.yo +20 -31
  131. package/std/regex/node.yo +134 -152
  132. package/std/regex/parser.yo +283 -259
  133. package/std/regex/unicode.yo +172 -202
  134. package/std/regex/vm.yo +155 -171
  135. package/std/string/index.yo +5 -7
  136. package/std/string/rune.yo +45 -55
  137. package/std/string/string.yo +937 -964
  138. package/std/string/string_builder.yo +94 -104
  139. package/std/string/unicode.yo +46 -64
  140. package/std/sync/channel.yo +72 -73
  141. package/std/sync/cond.yo +31 -36
  142. package/std/sync/mutex.yo +30 -32
  143. package/std/sync/once.yo +13 -16
  144. package/std/sync/rwlock.yo +26 -31
  145. package/std/sync/waitgroup.yo +20 -25
  146. package/std/sys/advise.yo +16 -24
  147. package/std/sys/bufio/buf_reader.yo +77 -93
  148. package/std/sys/bufio/buf_writer.yo +52 -65
  149. package/std/sys/clock.yo +4 -9
  150. package/std/sys/constants.yo +77 -61
  151. package/std/sys/copy.yo +4 -10
  152. package/std/sys/dir.yo +26 -43
  153. package/std/sys/dns.yo +41 -61
  154. package/std/sys/errors.yo +95 -103
  155. package/std/sys/events.yo +45 -57
  156. package/std/sys/externs.yo +319 -267
  157. package/std/sys/fallocate.yo +7 -11
  158. package/std/sys/fcntl.yo +14 -22
  159. package/std/sys/file.yo +26 -40
  160. package/std/sys/future.yo +5 -8
  161. package/std/sys/iov.yo +12 -25
  162. package/std/sys/lock.yo +12 -13
  163. package/std/sys/mmap.yo +38 -43
  164. package/std/sys/path.yo +3 -8
  165. package/std/sys/perm.yo +7 -21
  166. package/std/sys/pipe.yo +5 -12
  167. package/std/sys/process.yo +23 -29
  168. package/std/sys/seek.yo +10 -12
  169. package/std/sys/signal.yo +7 -13
  170. package/std/sys/signals.yo +52 -35
  171. package/std/sys/socket.yo +63 -58
  172. package/std/sys/socketpair.yo +3 -6
  173. package/std/sys/sockinfo.yo +11 -20
  174. package/std/sys/statfs.yo +11 -34
  175. package/std/sys/statx.yo +25 -52
  176. package/std/sys/sysinfo.yo +15 -20
  177. package/std/sys/tcp.yo +62 -92
  178. package/std/sys/temp.yo +5 -9
  179. package/std/sys/time.yo +5 -15
  180. package/std/sys/timer.yo +6 -11
  181. package/std/sys/tty.yo +10 -18
  182. package/std/sys/udp.yo +22 -39
  183. package/std/sys/umask.yo +3 -6
  184. package/std/sys/unix.yo +33 -52
  185. package/std/testing/bench.yo +49 -52
  186. package/std/thread.yo +10 -15
  187. package/std/time/datetime.yo +105 -89
  188. package/std/time/duration.yo +43 -56
  189. package/std/time/instant.yo +13 -18
  190. package/std/time/sleep.yo +5 -9
  191. package/std/url/index.yo +184 -209
  192. package/std/worker.yo +6 -10
  193. package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
  194. package/out/types/src/evaluator/types/module.d.ts +0 -19
package/std/url/index.yo CHANGED
@@ -1,137 +1,129 @@
1
1
  //! URL parsing and formatting per RFC 3986 (simplified).
2
-
3
- open import "../string";
4
- { ArrayList } :: import "../collections/array_list";
5
- { ToString } :: import "../fmt";
6
- { Error, AnyError, Exception } :: import "../error";
7
-
2
+ open(import("../string"));
3
+ { ArrayList } :: import("../collections/array_list");
4
+ { ToString } :: import("../fmt");
5
+ { Error, AnyError, Exception } :: import("../error");
8
6
  /// Errors that can occur during URL parsing.
9
7
  UrlError :: enum(
10
8
  EmptyInput,
11
9
  MissingScheme,
12
10
  InvalidPort,
13
- InvalidCharacter(pos: usize),
14
- Other(msg: String)
11
+ InvalidCharacter(pos : usize),
12
+ Other(msg : String)
15
13
  );
16
-
17
- impl(UrlError, ToString(
18
- to_string : (self ->
19
- match(self,
20
- .EmptyInput => `URL error: empty input`,
21
- .MissingScheme => `URL error: missing scheme`,
22
- .InvalidPort => `URL error: invalid port`,
23
- .InvalidCharacter(pos) => `URL error: invalid character at position ${pos}`,
24
- .Other(msg) => `URL error: ${msg}`
14
+ impl(
15
+ UrlError,
16
+ ToString(
17
+ to_string : (
18
+ self ->
19
+ match(
20
+ self,
21
+ .EmptyInput => `URL error: empty input`,
22
+ .MissingScheme => `URL error: missing scheme`,
23
+ .InvalidPort => `URL error: invalid port`,
24
+ .InvalidCharacter(pos) => `URL error: invalid character at position ${pos}`,
25
+ .Other(msg) => `URL error: ${msg}`
26
+ )
25
27
  )
26
28
  )
27
- ));
28
-
29
+ );
29
30
  impl(UrlError, Error());
30
-
31
31
  // ============================================================================
32
32
  // Url
33
33
  // ============================================================================
34
-
35
34
  // ASCII constants for URL parsing
36
- _COLON :: u8(58); // ':'
37
- _SLASH :: u8(47); // '/'
38
- _QUESTION :: u8(63); // '?'
39
- _HASH :: u8(35); // '#'
40
- _AT :: u8(64); // '@'
41
- _LBRACKET :: u8(91); // '['
42
- _RBRACKET :: u8(93); // ']'
43
- _ZERO :: u8(48); // '0'
44
- _NINE :: u8(57); // '9'
45
- _LOWER_A :: u8(97); // 'a'
46
- _LOWER_Z :: u8(122); // 'z'
47
- _UPPER_A :: u8(65); // 'A'
48
- _UPPER_Z :: u8(90); // 'Z'
49
- _PLUS :: u8(43); // '+'
50
- _MINUS :: u8(45); // '-'
51
- _DOT :: u8(46); // '.'
52
-
35
+ _COLON :: u8(58); // ':'
36
+ _SLASH :: u8(47); // '/'
37
+ _QUESTION :: u8(63); // '?'
38
+ _HASH :: u8(35); // '#'
39
+ _AT :: u8(64); // '@'
40
+ _LBRACKET :: u8(91); // '['
41
+ _RBRACKET :: u8(93); // ']'
42
+ _ZERO :: u8(48); // '0'
43
+ _NINE :: u8(57); // '9'
44
+ _LOWER_A :: u8(97); // 'a'
45
+ _LOWER_Z :: u8(122); // 'z'
46
+ _UPPER_A :: u8(65); // 'A'
47
+ _UPPER_Z :: u8(90); // 'Z'
48
+ _PLUS :: u8(43); // '+'
49
+ _MINUS :: u8(45); // '-'
50
+ _DOT :: u8(46); // '.'
53
51
  // ============================================================================
54
52
  // Helper: parse port number from bytes
55
53
  // ============================================================================
56
-
57
- _parse_port :: (fn(s: str, start: usize, end: usize, using(exn : Exception)) -> u16)({
54
+ _parse_port :: (fn(s : str, start : usize, end : usize, using(exn : Exception)) -> u16)({
58
55
  cond(
59
56
  (start >= end) => {
60
- exn.throw(dyn UrlError.InvalidPort);
57
+ exn.throw(dyn(UrlError.InvalidPort));
61
58
  },
62
59
  true => ()
63
60
  );
64
61
  val := u32(0);
65
62
  i := start;
66
- while runtime((i < end)), {
63
+ while(runtime(i < end), {
67
64
  ch := s.bytes(i);
68
65
  cond(
69
66
  ((ch >= _ZERO) && (ch <= _NINE)) => {
70
- val = ((val * u32(10)) + u32((ch - _ZERO)));
67
+ val = ((val * u32(10)) + u32(ch - _ZERO));
71
68
  cond(
72
69
  (val > u32(65535)) => {
73
- exn.throw(dyn UrlError.InvalidPort);
70
+ exn.throw(dyn(UrlError.InvalidPort));
74
71
  },
75
72
  true => ()
76
73
  );
77
74
  },
78
75
  true => {
79
- exn.throw(dyn UrlError.InvalidPort);
76
+ exn.throw(dyn(UrlError.InvalidPort));
80
77
  }
81
78
  );
82
79
  i = (i + usize(1));
83
- };
80
+ });
84
81
  u16(val)
85
82
  });
86
-
87
83
  /// Parsed URL with scheme, host, port, path, query, and fragment components.
88
84
  Url :: object(
89
- _scheme : String,
90
- _host : Option(String),
91
- _port : Option(u16),
92
- _path : String,
93
- _query : Option(String),
85
+ _scheme : String,
86
+ _host : Option(String),
87
+ _port : Option(u16),
88
+ _path : String,
89
+ _query : Option(String),
94
90
  _fragment : Option(String),
95
91
  _userinfo : Option(String)
96
92
  );
97
-
98
- impl(Url,
93
+ impl(
94
+ Url,
99
95
  // Parse a URL string.
100
96
  // Supports: scheme://[userinfo@]host[:port]/path[?query][#fragment]
101
97
  // Also supports scheme:path (opaque URIs like mailto:user@example.com)
102
- parse : (fn(s: str, using(exn : Exception)) -> Url)({
98
+ parse : (fn(s : str, using(exn : Exception)) -> Url)({
103
99
  cond(
104
100
  (s.len() == usize(0)) => {
105
- exn.throw(dyn UrlError.EmptyInput);
101
+ exn.throw(dyn(UrlError.EmptyInput));
106
102
  },
107
103
  true => ()
108
104
  );
109
-
110
105
  pos := usize(0);
111
106
  src_len := s.len();
112
-
113
107
  // --- Parse scheme ---
114
108
  // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
115
109
  scheme_end := usize(0);
116
110
  cond(
117
111
  (src_len == usize(0)) => {
118
- exn.throw(dyn UrlError.MissingScheme);
112
+ exn.throw(dyn(UrlError.MissingScheme));
119
113
  },
120
114
  true => ()
121
115
  );
122
-
123
116
  // First char must be a letter
124
117
  first := s.bytes(usize(0));
125
118
  cond(
126
- ((((first >= _LOWER_A) && (first <= _LOWER_Z)) || ((first >= _UPPER_A) && (first <= _UPPER_Z)))) => (),
119
+ (((first >= _LOWER_A) && (first <= _LOWER_Z)) || ((first >= _UPPER_A) && (first <= _UPPER_Z))) => (),
127
120
  true => {
128
- exn.throw(dyn UrlError.MissingScheme);
121
+ exn.throw(dyn(UrlError.MissingScheme));
129
122
  }
130
123
  );
131
-
132
124
  i := usize(1);
133
125
  found_colon := false;
134
- while runtime((i < src_len)), {
126
+ while(runtime(i < src_len), {
135
127
  ch := s.bytes(i);
136
128
  cond(
137
129
  (ch == _COLON) => {
@@ -141,47 +133,43 @@ impl(Url,
141
133
  },
142
134
  (((((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)))) => (),
143
135
  true => {
144
- exn.throw(dyn UrlError.MissingScheme);
136
+ exn.throw(dyn(UrlError.MissingScheme));
145
137
  }
146
138
  );
147
139
  i = (i + usize(1));
148
- };
140
+ });
149
141
  cond(
150
142
  (!(found_colon)) => {
151
- exn.throw(dyn UrlError.MissingScheme);
143
+ exn.throw(dyn(UrlError.MissingScheme));
152
144
  },
153
145
  true => ()
154
146
  );
155
-
156
147
  scheme_bytes := ArrayList(u8).new();
157
148
  j := usize(0);
158
- while runtime((j < scheme_end)), {
149
+ while(runtime(j < scheme_end), {
159
150
  b := s.bytes(j);
160
151
  // Normalize to lowercase
161
152
  cond(
162
- ((b >= _UPPER_A) && (b <= _UPPER_Z)) => scheme_bytes.push((b + u8(32))),
153
+ ((b >= _UPPER_A) && (b <= _UPPER_Z)) => scheme_bytes.push(b + u8(32)),
163
154
  true => scheme_bytes.push(b)
164
155
  );
165
156
  j = (j + usize(1));
166
- };
157
+ });
167
158
  scheme := String.from_bytes(scheme_bytes);
168
- pos = (scheme_end + usize(1)); // skip ':'
169
-
159
+ pos = (scheme_end + usize(1)); // skip ':'
170
160
  // --- Check for authority (// prefix) ---
171
161
  has_authority := false;
172
162
  cond(
173
- (((pos + usize(1)) < src_len) && ((s.bytes(pos) == _SLASH) && (s.bytes((pos + usize(1))) == _SLASH))) => {
163
+ (((pos + usize(1)) < src_len) && ((s.bytes(pos) == _SLASH) && (s.bytes(pos + usize(1)) == _SLASH))) => {
174
164
  has_authority = true;
175
- pos = (pos + usize(2)); // skip '//'
165
+ pos = (pos + usize(2)); // skip '//'
176
166
  },
177
167
  true => ()
178
168
  );
179
-
180
- (host : Option(String)) = .None;
181
- (port : Option(u16)) = .None;
182
- (userinfo : Option(String)) = .None;
169
+ (host : Option(String)) =.None;
170
+ (port : Option(u16)) =.None;
171
+ (userinfo : Option(String)) =.None;
183
172
  path_str := String.new();
184
-
185
173
  cond(
186
174
  has_authority => {
187
175
  // --- Parse authority: [userinfo@]host[:port] ---
@@ -189,7 +177,7 @@ impl(Url,
189
177
  auth_start := pos;
190
178
  auth_end := src_len;
191
179
  k := pos;
192
- while runtime((k < src_len)), {
180
+ while(runtime(k < src_len), {
193
181
  ch := s.bytes(k);
194
182
  cond(
195
183
  (((ch == _SLASH) || (ch == _QUESTION)) || (ch == _HASH)) => {
@@ -199,100 +187,97 @@ impl(Url,
199
187
  true => ()
200
188
  );
201
189
  k = (k + usize(1));
202
- };
203
-
190
+ });
204
191
  // Check for userinfo (look for '@')
205
192
  host_start := auth_start;
206
193
  m := auth_start;
207
- while runtime((m < auth_end)), {
194
+ while(runtime(m < auth_end), {
208
195
  cond(
209
196
  (s.bytes(m) == _AT) => {
210
197
  // Everything before '@' is userinfo
211
198
  ui_bytes := ArrayList(u8).new();
212
199
  n := auth_start;
213
- while runtime((n < m)), {
200
+ while(runtime(n < m), {
214
201
  ui_bytes.push(s.bytes(n));
215
202
  n = (n + usize(1));
216
- };
217
- userinfo = .Some(String.from_bytes(ui_bytes));
203
+ });
204
+ userinfo =.Some(String.from_bytes(ui_bytes));
218
205
  host_start = (m + usize(1));
219
206
  break;
220
207
  },
221
208
  true => ()
222
209
  );
223
210
  m = (m + usize(1));
224
- };
225
-
211
+ });
226
212
  // Parse host[:port]
227
213
  // Check for IPv6 literal [...]
228
214
  cond(
229
215
  ((host_start < auth_end) && (s.bytes(host_start) == _LBRACKET)) => {
230
216
  // IPv6: find closing ']'
231
217
  bracket_end := (host_start + usize(1));
232
- while runtime(((bracket_end < auth_end) && (s.bytes(bracket_end) != _RBRACKET))), {
218
+ while(runtime((bracket_end < auth_end) && (s.bytes(bracket_end) != _RBRACKET)), {
233
219
  bracket_end = (bracket_end + usize(1));
234
- };
235
-
220
+ });
236
221
  host_bytes := ArrayList(u8).new();
237
222
  hh := host_start;
238
- while runtime((hh <= bracket_end)), {
223
+ while(runtime(hh <= bracket_end), {
239
224
  cond(
240
- (hh < auth_end) => { host_bytes.push(s.bytes(hh)); },
225
+ (hh < auth_end) => {
226
+ host_bytes.push(s.bytes(hh));
227
+ },
241
228
  true => ()
242
229
  );
243
230
  hh = (hh + usize(1));
244
- };
245
- host = .Some(String.from_bytes(host_bytes));
246
-
231
+ });
232
+ host =.Some(String.from_bytes(host_bytes));
247
233
  // Check for port after ']:'
248
234
  after_bracket := (bracket_end + usize(1));
249
235
  cond(
250
236
  ((after_bracket < auth_end) && (s.bytes(after_bracket) == _COLON)) => {
251
- port = .Some(_parse_port(s, (after_bracket + usize(1)), auth_end));
237
+ port =.Some(_parse_port(s, after_bracket + usize(1), auth_end));
252
238
  },
253
239
  true => ()
254
240
  );
255
241
  },
256
242
  true => {
257
243
  // Regular host — find ':' for port
258
- (colon_pos : Option(usize)) = .None;
244
+ (colon_pos : Option(usize)) =.None;
259
245
  cp := host_start;
260
- while runtime((cp < auth_end)), {
246
+ while(runtime(cp < auth_end), {
261
247
  cond(
262
248
  (s.bytes(cp) == _COLON) => {
263
- colon_pos = .Some(cp);
249
+ colon_pos =.Some(cp);
264
250
  break;
265
251
  },
266
252
  true => ()
267
253
  );
268
254
  cp = (cp + usize(1));
269
- };
270
-
271
- match(colon_pos,
255
+ });
256
+ match(
257
+ colon_pos,
272
258
  .Some(cp_val) => {
273
259
  // host is before colon, port is after
274
260
  host_b := ArrayList(u8).new();
275
261
  hh2 := host_start;
276
- while runtime((hh2 < cp_val)), {
262
+ while(runtime(hh2 < cp_val), {
277
263
  host_b.push(s.bytes(hh2));
278
264
  hh2 = (hh2 + usize(1));
279
- };
280
- host = .Some(String.from_bytes(host_b));
281
-
282
- port = .Some(_parse_port(s, (cp_val + usize(1)), auth_end));
265
+ });
266
+ host =.Some(String.from_bytes(host_b));
267
+ port =.Some(_parse_port(s, cp_val + usize(1), auth_end));
283
268
  },
284
269
  .None => {
285
270
  // No port, entire range is host
286
271
  host_b := ArrayList(u8).new();
287
272
  hh3 := host_start;
288
- while runtime((hh3 < auth_end)), {
273
+ while(runtime(hh3 < auth_end), {
289
274
  host_b.push(s.bytes(hh3));
290
275
  hh3 = (hh3 + usize(1));
291
- };
276
+ });
292
277
  h := String.from_bytes(host_b);
293
278
  cond(
294
279
  (!(h.is_empty())) => {
295
- host = .Some(h);
280
+ host =.Some(h);
296
281
  },
297
282
  true => ()
298
283
  );
@@ -300,17 +285,15 @@ impl(Url,
300
285
  );
301
286
  }
302
287
  );
303
-
304
288
  pos = auth_end;
305
289
  },
306
290
  true => ()
307
291
  );
308
-
309
292
  // --- Parse path ---
310
293
  path_start := pos;
311
294
  path_end := src_len;
312
295
  pp := pos;
313
- while runtime((pp < src_len)), {
296
+ while(runtime(pp < src_len), {
314
297
  ch := s.bytes(pp);
315
298
  cond(
316
299
  ((ch == _QUESTION) || (ch == _HASH)) => {
@@ -320,31 +303,29 @@ impl(Url,
320
303
  true => ()
321
304
  );
322
305
  pp = (pp + usize(1));
323
- };
324
-
306
+ });
325
307
  cond(
326
308
  (path_start < path_end) => {
327
309
  path_bytes := ArrayList(u8).new();
328
310
  pb := path_start;
329
- while runtime((pb < path_end)), {
311
+ while(runtime(pb < path_end), {
330
312
  path_bytes.push(s.bytes(pb));
331
313
  pb = (pb + usize(1));
332
- };
314
+ });
333
315
  path_str = String.from_bytes(path_bytes);
334
316
  },
335
317
  true => ()
336
318
  );
337
319
  pos = path_end;
338
-
339
320
  // --- Parse query ---
340
- (query : Option(String)) = .None;
321
+ (query : Option(String)) =.None;
341
322
  cond(
342
323
  ((pos < src_len) && (s.bytes(pos) == _QUESTION)) => {
343
- pos = (pos + usize(1)); // skip '?'
324
+ pos = (pos + usize(1)); // skip '?'
344
325
  q_start := pos;
345
326
  q_end := src_len;
346
327
  qq := pos;
347
- while runtime((qq < src_len)), {
328
+ while(runtime(qq < src_len), {
348
329
  cond(
349
330
  (s.bytes(qq) == _HASH) => {
350
331
  q_end = qq;
@@ -353,152 +334,146 @@ impl(Url,
353
334
  true => ()
354
335
  );
355
336
  qq = (qq + usize(1));
356
- };
337
+ });
357
338
  q_bytes := ArrayList(u8).new();
358
339
  qb := q_start;
359
- while runtime((qb < q_end)), {
340
+ while(runtime(qb < q_end), {
360
341
  q_bytes.push(s.bytes(qb));
361
342
  qb = (qb + usize(1));
362
- };
363
- query = .Some(String.from_bytes(q_bytes));
343
+ });
344
+ query =.Some(String.from_bytes(q_bytes));
364
345
  pos = q_end;
365
346
  },
366
347
  true => ()
367
348
  );
368
-
369
349
  // --- Parse fragment ---
370
- (fragment : Option(String)) = .None;
350
+ (fragment : Option(String)) =.None;
371
351
  cond(
372
352
  ((pos < src_len) && (s.bytes(pos) == _HASH)) => {
373
- pos = (pos + usize(1)); // skip '#'
353
+ pos = (pos + usize(1)); // skip '#'
374
354
  f_bytes := ArrayList(u8).new();
375
355
  fb := pos;
376
- while runtime((fb < src_len)), {
356
+ while(runtime(fb < src_len), {
377
357
  f_bytes.push(s.bytes(fb));
378
358
  fb = (fb + usize(1));
379
- };
380
- fragment = .Some(String.from_bytes(f_bytes));
359
+ });
360
+ fragment =.Some(String.from_bytes(f_bytes));
381
361
  },
382
362
  true => ()
383
363
  );
384
-
385
364
  // Ensure authority-based URLs have a path starting with "/" or empty
386
365
  cond(
387
366
  (has_authority && ((!(path_str.is_empty())) && (path_str.as_bytes().get(usize(0)).unwrap() != _SLASH))) => {
388
- exn.throw(dyn UrlError.Other(`authority path must start with '/'`));
367
+ exn.throw(dyn(UrlError.Other(`authority path must start with '/'`)));
389
368
  },
390
369
  true => ()
391
370
  );
392
-
393
371
  Self(
394
- _scheme: scheme,
395
- _host: host,
396
- _port: port,
397
- _path: path_str,
398
- _query: query,
399
- _fragment: fragment,
400
- _userinfo: userinfo
372
+ _scheme : scheme,
373
+ _host : host,
374
+ _port : port,
375
+ _path : path_str,
376
+ _query : query,
377
+ _fragment : fragment,
378
+ _userinfo : userinfo
401
379
  )
402
380
  }),
403
-
404
381
  // --- Accessors ---
405
-
406
- scheme : (fn(self: Self) -> String)(
382
+ scheme : (fn(self : Self) -> String)(
407
383
  self._scheme
408
384
  ),
409
-
410
- host : (fn(self: Self) -> Option(String))(
385
+ host : (fn(self : Self) -> Option(String))(
411
386
  self._host
412
387
  ),
413
-
414
- port : (fn(self: Self) -> Option(u16))(
388
+ port : (fn(self : Self) -> Option(u16))(
415
389
  self._port
416
390
  ),
417
-
418
- path : (fn(self: Self) -> String)(
391
+ path : (fn(self : Self) -> String)(
419
392
  self._path
420
393
  ),
421
-
422
- query : (fn(self: Self) -> Option(String))(
394
+ query : (fn(self : Self) -> Option(String))(
423
395
  self._query
424
396
  ),
425
-
426
- fragment : (fn(self: Self) -> Option(String))(
397
+ fragment : (fn(self : Self) -> Option(String))(
427
398
  self._fragment
428
399
  ),
429
-
430
- userinfo : (fn(self: Self) -> Option(String))(
400
+ userinfo : (fn(self : Self) -> Option(String))(
431
401
  self._userinfo
432
402
  ),
433
-
434
403
  // Returns the host:port as a String, or just host if no port
435
- host_port : (fn(self: Self) -> Option(String))(
436
- match(self._host,
437
- .None => .None,
404
+ host_port : (fn(self : Self) -> Option(String))(
405
+ match(
406
+ self._host,
407
+ .None =>.None,
438
408
  .Some(h) =>
439
- match(self._port,
440
- .None => .Some(h),
441
- .Some(p) => .Some(`${h}:${p}`)
409
+ match(
410
+ self._port,
411
+ .None =>.Some(h),
412
+ .Some(p) =>.Some(`${h}:${p}`)
442
413
  )
443
414
  )
444
415
  ),
445
-
446
416
  // Returns scheme + "://" + host_port (the origin)
447
- origin : (fn(self: Self) -> String)(
448
- match(self._host,
417
+ origin : (fn(self : Self) -> String)(
418
+ match(
419
+ self._host,
449
420
  .None => self._scheme,
450
421
  .Some(h) =>
451
- match(self._port,
422
+ match(
423
+ self._port,
452
424
  .None => `${self._scheme}://${h}`,
453
425
  .Some(p) => `${self._scheme}://${h}:${p}`
454
426
  )
455
427
  )
456
428
  )
457
429
  );
458
-
459
430
  // Reconstruct the URL as a String
460
- impl(Url, ToString(
461
- to_string : (self -> {
462
- result := `${self._scheme}:`;
463
-
464
- match(self._host,
465
- .Some(h) => {
466
- result = result.concat(`//`);
467
- match(self._userinfo,
468
- .Some(ui) => {
469
- result = result.concat(ui).concat(`@`);
431
+ impl(
432
+ Url,
433
+ ToString(
434
+ to_string : (
435
+ self -> {
436
+ result := `${self._scheme}:`;
437
+ match(
438
+ self._host,
439
+ .Some(h) => {
440
+ result = result.concat(`//`);
441
+ match(
442
+ self._userinfo,
443
+ .Some(ui) => {
444
+ result = result.concat(ui).concat(`@`);
445
+ },
446
+ .None => ()
447
+ );
448
+ result = result.concat(h);
449
+ match(
450
+ self._port,
451
+ .Some(p) => {
452
+ result = result.concat(`:${p}`);
453
+ },
454
+ .None => ()
455
+ );
470
456
  },
471
457
  .None => ()
472
458
  );
473
- result = result.concat(h);
474
- match(self._port,
475
- .Some(p) => {
476
- result = result.concat(`:${p}`);
459
+ result = result.concat(self._path);
460
+ match(
461
+ self._query,
462
+ .Some(q) => {
463
+ result = result.concat(`?`).concat(q);
477
464
  },
478
465
  .None => ()
479
466
  );
480
- },
481
- .None => ()
482
- );
483
-
484
- result = result.concat(self._path);
485
-
486
- match(self._query,
487
- .Some(q) => {
488
- result = result.concat(`?`).concat(q);
489
- },
490
- .None => ()
491
- );
492
-
493
- match(self._fragment,
494
- .Some(f) => {
495
- result = result.concat(`#`).concat(f);
496
- },
497
- .None => ()
498
- );
499
-
500
- result
501
- })
502
- ));
503
-
504
- export Url, UrlError;
467
+ match(
468
+ self._fragment,
469
+ .Some(f) => {
470
+ result = result.concat(`#`).concat(f);
471
+ },
472
+ .None => ()
473
+ );
474
+ result
475
+ }
476
+ )
477
+ )
478
+ );
479
+ export(Url, UrlError);