@shd101wyy/yo 0.1.26 → 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 (167) hide show
  1. package/.github/skills/yo-async-effects/SKILL.md +4 -4
  2. package/.github/skills/yo-async-effects/async-effects-recipes.md +34 -34
  3. package/.github/skills/yo-core-patterns/SKILL.md +1 -1
  4. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +26 -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 +73 -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 +456 -438
  12. package/out/cjs/yo-cli.cjs +576 -543
  13. package/out/cjs/yo-lsp.cjs +559 -532
  14. package/out/esm/index.mjs +281 -263
  15. package/out/types/src/formatter.d.ts +11 -0
  16. package/out/types/src/lsp/formatting.d.ts +2 -0
  17. package/out/types/src/tests/formatter.test.d.ts +1 -0
  18. package/out/types/tsconfig.tsbuildinfo +1 -1
  19. package/package.json +1 -1
  20. package/std/alg/hash.yo +13 -21
  21. package/std/allocator.yo +25 -40
  22. package/std/async.yo +3 -7
  23. package/std/build.yo +105 -151
  24. package/std/cli/arg_parser.yo +184 -169
  25. package/std/collections/array_list.yo +350 -314
  26. package/std/collections/btree_map.yo +142 -131
  27. package/std/collections/deque.yo +132 -128
  28. package/std/collections/hash_map.yo +542 -566
  29. package/std/collections/hash_set.yo +623 -687
  30. package/std/collections/linked_list.yo +275 -293
  31. package/std/collections/ordered_map.yo +113 -85
  32. package/std/collections/priority_queue.yo +73 -73
  33. package/std/crypto/md5.yo +191 -95
  34. package/std/crypto/random.yo +56 -64
  35. package/std/crypto/sha256.yo +151 -107
  36. package/std/encoding/base64.yo +87 -81
  37. package/std/encoding/hex.yo +43 -50
  38. package/std/encoding/html.yo +56 -81
  39. package/std/encoding/html_char_utils.yo +7 -13
  40. package/std/encoding/html_entities.yo +2248 -2253
  41. package/std/encoding/json.yo +316 -224
  42. package/std/encoding/punycode.yo +86 -116
  43. package/std/encoding/toml.yo +67 -66
  44. package/std/encoding/utf16.yo +37 -44
  45. package/std/env.yo +62 -91
  46. package/std/error.yo +7 -15
  47. package/std/fmt/display.yo +5 -9
  48. package/std/fmt/index.yo +8 -14
  49. package/std/fmt/to_string.yo +330 -315
  50. package/std/fmt/writer.yo +58 -87
  51. package/std/fs/dir.yo +83 -102
  52. package/std/fs/file.yo +147 -180
  53. package/std/fs/metadata.yo +45 -78
  54. package/std/fs/temp.yo +55 -65
  55. package/std/fs/types.yo +27 -40
  56. package/std/fs/walker.yo +53 -68
  57. package/std/gc.yo +5 -8
  58. package/std/glob.yo +30 -43
  59. package/std/http/client.yo +107 -120
  60. package/std/http/http.yo +106 -96
  61. package/std/http/index.yo +4 -6
  62. package/std/imm/list.yo +88 -93
  63. package/std/imm/map.yo +528 -464
  64. package/std/imm/set.yo +52 -57
  65. package/std/imm/sorted_map.yo +340 -286
  66. package/std/imm/sorted_set.yo +57 -63
  67. package/std/imm/string.yo +404 -345
  68. package/std/imm/vec.yo +173 -181
  69. package/std/io/reader.yo +3 -6
  70. package/std/io/writer.yo +4 -8
  71. package/std/libc/assert.yo +5 -9
  72. package/std/libc/ctype.yo +32 -22
  73. package/std/libc/dirent.yo +26 -25
  74. package/std/libc/errno.yo +164 -90
  75. package/std/libc/fcntl.yo +52 -45
  76. package/std/libc/float.yo +66 -44
  77. package/std/libc/limits.yo +42 -33
  78. package/std/libc/math.yo +53 -82
  79. package/std/libc/signal.yo +72 -47
  80. package/std/libc/stdatomic.yo +217 -188
  81. package/std/libc/stdint.yo +5 -29
  82. package/std/libc/stdio.yo +5 -29
  83. package/std/libc/stdlib.yo +32 -39
  84. package/std/libc/string.yo +5 -23
  85. package/std/libc/sys/stat.yo +58 -56
  86. package/std/libc/time.yo +5 -19
  87. package/std/libc/unistd.yo +5 -20
  88. package/std/libc/wctype.yo +6 -9
  89. package/std/libc/windows.yo +26 -30
  90. package/std/log.yo +41 -55
  91. package/std/net/addr.yo +102 -97
  92. package/std/net/dns.yo +27 -28
  93. package/std/net/errors.yo +50 -49
  94. package/std/net/tcp.yo +113 -124
  95. package/std/net/udp.yo +55 -66
  96. package/std/os/env.yo +35 -33
  97. package/std/os/signal.yo +15 -25
  98. package/std/path.yo +276 -311
  99. package/std/prelude.yo +6304 -4315
  100. package/std/process/command.yo +87 -103
  101. package/std/process/index.yo +12 -31
  102. package/std/regex/compiler.yo +196 -95
  103. package/std/regex/flags.yo +58 -39
  104. package/std/regex/index.yo +157 -173
  105. package/std/regex/match.yo +20 -31
  106. package/std/regex/node.yo +134 -152
  107. package/std/regex/parser.yo +283 -259
  108. package/std/regex/unicode.yo +172 -202
  109. package/std/regex/vm.yo +155 -171
  110. package/std/string/index.yo +5 -7
  111. package/std/string/rune.yo +45 -55
  112. package/std/string/string.yo +937 -964
  113. package/std/string/string_builder.yo +94 -104
  114. package/std/string/unicode.yo +46 -64
  115. package/std/sync/channel.yo +72 -73
  116. package/std/sync/cond.yo +31 -36
  117. package/std/sync/mutex.yo +30 -32
  118. package/std/sync/once.yo +13 -16
  119. package/std/sync/rwlock.yo +26 -31
  120. package/std/sync/waitgroup.yo +20 -25
  121. package/std/sys/advise.yo +16 -24
  122. package/std/sys/bufio/buf_reader.yo +77 -93
  123. package/std/sys/bufio/buf_writer.yo +52 -65
  124. package/std/sys/clock.yo +4 -9
  125. package/std/sys/constants.yo +77 -61
  126. package/std/sys/copy.yo +4 -10
  127. package/std/sys/dir.yo +26 -43
  128. package/std/sys/dns.yo +41 -61
  129. package/std/sys/errors.yo +95 -103
  130. package/std/sys/events.yo +45 -57
  131. package/std/sys/externs.yo +319 -267
  132. package/std/sys/fallocate.yo +7 -11
  133. package/std/sys/fcntl.yo +14 -22
  134. package/std/sys/file.yo +26 -40
  135. package/std/sys/future.yo +5 -8
  136. package/std/sys/iov.yo +12 -25
  137. package/std/sys/lock.yo +12 -13
  138. package/std/sys/mmap.yo +38 -43
  139. package/std/sys/path.yo +3 -8
  140. package/std/sys/perm.yo +7 -21
  141. package/std/sys/pipe.yo +5 -12
  142. package/std/sys/process.yo +23 -29
  143. package/std/sys/seek.yo +10 -12
  144. package/std/sys/signal.yo +7 -13
  145. package/std/sys/signals.yo +52 -35
  146. package/std/sys/socket.yo +63 -58
  147. package/std/sys/socketpair.yo +3 -6
  148. package/std/sys/sockinfo.yo +11 -20
  149. package/std/sys/statfs.yo +11 -34
  150. package/std/sys/statx.yo +25 -52
  151. package/std/sys/sysinfo.yo +15 -20
  152. package/std/sys/tcp.yo +62 -92
  153. package/std/sys/temp.yo +5 -9
  154. package/std/sys/time.yo +5 -15
  155. package/std/sys/timer.yo +6 -11
  156. package/std/sys/tty.yo +10 -18
  157. package/std/sys/udp.yo +22 -39
  158. package/std/sys/umask.yo +3 -6
  159. package/std/sys/unix.yo +33 -52
  160. package/std/testing/bench.yo +49 -52
  161. package/std/thread.yo +10 -15
  162. package/std/time/datetime.yo +105 -89
  163. package/std/time/duration.yo +43 -56
  164. package/std/time/instant.yo +13 -18
  165. package/std/time/sleep.yo +5 -9
  166. package/std/url/index.yo +184 -209
  167. package/std/worker.yo +6 -10
@@ -1,123 +1,118 @@
1
1
  //! Immutable UTF-8 string type with comprehensive operations.
2
-
3
- { ArrayList } :: import "../collections/array_list.yo";
4
- { rune } :: import "./rune.yo";
5
- { memcpy, memcmp, strlen } :: import "../libc/string.yo";
6
-
2
+ { ArrayList } :: import("../collections/array_list.yo");
3
+ { rune } :: import("./rune.yo");
4
+ { memcpy, memcmp, strlen } :: import("../libc/string.yo");
7
5
  /// String operation error variants.
8
6
  StringError :: enum(
9
7
  /// The input bytes are not valid UTF-8.
10
8
  InvalidUtf8,
11
9
  /// The index is out of bounds for the string's byte length.
12
- IndexOutOfBounds(index: usize, length: usize)
10
+ IndexOutOfBounds(index : usize, length : usize)
13
11
  );
14
-
15
12
  /// Immutable UTF-8 encoded string.
16
13
  /// All operations return new strings; mutable operations require a pointer to self.
17
14
  /// Empty strings use zero allocation (represented as `Option.None` internally).
18
15
  String :: newtype(
19
- _bytes: Option(ArrayList(u8))
16
+ _bytes : Option(ArrayList(u8))
20
17
  );
21
-
22
- impl(String,
18
+ impl(
19
+ String,
23
20
  /**
24
- * Create a new empty string (zero allocation)
25
- */
21
+ * Create a new empty string (zero allocation)
22
+ */
26
23
  new : (fn() -> Self)(
27
- Self(_bytes: .None)
24
+ Self(_bytes :.None)
28
25
  ),
29
-
30
26
  /**
31
- * Create a new empty string with pre-allocated capacity for the given number of bytes.
32
- * The string starts empty but can hold `capacity` bytes without reallocating.
33
- */
34
- with_capacity : (fn(capacity: usize) -> Self)(
27
+ * Create a new empty string with pre-allocated capacity for the given number of bytes.
28
+ * The string starts empty but can hold `capacity` bytes without reallocating.
29
+ */
30
+ with_capacity : (fn(capacity : usize) -> Self)(
35
31
  cond(
36
- (capacity == usize(0)) => Self(_bytes: .None),
37
- true => Self(_bytes: .Some(ArrayList(u8).with_capacity(capacity)))
32
+ (capacity == usize(0)) => Self(_bytes :.None),
33
+ true => Self(_bytes :.Some(ArrayList(u8).with_capacity(capacity)))
38
34
  )
39
35
  ),
40
-
41
36
  /**
42
- * Create a string from raw bytes (assumes valid UTF-8)
43
- * No validation is performed - the caller must ensure bytes are valid UTF-8
44
- */
45
- from_bytes : (fn(bytes: ArrayList(u8)) -> Self)(
37
+ * Create a string from raw bytes (assumes valid UTF-8)
38
+ * No validation is performed - the caller must ensure bytes are valid UTF-8
39
+ */
40
+ from_bytes : (fn(bytes : ArrayList(u8)) -> Self)(
46
41
  cond(
47
- (bytes.len() == usize(0)) => Self(_bytes: .None),
48
- true => Self(_bytes: .Some(bytes))
42
+ (bytes.len() == usize(0)) => Self(_bytes :.None),
43
+ true => Self(_bytes :.Some(bytes))
49
44
  )
50
45
  ),
51
-
52
46
  /**
53
- * Create a string from a slice of bytes str
54
- * The slice is a fat pointer containing data pointer and length
55
- * Example: String.from(slice) where slice is str
56
- */
57
- from : (fn(slice: str) -> Self)({
47
+ * Create a string from a slice of bytes str
48
+ * The slice is a fat pointer containing data pointer and length
49
+ * Example: String.from(slice) where slice is str
50
+ */
51
+ from : (fn(slice : str) -> Self)({
58
52
  slen := slice.len();
59
- if((slen == usize(0)), {
60
- return Self(_bytes: .None);
53
+ if(slen == usize(0), {
54
+ return(Self(_bytes :.None));
61
55
  });
62
56
  bytes := ArrayList(u8).with_capacity(slen);
63
57
  bytes.extend_from_ptr(slice.ptr(), slen);
64
- return Self(_bytes: .Some(bytes));
58
+ return(Self(_bytes :.Some(bytes)));
65
59
  }),
66
-
67
60
  /**
68
- * Create a string from a C null-terminated string *(u8)
69
- * Copies bytes until it finds a null byte (0)
70
- * Example: String.from_cstr(c_string_ptr)
71
- *
72
- * Note: We manually search for the null terminator by iterating
73
- */
74
- from_cstr : (fn(cstr: *(u8)) -> Result(Self, StringError))({
61
+ * Create a string from a C null-terminated string *(u8)
62
+ * Copies bytes until it finds a null byte (0)
63
+ * Example: String.from_cstr(c_string_ptr)
64
+ *
65
+ * Note: We manually search for the null terminator by iterating
66
+ */
67
+ from_cstr : (fn(cstr : *(u8)) -> Result(Self, StringError))({
75
68
  len := strlen((*(char))(cstr));
76
- if((len == usize(0)), {
77
- return .Ok(Self(_bytes: .None));
69
+ if(len == usize(0), {
70
+ return(.Ok(Self(_bytes :.None)));
78
71
  });
79
72
  bytes := ArrayList(u8).with_capacity(len);
80
73
  bytes.extend_from_ptr(cstr, len);
81
- return .Ok(Self(_bytes: .Some(bytes)));
74
+ return(.Ok(Self(_bytes :.Some(bytes))));
82
75
  }),
83
-
84
76
  /// Convert the string to a null-terminated C string.
85
77
  /// Returns an `ArrayList(u8)` with the string bytes followed by a `\0`.
86
- to_cstr : (fn(self: Self) -> ArrayList(u8))({
87
- (bytes_len : usize) = match(self._bytes,
78
+ to_cstr : (fn(self : Self) -> ArrayList(u8))({
79
+ (bytes_len : usize) = match(
80
+ self._bytes,
88
81
  .Some(b) => b.len(),
89
82
  .None => usize(0)
90
83
  );
91
- bytes_with_null := ArrayList(u8).with_capacity((bytes_len + usize(1)));
92
- match(self._bytes,
93
- .Some(b) => match(b.ptr(),
84
+ bytes_with_null := ArrayList(u8).with_capacity(bytes_len + usize(1));
85
+ match(
86
+ self._bytes,
87
+ .Some(b) => match(
88
+ b.ptr(),
94
89
  .Some(src) => bytes_with_null.extend_from_ptr(src, bytes_len),
95
90
  .None => ()
96
91
  ),
97
92
  .None => ()
98
93
  );
99
94
  bytes_with_null.push(u8(0));
100
- return bytes_with_null;
95
+ return(bytes_with_null);
101
96
  }),
102
-
103
97
  /**
104
- * Get the length of the string in Unicode characters (runes)
105
- * For "你好世界", this returns 4
106
- */
107
- len : (fn(self: Self) -> usize)({
98
+ * Get the length of the string in Unicode characters (runes)
99
+ * For "你好世界", this returns 4
100
+ */
101
+ len : (fn(self : Self) -> usize)({
108
102
  (inner : Option(ArrayList(u8))) = self._bytes;
109
- match(inner,
110
- .None => { return usize(0); },
103
+ match(
104
+ inner,
105
+ .None => {
106
+ return(usize(0));
107
+ },
111
108
  .Some(al) => {
112
109
  count := usize(0);
113
110
  byte_index := usize(0);
114
111
  total_bytes := al.len();
115
-
116
- while ((byte_index < total_bytes)),
117
- (byte_index = (byte_index + usize(1))),
118
- {
112
+ while(byte_index < total_bytes, byte_index = (byte_index + usize(1)), {
119
113
  byte_opt := al.get(byte_index);
120
- match(byte_opt,
114
+ match(
115
+ byte_opt,
121
116
  .Some(byte) => {
122
117
  cond(
123
118
  ((byte < u8(0x80)) || (byte >= u8(0xC0))) => {
@@ -128,63 +123,65 @@ impl(String,
128
123
  },
129
124
  .None => ()
130
125
  );
131
- };
132
-
133
- return count;
126
+ });
127
+ return(count);
134
128
  }
135
129
  )
136
130
  }),
137
-
138
131
  /**
139
- * Check if the string is empty
140
- */
141
- is_empty : (fn(self: Self) -> bool)(
142
- match(self._bytes,
132
+ * Check if the string is empty
133
+ */
134
+ is_empty : (fn(self : Self) -> bool)(
135
+ match(
136
+ self._bytes,
143
137
  .None => true,
144
138
  .Some(al) => (al.len() == usize(0))
145
139
  )
146
140
  ),
147
-
148
141
  /**
149
- * Get a reference to the internal byte array
150
- * Returns an empty ArrayList if the string is empty
151
- */
152
- as_bytes : (fn(self: Self) -> ArrayList(u8))(
153
- match(self._bytes,
142
+ * Get a reference to the internal byte array
143
+ * Returns an empty ArrayList if the string is empty
144
+ */
145
+ as_bytes : (fn(self : Self) -> ArrayList(u8))(
146
+ match(
147
+ self._bytes,
154
148
  .None => ArrayList(u8).new(),
155
149
  .Some(al) => al
156
150
  )
157
151
  ),
158
-
159
152
  // as_bytes : (fn(self: Self) -> ArrayList(u8))({
160
153
  // return self._bytes;
161
154
  // }),
162
-
163
155
  /**
164
- * Get a str view into the string's UTF-8 bytes
165
- * Returns a fat pointer (pointer + length) without copying
166
- */
167
- as_str : (fn(self: Self) -> str)(
168
- match(self._bytes,
156
+ * Get a str view into the string's UTF-8 bytes
157
+ * Returns a fat pointer (pointer + length) without copying
158
+ */
159
+ as_str : (fn(self : Self) -> str)(
160
+ match(
161
+ self._bytes,
169
162
  .None => str.from_raw_parts(*(u8)(""), usize(0)),
170
- .Some(al) => match(al._ptr,
163
+ .Some(al) => match(
164
+ al._ptr,
171
165
  .Some(p) => str.from_raw_parts(p, al._length),
172
166
  .None => str.from_raw_parts(*(u8)(""), usize(0))
173
167
  )
174
168
  )
175
169
  ),
176
-
177
170
  /**
178
- * Decode a UTF-8 encoded rune starting at the given byte index
179
- * Internal helper method
180
- */
181
- _decode_rune_at : (fn(self: Self, byte_index: usize) -> Option(rune))({
171
+ * Decode a UTF-8 encoded rune starting at the given byte index
172
+ * Internal helper method
173
+ */
174
+ _decode_rune_at : (fn(self : Self, byte_index : usize) -> Option(rune))({
182
175
  (al : Option(ArrayList(u8))) = self._bytes;
183
- match(al,
184
- .None => { return .None; },
176
+ match(
177
+ al,
178
+ .None => {
179
+ return(.None);
180
+ },
185
181
  .Some(bytes) => {
186
182
  first_byte_opt := bytes.get(byte_index);
187
- match(first_byte_opt,
183
+ match(
184
+ first_byte_opt,
188
185
  .Some(first_byte) => {
189
186
  (res : Option(rune)) = cond(
190
187
  (first_byte < u8(0x80)) => {
@@ -192,85 +189,91 @@ impl(String,
192
189
  rune.from_u32(codepoint)
193
190
  },
194
191
  ((first_byte >= u8(0xC0)) && (first_byte < u8(0xE0))) => {
195
- second_opt := bytes.get((byte_index + usize(1)));
196
- match(second_opt,
192
+ second_opt := bytes.get(byte_index + usize(1));
193
+ match(
194
+ second_opt,
197
195
  .Some(second) => {
198
196
  codepoint := (((u32(first_byte) & u32(0x1F)) << u32(6)) | (u32(second) & u32(0x3F)));
199
197
  rune.from_u32(codepoint)
200
198
  },
201
- .None => .None
199
+ .None =>.None
202
200
  )
203
201
  },
204
202
  ((first_byte >= u8(0xE0)) && (first_byte < u8(0xF0))) => {
205
- second_opt := bytes.get((byte_index + usize(1)));
206
- third_opt := bytes.get((byte_index + usize(2)));
207
- match(second_opt,
203
+ second_opt := bytes.get(byte_index + usize(1));
204
+ third_opt := bytes.get(byte_index + usize(2));
205
+ match(
206
+ second_opt,
208
207
  .Some(second) =>
209
- match(third_opt,
208
+ match(
209
+ third_opt,
210
210
  .Some(third) => {
211
211
  codepoint := ((((u32(first_byte) & u32(0x0F)) << u32(12)) | ((u32(second) & u32(0x3F)) << u32(6))) | (u32(third) & u32(0x3F)));
212
212
  rune.from_u32(codepoint)
213
213
  },
214
- .None => .None
214
+ .None =>.None
215
215
  ),
216
- .None => .None
216
+ .None =>.None
217
217
  )
218
218
  },
219
219
  ((first_byte >= u8(0xF0)) && (first_byte < u8(0xF8))) => {
220
- second_opt := bytes.get((byte_index + usize(1)));
221
- third_opt := bytes.get((byte_index + usize(2)));
222
- fourth_opt := bytes.get((byte_index + usize(3)));
223
- match(second_opt,
220
+ second_opt := bytes.get(byte_index + usize(1));
221
+ third_opt := bytes.get(byte_index + usize(2));
222
+ fourth_opt := bytes.get(byte_index + usize(3));
223
+ match(
224
+ second_opt,
224
225
  .Some(second) =>
225
- match(third_opt,
226
+ match(
227
+ third_opt,
226
228
  .Some(third) =>
227
- match(fourth_opt,
229
+ match(
230
+ fourth_opt,
228
231
  .Some(fourth) => {
229
232
  codepoint := (((((u32(first_byte) & u32(0x07)) << u32(18)) | ((u32(second) & u32(0x3F)) << u32(12))) | ((u32(third) & u32(0x3F)) << u32(6))) | (u32(fourth) & u32(0x3F)));
230
233
  rune.from_u32(codepoint)
231
234
  },
232
- .None => .None
235
+ .None =>.None
233
236
  ),
234
- .None => .None
237
+ .None =>.None
235
238
  ),
236
- .None => .None
239
+ .None =>.None
237
240
  )
238
241
  },
239
- true => .None
242
+ true =>.None
240
243
  );
241
- return res;
244
+ return(res);
242
245
  },
243
- .None => .None
246
+ .None =>.None
244
247
  )
245
248
  }
246
249
  )
247
250
  }),
248
-
249
251
  /**
250
- * Get the rune at the specified character index (0-based)
251
- * Returns None if index is out of bounds
252
- * For "你好世界", at(0) returns '你', at(1) returns '好', etc.
253
- */
254
- at : (fn(self: Self, index: usize) -> Option(rune))(
255
- match(self._bytes,
256
- .None => { return .None; },
252
+ * Get the rune at the specified character index (0-based)
253
+ * Returns None if index is out of bounds
254
+ * For "你好世界", at(0) returns '你', at(1) returns '好', etc.
255
+ */
256
+ at : (fn(self : Self, index : usize) -> Option(rune))(
257
+ match(
258
+ self._bytes,
259
+ .None => {
260
+ return(.None);
261
+ },
257
262
  .Some(al) => {
258
263
  char_count := usize(0);
259
264
  byte_index := usize(0);
260
265
  total_bytes := al.len();
261
-
262
- while ((byte_index < total_bytes)),
263
- (byte_index = (byte_index + usize(1))),
264
- {
266
+ while(byte_index < total_bytes, byte_index = (byte_index + usize(1)), {
265
267
  byte_opt := al.get(byte_index);
266
- match(byte_opt,
268
+ match(
269
+ byte_opt,
267
270
  .Some(byte) => {
268
271
  is_start := ((byte < u8(0x80)) || (byte >= u8(0xC0)));
269
272
  cond(
270
273
  is_start => {
271
274
  cond(
272
275
  (char_count == index) => {
273
- return Self._decode_rune_at(self, byte_index);
276
+ return(Self._decode_rune_at(self, byte_index));
274
277
  },
275
278
  true => {
276
279
  char_count = (char_count + usize(1));
@@ -282,55 +285,56 @@ impl(String,
282
285
  },
283
286
  .None => ()
284
287
  );
285
- };
286
-
287
- return .None;
288
+ });
289
+ return(.None);
288
290
  }
289
291
  )
290
292
  ),
291
-
292
293
  /**
293
- * Concatenate two strings (like JavaScript +)
294
- */
295
- concat : (fn(self: Self, other: Self) -> Self)({
296
- (self_len : usize) = match(self._bytes, .Some(b) => b.len(), .None => usize(0));
297
- (other_len : usize) = match(other._bytes, .Some(b) => b.len(), .None => usize(0));
298
- if(((self_len == usize(0)) && (other_len == usize(0))), {
299
- return Self(_bytes: .None);
294
+ * Concatenate two strings (like JavaScript +)
295
+ */
296
+ concat : (fn(self : Self, other : Self) -> Self)({
297
+ (self_len : usize) = match(self._bytes,.Some(b) => b.len(),.None => usize(0));
298
+ (other_len : usize) = match(other._bytes,.Some(b) => b.len(),.None => usize(0));
299
+ if((self_len == usize(0)) && (other_len == usize(0)), {
300
+ return(Self(_bytes :.None));
300
301
  });
301
- new_bytes := ArrayList(u8).with_capacity((self_len + other_len));
302
-
303
- match(self._bytes,
304
- .Some(b) => match(b.ptr(),
302
+ new_bytes := ArrayList(u8).with_capacity(self_len + other_len);
303
+ match(
304
+ self._bytes,
305
+ .Some(b) => match(
306
+ b.ptr(),
305
307
  .Some(p) => new_bytes.extend_from_ptr(p, self_len),
306
308
  .None => ()
307
309
  ),
308
310
  .None => ()
309
311
  );
310
-
311
- match(other._bytes,
312
- .Some(b) => match(b.ptr(),
312
+ match(
313
+ other._bytes,
314
+ .Some(b) => match(
315
+ b.ptr(),
313
316
  .Some(p) => new_bytes.extend_from_ptr(p, other_len),
314
317
  .None => ()
315
318
  ),
316
319
  .None => ()
317
320
  );
318
-
319
- return Self(_bytes: .Some(new_bytes));
321
+ return(Self(_bytes :.Some(new_bytes)));
320
322
  }),
321
-
322
323
  /// Append another `String` to this string in-place (mutates `self`).
323
- push_string : (fn(self: *(Self), other: Self) -> unit)({
324
- (olen : usize) = match(other._bytes, .Some(b) => b.len(), .None => usize(0));
325
- if((olen > usize(0)), {
326
- match(other._bytes,
327
- .Some(ob) => match(ob.ptr(),
324
+ push_string : (fn(self : *(Self), other : Self) -> unit)({
325
+ (olen : usize) = match(other._bytes,.Some(b) => b.len(),.None => usize(0));
326
+ if(olen > usize(0), {
327
+ match(
328
+ other._bytes,
329
+ .Some(ob) => match(
330
+ ob.ptr(),
328
331
  .Some(p) => {
329
- match(self.*._bytes,
332
+ match(
333
+ self.*._bytes,
330
334
  .None => {
331
335
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(olen);
332
336
  new_al.extend_from_ptr(p, olen);
333
- self.*._bytes = .Some(new_al);
337
+ self.*._bytes =.Some(new_al);
334
338
  },
335
339
  .Some(al) => {
336
340
  al.extend_from_ptr(p, olen);
@@ -343,16 +347,16 @@ impl(String,
343
347
  );
344
348
  });
345
349
  }),
346
-
347
350
  /// Append a `str` slice to this string in-place (mutates `self`).
348
- push_str : (fn(self: *(Self), s: str) -> unit)({
351
+ push_str : (fn(self : *(Self), s : str) -> unit)({
349
352
  (slen : usize) = s.len();
350
- if((slen > usize(0)), {
351
- match(self.*._bytes,
353
+ if(slen > usize(0), {
354
+ match(
355
+ self.*._bytes,
352
356
  .None => {
353
357
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(slen);
354
358
  new_al.extend_from_ptr(s.ptr(), slen);
355
- self.*._bytes = .Some(new_al);
359
+ self.*._bytes =.Some(new_al);
356
360
  },
357
361
  .Some(al) => {
358
362
  al.extend_from_ptr(s.ptr(), slen);
@@ -360,88 +364,89 @@ impl(String,
360
364
  );
361
365
  });
362
366
  }),
363
-
364
367
  /// Append a single byte to this string in-place (mutates `self`).
365
368
  /// The caller must ensure the byte maintains valid UTF-8.
366
- push_byte : (fn(self: *(Self), b: u8) -> unit)({
367
- match(self.*._bytes,
369
+ push_byte : (fn(self : *(Self), b : u8) -> unit)({
370
+ match(
371
+ self.*._bytes,
368
372
  .None => {
369
373
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(usize(8));
370
374
  new_al.push(b);
371
- self.*._bytes = .Some(new_al);
375
+ self.*._bytes =.Some(new_al);
372
376
  },
373
377
  .Some(al) => {
374
378
  al.push(b);
375
379
  }
376
380
  );
377
381
  }),
378
-
379
382
  /// Reserve capacity for at least `additional` more bytes.
380
383
  /// If the string is empty, creates a new buffer with the given capacity.
381
- reserve : (fn(self: *(Self), additional: usize) -> unit)({
382
- match(self.*._bytes,
384
+ reserve : (fn(self : *(Self), additional : usize) -> unit)({
385
+ match(
386
+ self.*._bytes,
383
387
  .None => {
384
- self.*._bytes = .Some(ArrayList(u8).with_capacity(additional));
388
+ self.*._bytes =.Some(ArrayList(u8).with_capacity(additional));
385
389
  },
386
390
  .Some(al) => {
387
391
  (current_len : usize) = al.len();
388
- al.ensure_total_capacity((current_len + additional));
392
+ al.ensure_total_capacity(current_len + additional);
389
393
  }
390
394
  );
391
395
  }),
392
-
393
396
  /// Clear the string content but keep the allocated buffer for reuse.
394
- clear : (fn(self: *(Self)) -> unit)(
395
- match(self.*._bytes,
397
+ clear : (fn(self : *(Self)) -> unit)(
398
+ match(
399
+ self.*._bytes,
396
400
  .Some(al) => al.clear(),
397
401
  .None => ()
398
402
  )
399
403
  ),
400
-
401
404
  /// Create a deep copy of this string with its own buffer.
402
- clone : (fn(self: Self) -> Self)(
403
- match(self._bytes,
404
- .None => Self(_bytes: .None),
405
+ clone : (fn(self : Self) -> Self)(
406
+ match(
407
+ self._bytes,
408
+ .None => Self(_bytes :.None),
405
409
  .Some(al) => {
406
410
  (new_al : ArrayList(u8)) = ArrayList(u8).with_capacity(al.len());
407
- match(al.ptr(),
411
+ match(
412
+ al.ptr(),
408
413
  .Some(p) => new_al.extend_from_ptr(p, al.len()),
409
414
  .None => ()
410
415
  );
411
- Self(_bytes: .Some(new_al))
416
+ Self(_bytes :.Some(new_al))
412
417
  }
413
418
  )
414
419
  ),
415
-
416
420
  /// Get the number of bytes in the string (not Unicode characters).
417
421
  /// Use `len()` for Unicode character count.
418
- bytes_len : (fn(self: Self) -> usize)(
419
- match(self._bytes, .Some(b) => b.len(), .None => usize(0))
422
+ bytes_len : (fn(self : Self) -> usize)(
423
+ match(self._bytes,.Some(b) => b.len(),.None => usize(0))
420
424
  ),
421
-
422
425
  /**
423
- * Extract a substring from start to end character indices (like JavaScript substring)
424
- * Returns a new string containing characters from start (inclusive) to end (exclusive)
425
- * If end is greater than length, it will substring to the end of the string
426
- */
427
- substring : (fn(self: Self, start: usize, end: usize) -> Self)(
428
- match(self._bytes,
429
- .None => { return Self(_bytes: .None); },
426
+ * Extract a substring from start to end character indices (like JavaScript substring)
427
+ * Returns a new string containing characters from start (inclusive) to end (exclusive)
428
+ * If end is greater than length, it will substring to the end of the string
429
+ */
430
+ substring : (fn(self : Self, start : usize, end : usize) -> Self)(
431
+ match(
432
+ self._bytes,
433
+ .None => {
434
+ return(Self(_bytes :.None));
435
+ },
430
436
  .Some(al) => {
431
437
  total_bytes := al.len();
432
-
433
- if((start >= end), {
434
- return Self(_bytes: .None);
438
+ if(start >= end, {
439
+ return(Self(_bytes :.None));
435
440
  });
436
-
437
441
  (char_index : usize) = usize(0);
438
442
  (byte_index : usize) = usize(0);
439
443
  (start_byte : usize) = total_bytes;
440
444
  (end_byte : usize) = total_bytes;
441
-
442
- while (byte_index < total_bytes), {
443
- if((char_index == start), { start_byte = byte_index; });
444
- if((char_index == end), {
445
+ while(byte_index < total_bytes, {
446
+ if(char_index == start, {
447
+ start_byte = byte_index;
448
+ });
449
+ if(char_index == end, {
445
450
  end_byte = byte_index;
446
451
  break;
447
452
  });
@@ -454,52 +459,53 @@ impl(String,
454
459
  );
455
460
  byte_index = (byte_index + byte_len);
456
461
  char_index = (char_index + usize(1));
457
- };
458
- if((char_index == start), { start_byte = byte_index; });
459
- if((char_index == end), { end_byte = byte_index; });
460
-
461
- if((start_byte >= end_byte), {
462
- return Self(_bytes: .None);
463
462
  });
464
-
463
+ if(char_index == start, {
464
+ start_byte = byte_index;
465
+ });
466
+ if(char_index == end, {
467
+ end_byte = byte_index;
468
+ });
469
+ if(start_byte >= end_byte, {
470
+ return(Self(_bytes :.None));
471
+ });
465
472
  (count : usize) = (end_byte - start_byte);
466
473
  new_bytes := ArrayList(u8).with_capacity(count);
467
- match(al.ptr(),
468
- .Some(src_p) => new_bytes.extend_from_ptr((src_p &+ start_byte), count),
474
+ match(
475
+ al.ptr(),
476
+ .Some(src_p) => new_bytes.extend_from_ptr(src_p &+ start_byte, count),
469
477
  .None => ()
470
478
  );
471
- Self(_bytes: .Some(new_bytes))
479
+ Self(_bytes :.Some(new_bytes))
472
480
  }
473
481
  )
474
482
  ),
475
-
476
483
  /**
477
- * Find the first occurrence of a substring (like JavaScript indexOf)
478
- * Returns the character index of the first match, or None if not found
479
- * from_index specifies the character index to start searching from
480
- */
481
- index_of : (fn(self: Self, substr: Self, (from_index : usize) ?= 0) -> Option(usize))(
484
+ * Find the first occurrence of a substring (like JavaScript indexOf)
485
+ * Returns the character index of the first match, or None if not found
486
+ * from_index specifies the character index to start searching from
487
+ */
488
+ index_of : (fn(self : Self, substr : Self, (from_index : usize) ?= 0) -> Option(usize))(
482
489
  cond(
483
- substr.is_empty() => .Some(from_index),
490
+ substr.is_empty() =>.Some(from_index),
484
491
  true => {
485
- (self_bytes : usize) = match(self._bytes, .Some(b) => b.len(), .None => usize(0));
486
- (sub_bytes : usize) = match(substr._bytes, .Some(b) => b.len(), .None => usize(0));
487
-
492
+ (self_bytes : usize) = match(self._bytes,.Some(b) => b.len(),.None => usize(0));
493
+ (sub_bytes : usize) = match(substr._bytes,.Some(b) => b.len(),.None => usize(0));
488
494
  cond(
489
- (sub_bytes > self_bytes) => .None,
490
- true => match(self._bytes,
491
- .None => .None,
492
- .Some(self_al) => match(substr._bytes,
493
- .None => .None,
495
+ (sub_bytes > self_bytes) =>.None,
496
+ true => match(
497
+ self._bytes,
498
+ .None =>.None,
499
+ .Some(self_al) => match(
500
+ substr._bytes,
501
+ .None =>.None,
494
502
  .Some(sub_al) => {
495
503
  char_index := usize(0);
496
504
  byte_index := usize(0);
497
-
498
- while (((byte_index < self_bytes) && (char_index < from_index))),
499
- (byte_index = (byte_index + usize(1))),
500
- {
505
+ while((byte_index < self_bytes) && (char_index < from_index), byte_index = (byte_index + usize(1)), {
501
506
  first_byte_opt := self_al.get(byte_index);
502
- match(first_byte_opt,
507
+ match(
508
+ first_byte_opt,
503
509
  .Some(first_byte) => {
504
510
  is_start := ((first_byte < u8(0x80)) || (first_byte >= u8(0xC0)));
505
511
  cond(
@@ -511,21 +517,18 @@ impl(String,
511
517
  },
512
518
  .None => ()
513
519
  );
514
- };
515
-
516
- while ((byte_index <= (self_bytes - sub_bytes))),
517
- (byte_index = (byte_index + usize(1))),
518
- {
520
+ });
521
+ while(byte_index <= (self_bytes - sub_bytes), byte_index = (byte_index + usize(1)), {
519
522
  matches := true;
520
523
  j := usize(0);
521
- while ((j < sub_bytes)),
522
- (j = (j + usize(1))),
523
- {
524
- self_byte_opt := self_al.get((byte_index + j));
524
+ while(j < sub_bytes, j = (j + usize(1)), {
525
+ self_byte_opt := self_al.get(byte_index + j);
525
526
  sub_byte_opt := sub_al.get(j);
526
- match(self_byte_opt,
527
+ match(
528
+ self_byte_opt,
527
529
  .Some(self_byte) =>
528
- match(sub_byte_opt,
530
+ match(
531
+ sub_byte_opt,
529
532
  .Some(sub_byte) => {
530
533
  cond(
531
534
  (self_byte != sub_byte) => {
@@ -545,17 +548,16 @@ impl(String,
545
548
  break;
546
549
  }
547
550
  );
548
- };
549
-
551
+ });
550
552
  cond(
551
553
  matches => {
552
- return .Some(char_index);
554
+ return(.Some(char_index));
553
555
  },
554
556
  true => ()
555
557
  );
556
-
557
558
  first_byte_opt := self_al.get(byte_index);
558
- match(first_byte_opt,
559
+ match(
560
+ first_byte_opt,
559
561
  .Some(first_byte) => {
560
562
  is_start := ((first_byte < u8(0x80)) || (first_byte >= u8(0xC0)));
561
563
  cond(
@@ -567,9 +569,8 @@ impl(String,
567
569
  },
568
570
  .None => ()
569
571
  );
570
- };
571
-
572
- return .None;
572
+ });
573
+ return(.None);
573
574
  }
574
575
  )
575
576
  )
@@ -577,72 +578,66 @@ impl(String,
577
578
  }
578
579
  )
579
580
  ),
580
-
581
581
  /**
582
- * Check if the string contains a substring
583
- */
584
- contains : (fn(self: Self, substr: Self, (from_index : usize) ?= 0) -> bool)(
585
- match(self.index_of(substr, from_index),
582
+ * Check if the string contains a substring
583
+ */
584
+ contains : (fn(self : Self, substr : Self, (from_index : usize) ?= 0) -> bool)(
585
+ match(
586
+ self.index_of(substr, from_index),
586
587
  .Some(_) => true,
587
588
  .None => false
588
589
  )
589
590
  ),
590
-
591
591
  /**
592
- * Split the string by a separator into an array of strings (like JavaScript split)
593
- * Returns an ArrayList of String
594
- */
595
- split : (fn(self: Self, separator: Self) -> ArrayList(Self))({
592
+ * Split the string by a separator into an array of strings (like JavaScript split)
593
+ * Returns an ArrayList of String
594
+ */
595
+ split : (fn(self : Self, separator : Self) -> ArrayList(Self))({
596
596
  result := ArrayList(Self).new();
597
-
598
597
  cond(
599
598
  separator.is_empty() => {
600
599
  char_count := self.len();
601
600
  i := usize(0);
602
- while ((i < char_count)),
603
- (i = (i + usize(1))),
604
- {
605
- char_str := self.substring(i, (i + usize(1)));
601
+ while(i < char_count, i = (i + usize(1)), {
602
+ char_str := self.substring(i, i + usize(1));
606
603
  result.push(char_str);
607
- };
608
- return result;
604
+ });
605
+ return(result);
609
606
  },
610
607
  self.is_empty() => {
611
608
  result.push(new());
612
- return result;
609
+ return(result);
613
610
  },
614
- true => match(self._bytes,
611
+ true => match(
612
+ self._bytes,
615
613
  .None => {
616
614
  result.push(new());
617
- return result;
615
+ return(result);
618
616
  },
619
- .Some(self_al) => match(separator._bytes,
617
+ .Some(self_al) => match(
618
+ separator._bytes,
620
619
  .None => {
621
620
  result.push(self);
622
- return result;
621
+ return(result);
623
622
  },
624
623
  .Some(sep_al) => {
625
624
  self_bytes := self_al.len();
626
625
  sep_bytes := sep_al.len();
627
-
628
626
  current_bytes := ArrayList(u8).new();
629
627
  byte_index := usize(0);
630
-
631
- while ((byte_index < self_bytes)),
632
- (byte_index = (byte_index + usize(1))),
633
- {
628
+ while(byte_index < self_bytes, byte_index = (byte_index + usize(1)), {
634
629
  matches := true;
635
630
  cond(
636
631
  ((byte_index + sep_bytes) <= self_bytes) => {
637
632
  j := usize(0);
638
- while ((j < sep_bytes)),
639
- (j = (j + usize(1))),
640
- {
641
- self_byte_opt := self_al.get((byte_index + j));
633
+ while(j < sep_bytes, j = (j + usize(1)), {
634
+ self_byte_opt := self_al.get(byte_index + j);
642
635
  sep_byte_opt := sep_al.get(j);
643
- match(self_byte_opt,
636
+ match(
637
+ self_byte_opt,
644
638
  .Some(self_byte) =>
645
- match(sep_byte_opt,
639
+ match(
640
+ sep_byte_opt,
646
641
  .Some(sep_byte) => {
647
642
  cond(
648
643
  (self_byte != sep_byte) => {
@@ -662,25 +657,25 @@ impl(String,
662
657
  break;
663
658
  }
664
659
  );
665
- };
660
+ });
666
661
  },
667
662
  true => {
668
663
  matches = false;
669
664
  }
670
665
  );
671
-
672
666
  cond(
673
667
  matches => {
674
668
  cond(
675
- (current_bytes.len() == usize(0)) => result.push(Self(_bytes: .None)),
676
- true => result.push(Self(_bytes: .Some(current_bytes)))
669
+ (current_bytes.len() == usize(0)) => result.push(Self(_bytes :.None)),
670
+ true => result.push(Self(_bytes :.Some(current_bytes)))
677
671
  );
678
672
  current_bytes = ArrayList(u8).new();
679
673
  byte_index = ((byte_index + sep_bytes) - usize(1));
680
674
  },
681
675
  true => {
682
676
  byte_opt := self_al.get(byte_index);
683
- match(byte_opt,
677
+ match(
678
+ byte_opt,
684
679
  .Some(byte) => {
685
680
  current_bytes.push(byte);
686
681
  },
@@ -688,48 +683,45 @@ impl(String,
688
683
  );
689
684
  }
690
685
  );
691
- };
692
-
686
+ });
693
687
  cond(
694
- (current_bytes.len() == usize(0)) => result.push(Self(_bytes: .None)),
695
- true => result.push(Self(_bytes: .Some(current_bytes)))
688
+ (current_bytes.len() == usize(0)) => result.push(Self(_bytes :.None)),
689
+ true => result.push(Self(_bytes :.Some(current_bytes)))
696
690
  );
697
- return result;
691
+ return(result);
698
692
  }
699
693
  )
700
694
  )
701
695
  )
702
696
  }),
703
-
704
697
  /**
705
- * Find the last occurrence of a substring (like JavaScript lastIndexOf)
706
- * Returns the character index of the last match, or None if not found
707
- * from_index specifies the character index to start searching backwards from
708
- */
709
- last_index_of : (fn(self: Self, substr: Self, (from_index : usize) ?= usize.MAX) -> Option(usize))(
698
+ * Find the last occurrence of a substring (like JavaScript lastIndexOf)
699
+ * Returns the character index of the last match, or None if not found
700
+ * from_index specifies the character index to start searching backwards from
701
+ */
702
+ last_index_of : (fn(self : Self, substr : Self, (from_index : usize) ?= usize.MAX) -> Option(usize))(
710
703
  cond(
711
- substr.is_empty() => .Some(self.len()),
712
- true => match(self._bytes,
713
- .None => .None,
714
- .Some(self_al) => match(substr._bytes,
715
- .None => .None,
704
+ substr.is_empty() =>.Some(self.len()),
705
+ true => match(
706
+ self._bytes,
707
+ .None =>.None,
708
+ .Some(self_al) => match(
709
+ substr._bytes,
710
+ .None =>.None,
716
711
  .Some(sub_al) => {
717
712
  self_bytes := self_al.len();
718
713
  sub_bytes := sub_al.len();
719
-
720
714
  cond(
721
- (sub_bytes > self_bytes) => .None,
715
+ (sub_bytes > self_bytes) =>.None,
722
716
  true => {
723
717
  char_positions := ArrayList(usize).new();
724
718
  byte_positions := ArrayList(usize).new();
725
-
726
719
  byte_idx := usize(0);
727
720
  char_idx := usize(0);
728
- while ((byte_idx < self_bytes)),
729
- (byte_idx = (byte_idx + usize(1))),
730
- {
721
+ while(byte_idx < self_bytes, byte_idx = (byte_idx + usize(1)), {
731
722
  byte_opt := self_al.get(byte_idx);
732
- match(byte_opt,
723
+ match(
724
+ byte_opt,
733
725
  .Some(byte) => {
734
726
  is_start := ((byte < u8(0x80)) || (byte >= u8(0xC0)));
735
727
  cond(
@@ -743,37 +735,35 @@ impl(String,
743
735
  },
744
736
  .None => ()
745
737
  );
746
- };
747
-
738
+ });
748
739
  max_char_index := cond(
749
740
  (from_index >= char_idx) => char_idx,
750
741
  true => (from_index + usize(1))
751
742
  );
752
-
753
- (last_match : Option(usize)) = .None;
743
+ (last_match : Option(usize)) =.None;
754
744
  i := usize(0);
755
- while ((i < char_positions.len())),
756
- (i = (i + usize(1))),
757
- {
745
+ while(i < char_positions.len(), i = (i + usize(1)), {
758
746
  char_pos_opt := char_positions.get(i);
759
747
  byte_pos_opt := byte_positions.get(i);
760
- match(char_pos_opt,
748
+ match(
749
+ char_pos_opt,
761
750
  .Some(char_pos) =>
762
- match(byte_pos_opt,
751
+ match(
752
+ byte_pos_opt,
763
753
  .Some(byte_pos) => {
764
754
  cond(
765
755
  (char_pos >= max_char_index) => break,
766
756
  ((byte_pos + sub_bytes) <= self_bytes) => {
767
757
  matches := true;
768
758
  j := usize(0);
769
- while ((j < sub_bytes)),
770
- (j = (j + usize(1))),
771
- {
772
- self_byte_opt := self_al.get((byte_pos + j));
759
+ while(j < sub_bytes, j = (j + usize(1)), {
760
+ self_byte_opt := self_al.get(byte_pos + j);
773
761
  sub_byte_opt := sub_al.get(j);
774
- match(self_byte_opt,
762
+ match(
763
+ self_byte_opt,
775
764
  .Some(self_byte) =>
776
- match(sub_byte_opt,
765
+ match(
766
+ sub_byte_opt,
777
767
  .Some(sub_byte) => {
778
768
  cond(
779
769
  (self_byte != sub_byte) => {
@@ -793,10 +783,10 @@ impl(String,
793
783
  break;
794
784
  }
795
785
  );
796
- };
786
+ });
797
787
  cond(
798
788
  matches => {
799
- last_match = .Some(char_pos);
789
+ last_match =.Some(char_pos);
800
790
  },
801
791
  true => ()
802
792
  );
@@ -808,9 +798,8 @@ impl(String,
808
798
  ),
809
799
  .None => ()
810
800
  );
811
- };
812
-
813
- return last_match;
801
+ });
802
+ return(last_match);
814
803
  }
815
804
  )
816
805
  }
@@ -818,30 +807,28 @@ impl(String,
818
807
  )
819
808
  )
820
809
  ),
821
-
822
810
  /**
823
- * Check if the string starts with the specified substring (like JavaScript startsWith)
824
- * position: The character index to start checking from (default 0)
825
- */
826
- starts_with : (fn(self: Self, prefix: Self, (position : usize) ?= 0) -> bool)({
827
- (prefix_bytes : usize) = match(prefix._bytes, .Some(b) => b.len(), .None => usize(0));
828
- (self_bytes : usize) = match(self._bytes, .Some(b) => b.len(), .None => usize(0));
829
-
811
+ * Check if the string starts with the specified substring (like JavaScript startsWith)
812
+ * position: The character index to start checking from (default 0)
813
+ */
814
+ starts_with : (fn(self : Self, prefix : Self, (position : usize) ?= 0) -> bool)({
815
+ (prefix_bytes : usize) = match(prefix._bytes,.Some(b) => b.len(),.None => usize(0));
816
+ (self_bytes : usize) = match(self._bytes,.Some(b) => b.len(),.None => usize(0));
830
817
  cond(
831
818
  (prefix_bytes == usize(0)) => true,
832
- true => match(self._bytes,
819
+ true => match(
820
+ self._bytes,
833
821
  .None => false,
834
- .Some(self_al) => match(prefix._bytes,
822
+ .Some(self_al) => match(
823
+ prefix._bytes,
835
824
  .None => true,
836
825
  .Some(prefix_al) => {
837
826
  char_index := usize(0);
838
827
  byte_index := usize(0);
839
-
840
- while (((byte_index < self_bytes) && (char_index < position))),
841
- (byte_index = (byte_index + usize(1))),
842
- {
828
+ while((byte_index < self_bytes) && (char_index < position), byte_index = (byte_index + usize(1)), {
843
829
  byte_opt := self_al.get(byte_index);
844
- match(byte_opt,
830
+ match(
831
+ byte_opt,
845
832
  .Some(byte) => {
846
833
  is_start := ((byte < u8(0x80)) || (byte >= u8(0xC0)));
847
834
  cond(
@@ -861,21 +848,20 @@ impl(String,
861
848
  },
862
849
  .None => ()
863
850
  );
864
- };
865
-
851
+ });
866
852
  cond(
867
853
  ((byte_index + prefix_bytes) > self_bytes) => false,
868
854
  true => {
869
855
  i := usize(0);
870
856
  matches := true;
871
- while ((i < prefix_bytes)),
872
- (i = (i + usize(1))),
873
- {
874
- self_byte_opt := self_al.get((byte_index + i));
857
+ while(i < prefix_bytes, i = (i + usize(1)), {
858
+ self_byte_opt := self_al.get(byte_index + i);
875
859
  prefix_byte_opt := prefix_al.get(i);
876
- match(self_byte_opt,
860
+ match(
861
+ self_byte_opt,
877
862
  .Some(self_byte) =>
878
- match(prefix_byte_opt,
863
+ match(
864
+ prefix_byte_opt,
879
865
  .Some(prefix_byte) => {
880
866
  cond(
881
867
  (self_byte != prefix_byte) => {
@@ -895,8 +881,8 @@ impl(String,
895
881
  break;
896
882
  }
897
883
  );
898
- };
899
- return matches;
884
+ });
885
+ return(matches);
900
886
  }
901
887
  )
902
888
  }
@@ -904,20 +890,20 @@ impl(String,
904
890
  )
905
891
  )
906
892
  }),
907
-
908
893
  /**
909
- * Check if the string ends with the specified substring (like JavaScript endsWith)
910
- * end_position: The character length to consider (default is string length)
911
- */
912
- ends_with : (fn(self: Self, suffix: Self, (end_position : usize) ?= usize.MAX) -> bool)({
913
- (suffix_bytes : usize) = match(suffix._bytes, .Some(b) => b.len(), .None => usize(0));
914
- (self_bytes : usize) = match(self._bytes, .Some(b) => b.len(), .None => usize(0));
915
-
894
+ * Check if the string ends with the specified substring (like JavaScript endsWith)
895
+ * end_position: The character length to consider (default is string length)
896
+ */
897
+ ends_with : (fn(self : Self, suffix : Self, (end_position : usize) ?= usize.MAX) -> bool)({
898
+ (suffix_bytes : usize) = match(suffix._bytes,.Some(b) => b.len(),.None => usize(0));
899
+ (self_bytes : usize) = match(self._bytes,.Some(b) => b.len(),.None => usize(0));
916
900
  cond(
917
901
  (suffix_bytes == usize(0)) => true,
918
- true => match(self._bytes,
902
+ true => match(
903
+ self._bytes,
919
904
  .None => false,
920
- .Some(self_al) => match(suffix._bytes,
905
+ .Some(self_al) => match(
906
+ suffix._bytes,
921
907
  .None => true,
922
908
  .Some(suffix_al) => {
923
909
  string_char_len := self.len();
@@ -926,16 +912,13 @@ impl(String,
926
912
  (end_position > string_char_len) => string_char_len,
927
913
  true => end_position
928
914
  );
929
-
930
915
  char_index := usize(0);
931
916
  byte_index := usize(0);
932
917
  end_byte_index := self_bytes;
933
-
934
- while ((byte_index < self_bytes)),
935
- (byte_index = (byte_index + usize(1))),
936
- {
918
+ while(byte_index < self_bytes, byte_index = (byte_index + usize(1)), {
937
919
  byte_opt := self_al.get(byte_index);
938
- match(byte_opt,
920
+ match(
921
+ byte_opt,
939
922
  .Some(byte) => {
940
923
  is_start := ((byte < u8(0x80)) || (byte >= u8(0xC0)));
941
924
  cond(
@@ -955,22 +938,21 @@ impl(String,
955
938
  },
956
939
  .None => ()
957
940
  );
958
- };
959
-
941
+ });
960
942
  cond(
961
943
  (suffix_bytes > end_byte_index) => false,
962
944
  true => {
963
945
  offset := (end_byte_index - suffix_bytes);
964
946
  i := usize(0);
965
947
  matches := true;
966
- while ((i < suffix_bytes)),
967
- (i = (i + usize(1))),
968
- {
969
- self_byte_opt := self_al.get((offset + i));
948
+ while(i < suffix_bytes, i = (i + usize(1)), {
949
+ self_byte_opt := self_al.get(offset + i);
970
950
  suffix_byte_opt := suffix_al.get(i);
971
- match(self_byte_opt,
951
+ match(
952
+ self_byte_opt,
972
953
  .Some(self_byte) =>
973
- match(suffix_byte_opt,
954
+ match(
955
+ suffix_byte_opt,
974
956
  .Some(suffix_byte) => {
975
957
  cond(
976
958
  (self_byte != suffix_byte) => {
@@ -990,8 +972,8 @@ impl(String,
990
972
  break;
991
973
  }
992
974
  );
993
- };
994
- return matches;
975
+ });
976
+ return(matches);
995
977
  }
996
978
  )
997
979
  }
@@ -999,39 +981,36 @@ impl(String,
999
981
  )
1000
982
  )
1001
983
  }),
1002
-
1003
984
  /**
1004
- * Replace the first occurrence of search_value with new_value (like JavaScript replace)
1005
- */
1006
- replace : (fn(self: Self, search_value: Self, new_value: Self) -> Self)(
985
+ * Replace the first occurrence of search_value with new_value (like JavaScript replace)
986
+ */
987
+ replace : (fn(self : Self, search_value : Self, new_value : Self) -> Self)(
1007
988
  cond(
1008
989
  search_value.is_empty() => {
1009
- return new_value.concat(self);
990
+ return(new_value.concat(self));
1010
991
  },
1011
- true => match(self._bytes,
992
+ true => match(
993
+ self._bytes,
1012
994
  .None => self,
1013
- .Some(self_al) => match(search_value._bytes,
995
+ .Some(self_al) => match(
996
+ search_value._bytes,
1014
997
  .None => self,
1015
998
  .Some(search_al) => {
1016
999
  self_bytes := self_al.len();
1017
1000
  search_bytes := search_al.len();
1018
-
1019
1001
  byte_index := usize(0);
1020
- (found_at : Option(usize)) = .None;
1021
-
1022
- while ((byte_index <= (self_bytes - search_bytes))),
1023
- (byte_index = (byte_index + usize(1))),
1024
- {
1002
+ (found_at : Option(usize)) =.None;
1003
+ while(byte_index <= (self_bytes - search_bytes), byte_index = (byte_index + usize(1)), {
1025
1004
  matches := true;
1026
1005
  j := usize(0);
1027
- while ((j < search_bytes)),
1028
- (j = (j + usize(1))),
1029
- {
1030
- self_byte_opt := self_al.get((byte_index + j));
1006
+ while(j < search_bytes, j = (j + usize(1)), {
1007
+ self_byte_opt := self_al.get(byte_index + j);
1031
1008
  search_byte_opt := search_al.get(j);
1032
- match(self_byte_opt,
1009
+ match(
1010
+ self_byte_opt,
1033
1011
  .Some(self_byte) =>
1034
- match(search_byte_opt,
1012
+ match(
1013
+ search_byte_opt,
1035
1014
  .Some(search_byte) => {
1036
1015
  cond(
1037
1016
  (self_byte != search_byte) => {
@@ -1051,48 +1030,47 @@ impl(String,
1051
1030
  break;
1052
1031
  }
1053
1032
  );
1054
- };
1055
-
1033
+ });
1056
1034
  cond(
1057
1035
  matches => {
1058
- found_at = .Some(byte_index);
1036
+ found_at =.Some(byte_index);
1059
1037
  break;
1060
1038
  },
1061
1039
  true => ()
1062
1040
  );
1063
- };
1064
-
1065
- match(found_at,
1041
+ });
1042
+ match(
1043
+ found_at,
1066
1044
  .Some(pos) => {
1067
- (nv_bytes : usize) = match(new_value._bytes, .Some(b) => b.len(), .None => usize(0));
1068
- new_bytes := ArrayList(u8).with_capacity(((self_bytes - search_bytes) + nv_bytes));
1069
-
1070
- match(self_al.ptr(),
1045
+ (nv_bytes : usize) = match(new_value._bytes,.Some(b) => b.len(),.None => usize(0));
1046
+ new_bytes := ArrayList(u8).with_capacity((self_bytes - search_bytes) + nv_bytes);
1047
+ match(
1048
+ self_al.ptr(),
1071
1049
  .Some(p) => {
1072
- if((pos > usize(0)), {
1050
+ if(pos > usize(0), {
1073
1051
  new_bytes.extend_from_ptr(p, pos);
1074
1052
  });
1075
1053
  },
1076
1054
  .None => ()
1077
1055
  );
1078
-
1079
- match(new_value._bytes,
1080
- .Some(nv_al) => match(nv_al.ptr(),
1056
+ match(
1057
+ new_value._bytes,
1058
+ .Some(nv_al) => match(
1059
+ nv_al.ptr(),
1081
1060
  .Some(p) => new_bytes.extend_from_ptr(p, nv_bytes),
1082
1061
  .None => ()
1083
1062
  ),
1084
1063
  .None => ()
1085
1064
  );
1086
-
1087
1065
  (after_pos : usize) = (pos + search_bytes);
1088
- if((after_pos < self_bytes), {
1089
- match(self_al.ptr(),
1090
- .Some(p) => new_bytes.extend_from_ptr((p &+ after_pos), (self_bytes - after_pos)),
1066
+ if(after_pos < self_bytes, {
1067
+ match(
1068
+ self_al.ptr(),
1069
+ .Some(p) => new_bytes.extend_from_ptr(p &+ after_pos, self_bytes - after_pos),
1091
1070
  .None => ()
1092
1071
  );
1093
1072
  });
1094
-
1095
- return Self(_bytes: .Some(new_bytes));
1073
+ return(Self(_bytes :.Some(new_bytes)));
1096
1074
  },
1097
1075
  .None => self
1098
1076
  )
@@ -1101,38 +1079,36 @@ impl(String,
1101
1079
  )
1102
1080
  )
1103
1081
  ),
1104
-
1105
1082
  /**
1106
- * Replace all occurrences of search_value with new_value (like JavaScript replaceAll)
1107
- */
1108
- replace_all : (fn(self: Self, search_value: Self, new_value: Self) -> Self)(
1083
+ * Replace all occurrences of search_value with new_value (like JavaScript replaceAll)
1084
+ */
1085
+ replace_all : (fn(self : Self, search_value : Self, new_value : Self) -> Self)(
1109
1086
  cond(
1110
1087
  search_value.is_empty() => self,
1111
- true => match(self._bytes,
1088
+ true => match(
1089
+ self._bytes,
1112
1090
  .None => self,
1113
- .Some(self_al) => match(search_value._bytes,
1091
+ .Some(self_al) => match(
1092
+ search_value._bytes,
1114
1093
  .None => self,
1115
1094
  .Some(search_al) => {
1116
1095
  self_bytes := self_al.len();
1117
1096
  search_bytes := search_al.len();
1118
1097
  new_bytes := ArrayList(u8).new();
1119
-
1120
1098
  byte_index := usize(0);
1121
- while ((byte_index < self_bytes)),
1122
- (byte_index = (byte_index + usize(1))),
1123
- {
1099
+ while(byte_index < self_bytes, byte_index = (byte_index + usize(1)), {
1124
1100
  matches := true;
1125
1101
  cond(
1126
1102
  ((byte_index + search_bytes) <= self_bytes) => {
1127
1103
  j := usize(0);
1128
- while ((j < search_bytes)),
1129
- (j = (j + usize(1))),
1130
- {
1131
- self_byte_opt := self_al.get((byte_index + j));
1104
+ while(j < search_bytes, j = (j + usize(1)), {
1105
+ self_byte_opt := self_al.get(byte_index + j);
1132
1106
  search_byte_opt := search_al.get(j);
1133
- match(self_byte_opt,
1107
+ match(
1108
+ self_byte_opt,
1134
1109
  .Some(self_byte) =>
1135
- match(search_byte_opt,
1110
+ match(
1111
+ search_byte_opt,
1136
1112
  .Some(search_byte) => {
1137
1113
  cond(
1138
1114
  (self_byte != search_byte) => {
@@ -1152,17 +1128,18 @@ impl(String,
1152
1128
  break;
1153
1129
  }
1154
1130
  );
1155
- };
1131
+ });
1156
1132
  },
1157
1133
  true => {
1158
1134
  matches = false;
1159
1135
  }
1160
1136
  );
1161
-
1162
1137
  cond(
1163
1138
  matches => {
1164
- match(new_value._bytes,
1165
- .Some(nv_al) => match(nv_al.ptr(),
1139
+ match(
1140
+ new_value._bytes,
1141
+ .Some(nv_al) => match(
1142
+ nv_al.ptr(),
1166
1143
  .Some(p) => new_bytes.extend_from_ptr(p, nv_al.len()),
1167
1144
  .None => ()
1168
1145
  ),
@@ -1172,41 +1149,41 @@ impl(String,
1172
1149
  },
1173
1150
  true => {
1174
1151
  byte_opt := self_al.get(byte_index);
1175
- match(byte_opt,
1176
- .Some(byte) => { new_bytes.push(byte); },
1152
+ match(
1153
+ byte_opt,
1154
+ .Some(byte) => {
1155
+ new_bytes.push(byte);
1156
+ },
1177
1157
  .None => ()
1178
1158
  );
1179
1159
  }
1180
1160
  );
1181
- };
1182
-
1161
+ });
1183
1162
  cond(
1184
- (new_bytes.len() == usize(0)) => Self(_bytes: .None),
1185
- true => Self(_bytes: .Some(new_bytes))
1163
+ (new_bytes.len() == usize(0)) => Self(_bytes :.None),
1164
+ true => Self(_bytes :.Some(new_bytes))
1186
1165
  )
1187
1166
  }
1188
1167
  )
1189
1168
  )
1190
1169
  )
1191
1170
  ),
1192
-
1193
1171
  /**
1194
- * Convert ASCII lowercase letters to uppercase (like JavaScript toUpperCase)
1195
- * Note: Only handles ASCII a-z, not full Unicode case mapping
1196
- */
1197
- to_uppercase : (fn(self: Self) -> Self)(
1198
- match(self._bytes,
1199
- .None => Self(_bytes: .None),
1172
+ * Convert ASCII lowercase letters to uppercase (like JavaScript toUpperCase)
1173
+ * Note: Only handles ASCII a-z, not full Unicode case mapping
1174
+ */
1175
+ to_uppercase : (fn(self : Self) -> Self)(
1176
+ match(
1177
+ self._bytes,
1178
+ .None => Self(_bytes :.None),
1200
1179
  .Some(al) => {
1201
1180
  (total : usize) = al.len();
1202
1181
  new_bytes := ArrayList(u8).with_capacity(total);
1203
-
1204
1182
  i := usize(0);
1205
- while ((i < total)),
1206
- (i = (i + usize(1))),
1207
- {
1183
+ while(i < total, i = (i + usize(1)), {
1208
1184
  byte_opt := al.get(i);
1209
- match(byte_opt,
1185
+ match(
1186
+ byte_opt,
1210
1187
  .Some(byte) => {
1211
1188
  new_byte := cond(
1212
1189
  ((byte >= u8(0x61)) && (byte <= u8(0x7A))) => (byte - u8(0x20)),
@@ -1216,30 +1193,27 @@ impl(String,
1216
1193
  },
1217
1194
  .None => ()
1218
1195
  );
1219
- };
1220
-
1221
- Self(_bytes: .Some(new_bytes))
1196
+ });
1197
+ Self(_bytes :.Some(new_bytes))
1222
1198
  }
1223
1199
  )
1224
1200
  ),
1225
-
1226
1201
  /**
1227
- * Convert ASCII uppercase letters to lowercase (like JavaScript toLowerCase)
1228
- * Note: Only handles ASCII A-Z, not full Unicode case mapping
1229
- */
1230
- to_lowercase : (fn(self: Self) -> Self)(
1231
- match(self._bytes,
1232
- .None => Self(_bytes: .None),
1202
+ * Convert ASCII uppercase letters to lowercase (like JavaScript toLowerCase)
1203
+ * Note: Only handles ASCII A-Z, not full Unicode case mapping
1204
+ */
1205
+ to_lowercase : (fn(self : Self) -> Self)(
1206
+ match(
1207
+ self._bytes,
1208
+ .None => Self(_bytes :.None),
1233
1209
  .Some(al) => {
1234
1210
  (total : usize) = al.len();
1235
1211
  new_bytes := ArrayList(u8).with_capacity(total);
1236
-
1237
1212
  i := usize(0);
1238
- while ((i < total)),
1239
- (i = (i + usize(1))),
1240
- {
1213
+ while(i < total, i = (i + usize(1)), {
1241
1214
  byte_opt := al.get(i);
1242
- match(byte_opt,
1215
+ match(
1216
+ byte_opt,
1243
1217
  .Some(byte) => {
1244
1218
  new_byte := cond(
1245
1219
  ((byte >= u8(0x41)) && (byte <= u8(0x5A))) => (byte + u8(0x20)),
@@ -1249,81 +1223,77 @@ impl(String,
1249
1223
  },
1250
1224
  .None => ()
1251
1225
  );
1252
- };
1253
-
1254
- Self(_bytes: .Some(new_bytes))
1226
+ });
1227
+ Self(_bytes :.Some(new_bytes))
1255
1228
  }
1256
1229
  )
1257
1230
  ),
1258
-
1259
1231
  /**
1260
- * Helper to check if a byte is ASCII whitespace
1261
- * Space (0x20), Tab (0x09), Newline (0x0A), Carriage Return (0x0D), Form Feed (0x0C), Vertical Tab (0x0B)
1262
- */
1263
- _is_whitespace_byte : (fn(byte: u8) -> bool)(
1264
- ((byte == u8(0x20)) || ((byte == u8(0x09)) || ((byte == u8(0x0A)) || ((byte == u8(0x0D)) || ((byte == u8(0x0C)) || (byte == u8(0x0B)))))))
1232
+ * Helper to check if a byte is ASCII whitespace
1233
+ * Space (0x20), Tab (0x09), Newline (0x0A), Carriage Return (0x0D), Form Feed (0x0C), Vertical Tab (0x0B)
1234
+ */
1235
+ _is_whitespace_byte : (fn(byte : u8) -> bool)(
1236
+ (byte == u8(0x20)) || ((byte == u8(0x09)) || ((byte == u8(0x0A)) || ((byte == u8(0x0D)) || ((byte == u8(0x0C)) || (byte == u8(0x0B))))))
1265
1237
  ),
1266
-
1267
1238
  /**
1268
- * Remove whitespace from both ends of the string (like JavaScript trim)
1269
- */
1270
- trim : (fn(self: Self) -> Self)(
1271
- match(self._bytes,
1272
- .None => Self(_bytes: .None),
1239
+ * Remove whitespace from both ends of the string (like JavaScript trim)
1240
+ */
1241
+ trim : (fn(self : Self) -> Self)(
1242
+ match(
1243
+ self._bytes,
1244
+ .None => Self(_bytes :.None),
1273
1245
  .Some(al) => {
1274
1246
  total_bytes := al.len();
1275
-
1276
- if((total_bytes == usize(0)), {
1277
- return Self(_bytes: .None);
1247
+ if(total_bytes == usize(0), {
1248
+ return(Self(_bytes :.None));
1278
1249
  });
1279
-
1280
1250
  (start_idx : usize) = usize(0);
1281
- while (start_idx < total_bytes), {
1251
+ while(start_idx < total_bytes, {
1282
1252
  (b : u8) = al(start_idx);
1283
- if(!(Self._is_whitespace_byte(b)), { break; });
1253
+ if(!(Self._is_whitespace_byte(b)), {
1254
+ break;
1255
+ });
1284
1256
  start_idx = (start_idx + usize(1));
1285
- };
1286
-
1257
+ });
1287
1258
  (end_idx : usize) = total_bytes;
1288
- while (end_idx > start_idx), {
1289
- (b : u8) = al((end_idx - usize(1)));
1290
- if(!(Self._is_whitespace_byte(b)), { break; });
1259
+ while(end_idx > start_idx, {
1260
+ (b : u8) = al(end_idx - usize(1));
1261
+ if(!(Self._is_whitespace_byte(b)), {
1262
+ break;
1263
+ });
1291
1264
  end_idx = (end_idx - usize(1));
1292
- };
1293
-
1294
- if((start_idx >= end_idx), {
1295
- return Self(_bytes: .None);
1296
1265
  });
1297
-
1266
+ if(start_idx >= end_idx, {
1267
+ return(Self(_bytes :.None));
1268
+ });
1298
1269
  (count : usize) = (end_idx - start_idx);
1299
1270
  new_bytes := ArrayList(u8).with_capacity(count);
1300
- match(al.ptr(),
1301
- .Some(p) => new_bytes.extend_from_ptr((p &+ start_idx), count),
1271
+ match(
1272
+ al.ptr(),
1273
+ .Some(p) => new_bytes.extend_from_ptr(p &+ start_idx, count),
1302
1274
  .None => ()
1303
1275
  );
1304
- Self(_bytes: .Some(new_bytes))
1276
+ Self(_bytes :.Some(new_bytes))
1305
1277
  }
1306
1278
  )
1307
1279
  ),
1308
-
1309
1280
  /**
1310
- * Remove whitespace from the start of the string (like JavaScript trimStart)
1311
- */
1312
- trim_start : (fn(self: Self) -> Self)(
1313
- match(self._bytes,
1314
- .None => Self(_bytes: .None),
1281
+ * Remove whitespace from the start of the string (like JavaScript trimStart)
1282
+ */
1283
+ trim_start : (fn(self : Self) -> Self)(
1284
+ match(
1285
+ self._bytes,
1286
+ .None => Self(_bytes :.None),
1315
1287
  .Some(al) => {
1316
1288
  total_bytes := al.len();
1317
-
1318
1289
  cond(
1319
- (total_bytes == usize(0)) => Self(_bytes: .None),
1290
+ (total_bytes == usize(0)) => Self(_bytes :.None),
1320
1291
  true => {
1321
1292
  start_idx := usize(0);
1322
- while ((start_idx < total_bytes)),
1323
- (start_idx = (start_idx + usize(1))),
1324
- {
1293
+ while(start_idx < total_bytes, start_idx = (start_idx + usize(1)), {
1325
1294
  byte_opt := al.get(start_idx);
1326
- match(byte_opt,
1295
+ match(
1296
+ byte_opt,
1327
1297
  .Some(byte) => {
1328
1298
  is_ws := Self._is_whitespace_byte(byte);
1329
1299
  cond(
@@ -1333,18 +1303,18 @@ impl(String,
1333
1303
  },
1334
1304
  .None => break
1335
1305
  );
1336
- };
1337
-
1306
+ });
1338
1307
  cond(
1339
- (start_idx >= total_bytes) => Self(_bytes: .None),
1308
+ (start_idx >= total_bytes) => Self(_bytes :.None),
1340
1309
  true => {
1341
1310
  (count : usize) = (total_bytes - start_idx);
1342
1311
  new_bytes := ArrayList(u8).with_capacity(count);
1343
- match(al.ptr(),
1344
- .Some(p) => new_bytes.extend_from_ptr((p &+ start_idx), count),
1312
+ match(
1313
+ al.ptr(),
1314
+ .Some(p) => new_bytes.extend_from_ptr(p &+ start_idx, count),
1345
1315
  .None => ()
1346
1316
  );
1347
- Self(_bytes: .Some(new_bytes))
1317
+ Self(_bytes :.Some(new_bytes))
1348
1318
  }
1349
1319
  )
1350
1320
  }
@@ -1352,25 +1322,23 @@ impl(String,
1352
1322
  }
1353
1323
  )
1354
1324
  ),
1355
-
1356
1325
  /**
1357
- * Remove whitespace from the end of the string (like JavaScript trimEnd)
1358
- */
1359
- trim_end : (fn(self: Self) -> Self)(
1360
- match(self._bytes,
1361
- .None => Self(_bytes: .None),
1326
+ * Remove whitespace from the end of the string (like JavaScript trimEnd)
1327
+ */
1328
+ trim_end : (fn(self : Self) -> Self)(
1329
+ match(
1330
+ self._bytes,
1331
+ .None => Self(_bytes :.None),
1362
1332
  .Some(al) => {
1363
1333
  total_bytes := al.len();
1364
-
1365
1334
  cond(
1366
- (total_bytes == usize(0)) => Self(_bytes: .None),
1335
+ (total_bytes == usize(0)) => Self(_bytes :.None),
1367
1336
  true => {
1368
1337
  end_idx := total_bytes;
1369
- while ((end_idx > usize(0))),
1370
- (end_idx = (end_idx - usize(1))),
1371
- {
1372
- byte_opt := al.get((end_idx - usize(1)));
1373
- match(byte_opt,
1338
+ while(end_idx > usize(0), end_idx = (end_idx - usize(1)), {
1339
+ byte_opt := al.get(end_idx - usize(1));
1340
+ match(
1341
+ byte_opt,
1374
1342
  .Some(byte) => {
1375
1343
  is_ws := Self._is_whitespace_byte(byte);
1376
1344
  cond(
@@ -1380,17 +1348,17 @@ impl(String,
1380
1348
  },
1381
1349
  .None => break
1382
1350
  );
1383
- };
1384
-
1351
+ });
1385
1352
  cond(
1386
- (end_idx == usize(0)) => Self(_bytes: .None),
1353
+ (end_idx == usize(0)) => Self(_bytes :.None),
1387
1354
  true => {
1388
1355
  new_bytes := ArrayList(u8).with_capacity(end_idx);
1389
- match(al.ptr(),
1356
+ match(
1357
+ al.ptr(),
1390
1358
  .Some(p) => new_bytes.extend_from_ptr(p, end_idx),
1391
1359
  .None => ()
1392
1360
  );
1393
- Self(_bytes: .Some(new_bytes))
1361
+ Self(_bytes :.Some(new_bytes))
1394
1362
  }
1395
1363
  )
1396
1364
  }
@@ -1399,323 +1367,334 @@ impl(String,
1399
1367
  )
1400
1368
  )
1401
1369
  );
1402
-
1403
1370
  /// Add trait implementation — concatenate two strings with `+`.
1404
- impl(String, Add(String)(
1405
- Output : String,
1406
- (+) : (fn(self: Self, other: Self) -> Self.Output)({
1407
- return self.concat(other);
1408
- })
1409
- ));
1410
-
1371
+ impl(
1372
+ String,
1373
+ Add(String)(
1374
+ Output : String,
1375
+ (+) : (fn(self : Self, other : Self) -> Self.Output)({
1376
+ return(self.concat(other));
1377
+ })
1378
+ )
1379
+ );
1411
1380
  /// Eq trait implementation — byte-level comparison of two strings.
1412
- impl(String, Eq(String)(
1413
- (==) : (fn(self: Self, other: Self) -> bool)({
1414
- (self_len : usize) = match(self._bytes, .Some(b) => b.len(), .None => usize(0));
1415
- (other_len : usize) = match(other._bytes, .Some(b) => b.len(), .None => usize(0));
1416
-
1417
- cond(
1418
- (self_len != other_len) => false,
1419
- (self_len == usize(0)) => true,
1420
- true =>
1421
- match(self._bytes,
1422
- .Some(self_al) =>
1423
- match(other._bytes,
1424
- .Some(other_al) =>
1425
- match(self_al.ptr(),
1426
- .Some(self_ptr) =>
1427
- match(other_al.ptr(),
1428
- .Some(other_ptr) =>
1429
- (memcmp((*(void))(self_ptr), (*(void))(other_ptr), self_len) == int(0)),
1430
- .None => false
1431
- ),
1432
- .None => false
1433
- ),
1434
- .None => false
1435
- ),
1436
- .None => false
1437
- )
1438
- )
1439
- }),
1440
- (!=) : (fn(self: Self, other: Self) -> bool)({
1441
- return !(Self.(==)(self, other));
1442
- })
1443
- ));
1444
-
1381
+ impl(
1382
+ String,
1383
+ Eq(String)(
1384
+ (==) : (fn(self : Self, other : Self) -> bool)({
1385
+ (self_len : usize) = match(self._bytes,.Some(b) => b.len(),.None => usize(0));
1386
+ (other_len : usize) = match(other._bytes,.Some(b) => b.len(),.None => usize(0));
1387
+ cond(
1388
+ (self_len != other_len) => false,
1389
+ (self_len == usize(0)) => true,
1390
+ true =>
1391
+ match(
1392
+ self._bytes,
1393
+ .Some(self_al) =>
1394
+ match(
1395
+ other._bytes,
1396
+ .Some(other_al) =>
1397
+ match(
1398
+ self_al.ptr(),
1399
+ .Some(self_ptr) =>
1400
+ match(
1401
+ other_al.ptr(),
1402
+ .Some(other_ptr) =>
1403
+ (memcmp((*(void))(self_ptr), (*(void))(other_ptr), self_len) == int(0)),
1404
+ .None => false
1405
+ ),
1406
+ .None => false
1407
+ ),
1408
+ .None => false
1409
+ ),
1410
+ .None => false
1411
+ )
1412
+ )
1413
+ }),
1414
+ (!=) : (fn(self : Self, other : Self) -> bool)({
1415
+ return(!(Self.(==)(self, other)));
1416
+ })
1417
+ )
1418
+ );
1445
1419
  /// Hash trait implementation — FNV-1a hash over the string's bytes.
1446
- impl(String, Hash(
1447
- (hash): (fn(self: *(Self)) -> u64)({
1448
- h := u64(14695981039346656037);
1449
- match(self.*._bytes,
1450
- .None => (),
1451
- .Some(al) => {
1452
- i := usize(0);
1453
- len := al.len();
1454
- while ((i < len)),
1455
- (i = (i + usize(1))),
1456
- {
1457
- match(al.get(i),
1458
- .Some(b) => {
1459
- h = (h ^ u64(b));
1460
- h = (h * u64(1099511628211));
1461
- },
1462
- .None => ()
1463
- );
1464
- };
1465
- }
1466
- );
1467
- h
1468
- })
1469
- ));
1470
-
1420
+ impl(
1421
+ String,
1422
+ Hash(
1423
+ (hash) : (fn(self : *(Self)) -> u64)({
1424
+ h := u64(14695981039346656037);
1425
+ match(
1426
+ self.*._bytes,
1427
+ .None => (),
1428
+ .Some(al) => {
1429
+ i := usize(0);
1430
+ len := al.len();
1431
+ while(i < len, i = (i + usize(1)), {
1432
+ match(
1433
+ al.get(i),
1434
+ .Some(b) => {
1435
+ h = (h ^ u64(b));
1436
+ h = (h * u64(1099511628211));
1437
+ },
1438
+ .None => ()
1439
+ );
1440
+ });
1441
+ }
1442
+ );
1443
+ h
1444
+ })
1445
+ )
1446
+ );
1471
1447
  /// === Iterator support ===
1472
-
1473
1448
  /**
1474
- * Rune iterator for `String` — yields decoded Unicode runes.
1475
- * Used by `chars()` and `into_iter()`.
1476
- */
1449
+ * Rune iterator for `String` — yields decoded Unicode runes.
1450
+ * Used by `chars()` and `into_iter()`.
1451
+ */
1477
1452
  StringChars :: struct(
1478
- _string : String,
1453
+ _string : String,
1479
1454
  _byte_index : usize
1480
1455
  );
1481
-
1482
- impl(StringChars, Iterator(
1483
- Item : rune,
1484
- next : (fn(self : *(Self)) -> Option(rune))(
1485
- match(self._string._bytes,
1486
- .None => .None,
1487
- .Some(al) => cond(
1488
- (self._byte_index >= al.len()) => .None,
1489
- true => {
1490
- first_byte_opt := al.get(self._byte_index);
1491
- match(first_byte_opt,
1492
- .Some(first_byte) => {
1493
- (byte_len : usize) = cond(
1494
- (first_byte < u8(0x80)) => usize(1),
1495
- ((first_byte >= u8(0xC0)) && (first_byte < u8(0xE0))) => usize(2),
1496
- ((first_byte >= u8(0xE0)) && (first_byte < u8(0xF0))) => usize(3),
1497
- ((first_byte >= u8(0xF0)) && (first_byte < u8(0xF8))) => usize(4),
1498
- true => usize(1)
1499
- );
1500
- r := self._string._decode_rune_at(self._byte_index);
1501
- self._byte_index = (self._byte_index + byte_len);
1502
- r
1503
- },
1504
- .None => .None
1505
- )
1506
- }
1456
+ impl(
1457
+ StringChars,
1458
+ Iterator(
1459
+ Item : rune,
1460
+ next : (fn(self : *(Self)) -> Option(rune))(
1461
+ match(
1462
+ self._string._bytes,
1463
+ .None =>.None,
1464
+ .Some(al) => cond(
1465
+ (self._byte_index >= al.len()) =>.None,
1466
+ true => {
1467
+ first_byte_opt := al.get(self._byte_index);
1468
+ match(
1469
+ first_byte_opt,
1470
+ .Some(first_byte) => {
1471
+ (byte_len : usize) = cond(
1472
+ (first_byte < u8(0x80)) => usize(1),
1473
+ ((first_byte >= u8(0xC0)) && (first_byte < u8(0xE0))) => usize(2),
1474
+ ((first_byte >= u8(0xE0)) && (first_byte < u8(0xF0))) => usize(3),
1475
+ ((first_byte >= u8(0xF0)) && (first_byte < u8(0xF8))) => usize(4),
1476
+ true => usize(1)
1477
+ );
1478
+ r := self._string._decode_rune_at(self._byte_index);
1479
+ self._byte_index = (self._byte_index + byte_len);
1480
+ r
1481
+ },
1482
+ .None =>.None
1483
+ )
1484
+ }
1485
+ )
1507
1486
  )
1508
1487
  )
1509
1488
  )
1510
- ));
1511
-
1489
+ );
1512
1490
  /**
1513
- * Byte iterator for `String` — yields raw UTF-8 bytes.
1514
- * Used by `bytes()`.
1515
- */
1491
+ * Byte iterator for `String` — yields raw UTF-8 bytes.
1492
+ * Used by `bytes()`.
1493
+ */
1516
1494
  StringBytes :: struct(
1517
1495
  _string : String,
1518
- _index : usize
1496
+ _index : usize
1519
1497
  );
1520
-
1521
- impl(StringBytes, Iterator(
1522
- Item : u8,
1523
- next : (fn(self : *(Self)) -> Option(u8))(
1524
- match(self._string._bytes,
1525
- .None => .None,
1526
- .Some(al) => cond(
1527
- (self._index >= al.len()) => .None,
1528
- true => {
1529
- byte_opt := al.get(self._index);
1530
- self._index = (self._index + usize(1));
1531
- byte_opt
1532
- }
1498
+ impl(
1499
+ StringBytes,
1500
+ Iterator(
1501
+ Item : u8,
1502
+ next : (fn(self : *(Self)) -> Option(u8))(
1503
+ match(
1504
+ self._string._bytes,
1505
+ .None =>.None,
1506
+ .Some(al) => cond(
1507
+ (self._index >= al.len()) =>.None,
1508
+ true => {
1509
+ byte_opt := al.get(self._index);
1510
+ self._index = (self._index + usize(1));
1511
+ byte_opt
1512
+ }
1513
+ )
1533
1514
  )
1534
1515
  )
1535
1516
  )
1536
- ));
1537
-
1538
- impl(String,
1517
+ );
1518
+ impl(
1519
+ String,
1539
1520
  /**
1540
- * Returns a rune iterator over the string's Unicode characters
1541
- */
1521
+ * Returns a rune iterator over the string's Unicode characters
1522
+ */
1542
1523
  chars : (fn(self : Self) -> StringChars)(
1543
- StringChars(_string: self, _byte_index: usize(0))
1524
+ StringChars(_string : self, _byte_index : usize(0))
1544
1525
  ),
1545
-
1546
1526
  /**
1547
- * Returns a byte iterator over the string's raw UTF-8 bytes
1548
- */
1527
+ * Returns a byte iterator over the string's raw UTF-8 bytes
1528
+ */
1549
1529
  bytes : (fn(self : Self) -> StringBytes)(
1550
- StringBytes(_string: self, _index: usize(0))
1530
+ StringBytes(_string : self, _index : usize(0))
1551
1531
  ),
1552
-
1553
1532
  /**
1554
- * Consume the string and return a rune iterator (default iteration)
1555
- */
1533
+ * Consume the string and return a rune iterator (default iteration)
1534
+ */
1556
1535
  into_iter : (fn(self : Self) -> StringChars)(
1557
- StringChars(_string: self, _byte_index: usize(0))
1536
+ StringChars(_string : self, _byte_index : usize(0))
1558
1537
  )
1559
1538
  );
1560
-
1561
1539
  /// === String utility methods ===
1562
-
1563
1540
  /**
1564
- * Line iterator for `String` — yields one line at a time (split on `\n`).
1565
- * The trailing newline is not included in each yielded line.
1566
- * Used by `lines()`.
1567
- */
1541
+ * Line iterator for `String` — yields one line at a time (split on `\n`).
1542
+ * The trailing newline is not included in each yielded line.
1543
+ * Used by `lines()`.
1544
+ */
1568
1545
  StringLines :: struct(
1569
- _string : String,
1546
+ _string : String,
1570
1547
  _byte_index : usize
1571
1548
  );
1572
-
1573
- impl(StringLines, Iterator(
1574
- Item : String,
1575
- next : (fn(self : *(Self)) -> Option(String))(
1576
- match(self._string._bytes,
1577
- .None => .None,
1578
- .Some(al) => {
1579
- total := al.len();
1580
- cond(
1581
- (self._byte_index >= total) => .None,
1582
- true => {
1583
- start := self._byte_index;
1584
- i := start;
1585
- while ((i < total)),
1586
- (i = (i + usize(1))),
1587
- {
1588
- byte_opt := al.get(i);
1589
- match(byte_opt,
1590
- .Some(b) => {
1591
- cond(
1592
- (b == u8(10)) => { break; },
1593
- true => ()
1594
- );
1595
- },
1596
- .None => ()
1597
- );
1598
- };
1599
- line_buf := ArrayList(u8).with_capacity((i - start));
1600
- j := start;
1601
- while ((j < i)),
1602
- (j = (j + usize(1))),
1603
- {
1604
- byte_opt := al.get(j);
1605
- match(byte_opt,
1606
- .Some(b) => { line_buf.push(b); },
1607
- .None => ()
1549
+ impl(
1550
+ StringLines,
1551
+ Iterator(
1552
+ Item : String,
1553
+ next : (fn(self : *(Self)) -> Option(String))(
1554
+ match(
1555
+ self._string._bytes,
1556
+ .None =>.None,
1557
+ .Some(al) => {
1558
+ total := al.len();
1559
+ cond(
1560
+ (self._byte_index >= total) =>.None,
1561
+ true => {
1562
+ start := self._byte_index;
1563
+ i := start;
1564
+ while(i < total, i = (i + usize(1)), {
1565
+ byte_opt := al.get(i);
1566
+ match(
1567
+ byte_opt,
1568
+ .Some(b) => {
1569
+ cond(
1570
+ (b == u8(10)) => {
1571
+ break;
1572
+ },
1573
+ true => ()
1574
+ );
1575
+ },
1576
+ .None => ()
1577
+ );
1578
+ });
1579
+ line_buf := ArrayList(u8).with_capacity(i - start);
1580
+ j := start;
1581
+ while(j < i, j = (j + usize(1)), {
1582
+ byte_opt := al.get(j);
1583
+ match(
1584
+ byte_opt,
1585
+ .Some(b) => {
1586
+ line_buf.push(b);
1587
+ },
1588
+ .None => ()
1589
+ );
1590
+ });
1591
+ self._byte_index = cond(
1592
+ (i < total) => (i + usize(1)),
1593
+ true => total
1608
1594
  );
1609
- };
1610
- self._byte_index = cond(
1611
- (i < total) => (i + usize(1)),
1612
- true => total
1613
- );
1614
- cond(
1615
- (line_buf.len() == usize(0)) => .Some(String(_bytes: .None)),
1616
- true => .Some(String(_bytes: .Some(line_buf)))
1617
- )
1618
- }
1619
- )
1620
- }
1595
+ cond(
1596
+ (line_buf.len() == usize(0)) =>.Some(String(_bytes :.None)),
1597
+ true =>.Some(String(_bytes :.Some(line_buf)))
1598
+ )
1599
+ }
1600
+ )
1601
+ }
1602
+ )
1621
1603
  )
1622
1604
  )
1623
- ));
1624
-
1625
- impl(String,
1605
+ );
1606
+ impl(
1607
+ String,
1626
1608
  /**
1627
- * Returns a line iterator over the string.
1628
- * Each call to `next()` yields the next line (without the trailing `\n`).
1629
- *
1630
- * ## Example
1631
- * ```rust
1632
- * s := `hello\nworld`;
1633
- * iter := s.lines();
1634
- * assert(iter.next() == .Some(`hello`), "first line");
1635
- * assert(iter.next() == .Some(`world`), "second line");
1636
- * assert(iter.next() == .None, "done");
1637
- * ```
1638
- */
1609
+ * Returns a line iterator over the string.
1610
+ * Each call to `next()` yields the next line (without the trailing `\n`).
1611
+ *
1612
+ * ## Example
1613
+ * ```rust
1614
+ * s := `hello\nworld`;
1615
+ * iter := s.lines();
1616
+ * assert(iter.next() == .Some(`hello`), "first line");
1617
+ * assert(iter.next() == .Some(`world`), "second line");
1618
+ * assert(iter.next() == .None, "done");
1619
+ * ```
1620
+ */
1639
1621
  lines : (fn(self : Self) -> StringLines)(
1640
- StringLines(_string: self, _byte_index: usize(0))
1622
+ StringLines(_string : self, _byte_index : usize(0))
1641
1623
  ),
1642
-
1643
1624
  /**
1644
- * Returns a new string containing `n` copies of `self`.
1645
- * Returns an empty string when `n == 0` or `self` is empty.
1646
- *
1647
- * ## Example
1648
- * ```rust
1649
- * assert(`ab`.repeat(usize(3)) == `ababab`, "repeat");
1650
- * assert(`x`.repeat(usize(0)) == ``, "repeat 0");
1651
- * ```
1652
- */
1653
- repeat : (fn(self: Self, n: usize) -> Self)(
1625
+ * Returns a new string containing `n` copies of `self`.
1626
+ * Returns an empty string when `n == 0` or `self` is empty.
1627
+ *
1628
+ * ## Example
1629
+ * ```rust
1630
+ * assert(`ab`.repeat(usize(3)) == `ababab`, "repeat");
1631
+ * assert(`x`.repeat(usize(0)) == ``, "repeat 0");
1632
+ * ```
1633
+ */
1634
+ repeat : (fn(self : Self, n : usize) -> Self)(
1654
1635
  cond(
1655
- (n == usize(0)) => Self(_bytes: .None),
1656
- self.is_empty() => Self(_bytes: .None),
1636
+ (n == usize(0)) => Self(_bytes :.None),
1637
+ self.is_empty() => Self(_bytes :.None),
1657
1638
  true => {
1658
1639
  self_byte_len := self.bytes_len();
1659
1640
  total := (self_byte_len * n);
1660
1641
  buf := ArrayList(u8).with_capacity(total);
1661
1642
  i := usize(0);
1662
- while ((i < n)),
1663
- (i = (i + usize(1))),
1664
- {
1665
- match(self._bytes,
1643
+ while(i < n, i = (i + usize(1)), {
1644
+ match(
1645
+ self._bytes,
1666
1646
  .Some(al) => {
1667
1647
  j := usize(0);
1668
- while ((j < self_byte_len)),
1669
- (j = (j + usize(1))),
1670
- {
1648
+ while(j < self_byte_len, j = (j + usize(1)), {
1671
1649
  byte_opt := al.get(j);
1672
- match(byte_opt,
1673
- .Some(b) => { buf.push(b); },
1650
+ match(
1651
+ byte_opt,
1652
+ .Some(b) => {
1653
+ buf.push(b);
1654
+ },
1674
1655
  .None => ()
1675
1656
  );
1676
- };
1657
+ });
1677
1658
  },
1678
1659
  .None => ()
1679
1660
  );
1680
- };
1681
- Self(_bytes: .Some(buf))
1661
+ });
1662
+ Self(_bytes :.Some(buf))
1682
1663
  }
1683
1664
  )
1684
1665
  ),
1685
-
1686
1666
  /**
1687
- * Join an `ArrayList(String)` with this string as separator.
1688
- * Returns an empty string when `items` is empty.
1689
- *
1690
- * ## Example
1691
- * ```rust
1692
- * items := ArrayList(String).new();
1693
- * items.push(`a`);
1694
- * items.push(`b`);
1695
- * items.push(`c`);
1696
- * result := `, `.join(items);
1697
- * assert(result == `a, b, c`, "join");
1698
- * ```
1699
- */
1700
- join : (fn(self: Self, items: ArrayList(Self)) -> Self)({
1667
+ * Join an `ArrayList(String)` with this string as separator.
1668
+ * Returns an empty string when `items` is empty.
1669
+ *
1670
+ * ## Example
1671
+ * ```rust
1672
+ * items := ArrayList(String).new();
1673
+ * items.push(`a`);
1674
+ * items.push(`b`);
1675
+ * items.push(`c`);
1676
+ * result := `, `.join(items);
1677
+ * assert(result == `a, b, c`, "join");
1678
+ * ```
1679
+ */
1680
+ join : (fn(self : Self, items : ArrayList(Self)) -> Self)({
1701
1681
  count := items.len();
1702
1682
  cond(
1703
- (count == usize(0)) => Self(_bytes: .None),
1683
+ (count == usize(0)) => Self(_bytes :.None),
1704
1684
  true => {
1705
1685
  sep_byte_len := self.bytes_len();
1706
1686
  total_bytes := usize(0);
1707
1687
  k := usize(0);
1708
- while ((k < count)),
1709
- (k = (k + usize(1))),
1710
- {
1688
+ while(k < count, k = (k + usize(1)), {
1711
1689
  item_opt := items.get(k);
1712
- match(item_opt,
1690
+ match(
1691
+ item_opt,
1713
1692
  .Some(item) => {
1714
1693
  total_bytes = (total_bytes + item.bytes_len());
1715
1694
  },
1716
1695
  .None => ()
1717
1696
  );
1718
- };
1697
+ });
1719
1698
  cond(
1720
1699
  (count > usize(1)) => {
1721
1700
  total_bytes = (total_bytes + (sep_byte_len * (count - usize(1))));
@@ -1724,41 +1703,44 @@ impl(String,
1724
1703
  );
1725
1704
  buf := ArrayList(u8).with_capacity(total_bytes);
1726
1705
  m := usize(0);
1727
- while ((m < count)),
1728
- (m = (m + usize(1))),
1729
- {
1706
+ while(m < count, m = (m + usize(1)), {
1730
1707
  item_opt := items.get(m);
1731
- match(item_opt,
1708
+ match(
1709
+ item_opt,
1732
1710
  .Some(item) => {
1733
- match(item._bytes,
1711
+ match(
1712
+ item._bytes,
1734
1713
  .Some(al) => {
1735
1714
  p := usize(0);
1736
- while ((p < al.len())),
1737
- (p = (p + usize(1))),
1738
- {
1715
+ while(p < al.len(), p = (p + usize(1)), {
1739
1716
  byte_opt := al.get(p);
1740
- match(byte_opt,
1741
- .Some(b) => { buf.push(b); },
1717
+ match(
1718
+ byte_opt,
1719
+ .Some(b) => {
1720
+ buf.push(b);
1721
+ },
1742
1722
  .None => ()
1743
1723
  );
1744
- };
1724
+ });
1745
1725
  },
1746
1726
  .None => ()
1747
1727
  );
1748
1728
  cond(
1749
1729
  (m < (count - usize(1))) => {
1750
- match(self._bytes,
1730
+ match(
1731
+ self._bytes,
1751
1732
  .Some(sep_al) => {
1752
1733
  q := usize(0);
1753
- while ((q < sep_byte_len)),
1754
- (q = (q + usize(1))),
1755
- {
1734
+ while(q < sep_byte_len, q = (q + usize(1)), {
1756
1735
  byte_opt := sep_al.get(q);
1757
- match(byte_opt,
1758
- .Some(b) => { buf.push(b); },
1736
+ match(
1737
+ byte_opt,
1738
+ .Some(b) => {
1739
+ buf.push(b);
1740
+ },
1759
1741
  .None => ()
1760
1742
  );
1761
- };
1743
+ });
1762
1744
  },
1763
1745
  .None => ()
1764
1746
  );
@@ -1768,42 +1750,42 @@ impl(String,
1768
1750
  },
1769
1751
  .None => ()
1770
1752
  );
1771
- };
1753
+ });
1772
1754
  cond(
1773
- (buf.len() == usize(0)) => Self(_bytes: .None),
1774
- true => Self(_bytes: .Some(buf))
1755
+ (buf.len() == usize(0)) => Self(_bytes :.None),
1756
+ true => Self(_bytes :.Some(buf))
1775
1757
  )
1776
1758
  }
1777
1759
  )
1778
1760
  })
1779
1761
  );
1780
-
1781
1762
  /// === Numeric parsing methods ===
1782
-
1783
- impl(String,
1763
+ impl(
1764
+ String,
1784
1765
  /**
1785
- * Helper: check if a byte is an ASCII digit '0'-'9'
1786
- */
1787
- _is_digit_byte : (fn(byte: u8) -> bool)(
1788
- ((byte >= u8(48)) && (byte <= u8(57)))
1766
+ * Helper: check if a byte is an ASCII digit '0'-'9'
1767
+ */
1768
+ _is_digit_byte : (fn(byte : u8) -> bool)(
1769
+ (byte >= u8(48)) && (byte <= u8(57))
1789
1770
  ),
1790
-
1791
1771
  /**
1792
- * Parse the string as a signed 32-bit integer.
1793
- * Returns .Some(value) on success, .None on failure (empty, invalid chars, overflow).
1794
- */
1795
- parse_i32 : (fn(self: Self) -> Option(i32))(
1796
- match(self._bytes,
1797
- .None => .None,
1772
+ * Parse the string as a signed 32-bit integer.
1773
+ * Returns .Some(value) on success, .None on failure (empty, invalid chars, overflow).
1774
+ */
1775
+ parse_i32 : (fn(self : Self) -> Option(i32))(
1776
+ match(
1777
+ self._bytes,
1778
+ .None =>.None,
1798
1779
  .Some(al) => {
1799
1780
  total_bytes := al.len();
1800
1781
  cond(
1801
- (total_bytes == usize(0)) => .None,
1782
+ (total_bytes == usize(0)) =>.None,
1802
1783
  true => {
1803
1784
  idx := usize(0);
1804
1785
  is_negative := false;
1805
1786
  first_byte_opt := al.get(usize(0));
1806
- match(first_byte_opt,
1787
+ match(
1788
+ first_byte_opt,
1807
1789
  .Some(first_byte) => {
1808
1790
  cond(
1809
1791
  (first_byte == u8(45)) => {
@@ -1817,49 +1799,45 @@ impl(String,
1817
1799
  );
1818
1800
  },
1819
1801
  .None => {
1820
- return .None;
1802
+ return(.None);
1821
1803
  }
1822
1804
  );
1823
-
1824
1805
  cond(
1825
- (idx >= total_bytes) => .None,
1806
+ (idx >= total_bytes) =>.None,
1826
1807
  true => {
1827
1808
  result := i64(0);
1828
1809
  has_digit := false;
1829
-
1830
- while ((idx < total_bytes)),
1831
- (idx = (idx + usize(1))),
1832
- {
1810
+ while(idx < total_bytes, idx = (idx + usize(1)), {
1833
1811
  byte_opt := al.get(idx);
1834
- match(byte_opt,
1812
+ match(
1813
+ byte_opt,
1835
1814
  .Some(byte) => {
1836
1815
  cond(
1837
1816
  Self._is_digit_byte(byte) => {
1838
- digit := i64((byte - u8(48)));
1817
+ digit := i64(byte - u8(48));
1839
1818
  result = ((result * i64(10)) + digit);
1840
1819
  has_digit = true;
1841
1820
  },
1842
1821
  true => {
1843
- return .None;
1822
+ return(.None);
1844
1823
  }
1845
1824
  );
1846
1825
  },
1847
1826
  .None => {
1848
- return .None;
1827
+ return(.None);
1849
1828
  }
1850
1829
  );
1851
- };
1852
-
1830
+ });
1853
1831
  cond(
1854
- (!(has_digit)) => .None,
1832
+ (!(has_digit)) =>.None,
1855
1833
  true => {
1856
1834
  final_val := cond(
1857
1835
  is_negative => (i64(0) - result),
1858
1836
  true => result
1859
1837
  );
1860
1838
  cond(
1861
- ((final_val < i64(-2147483648)) || (final_val > i64(2147483647))) => .None,
1862
- true => .Some(i32(final_val))
1839
+ ((final_val < i64(-(2147483648))) || (final_val > i64(2147483647))) =>.None,
1840
+ true =>.Some(i32(final_val))
1863
1841
  )
1864
1842
  }
1865
1843
  )
@@ -1870,24 +1848,25 @@ impl(String,
1870
1848
  }
1871
1849
  )
1872
1850
  ),
1873
-
1874
1851
  /**
1875
- * Parse the string as a signed 64-bit integer.
1876
- * Returns .Some(value) on success, .None on failure.
1877
- * Note: does not detect i64 overflow during accumulation.
1878
- */
1879
- parse_i64 : (fn(self: Self) -> Option(i64))(
1880
- match(self._bytes,
1881
- .None => .None,
1852
+ * Parse the string as a signed 64-bit integer.
1853
+ * Returns .Some(value) on success, .None on failure.
1854
+ * Note: does not detect i64 overflow during accumulation.
1855
+ */
1856
+ parse_i64 : (fn(self : Self) -> Option(i64))(
1857
+ match(
1858
+ self._bytes,
1859
+ .None =>.None,
1882
1860
  .Some(al) => {
1883
1861
  total_bytes := al.len();
1884
1862
  cond(
1885
- (total_bytes == usize(0)) => .None,
1863
+ (total_bytes == usize(0)) =>.None,
1886
1864
  true => {
1887
1865
  idx := usize(0);
1888
1866
  is_negative := false;
1889
1867
  first_byte_opt := al.get(usize(0));
1890
- match(first_byte_opt,
1868
+ match(
1869
+ first_byte_opt,
1891
1870
  .Some(first_byte) => {
1892
1871
  cond(
1893
1872
  (first_byte == u8(45)) => {
@@ -1901,47 +1880,43 @@ impl(String,
1901
1880
  );
1902
1881
  },
1903
1882
  .None => {
1904
- return .None;
1883
+ return(.None);
1905
1884
  }
1906
1885
  );
1907
-
1908
1886
  cond(
1909
- (idx >= total_bytes) => .None,
1887
+ (idx >= total_bytes) =>.None,
1910
1888
  true => {
1911
1889
  result := i64(0);
1912
1890
  has_digit := false;
1913
-
1914
- while ((idx < total_bytes)),
1915
- (idx = (idx + usize(1))),
1916
- {
1891
+ while(idx < total_bytes, idx = (idx + usize(1)), {
1917
1892
  byte_opt := al.get(idx);
1918
- match(byte_opt,
1893
+ match(
1894
+ byte_opt,
1919
1895
  .Some(byte) => {
1920
1896
  cond(
1921
1897
  Self._is_digit_byte(byte) => {
1922
- digit := i64((byte - u8(48)));
1898
+ digit := i64(byte - u8(48));
1923
1899
  result = ((result * i64(10)) + digit);
1924
1900
  has_digit = true;
1925
1901
  },
1926
1902
  true => {
1927
- return .None;
1903
+ return(.None);
1928
1904
  }
1929
1905
  );
1930
1906
  },
1931
1907
  .None => {
1932
- return .None;
1908
+ return(.None);
1933
1909
  }
1934
1910
  );
1935
- };
1936
-
1911
+ });
1937
1912
  cond(
1938
- (!(has_digit)) => .None,
1913
+ (!(has_digit)) =>.None,
1939
1914
  true => {
1940
1915
  final_val := cond(
1941
1916
  is_negative => (i64(0) - result),
1942
1917
  true => result
1943
1918
  );
1944
- return .Some(final_val);
1919
+ return(.Some(final_val));
1945
1920
  }
1946
1921
  )
1947
1922
  }
@@ -1951,26 +1926,27 @@ impl(String,
1951
1926
  }
1952
1927
  )
1953
1928
  ),
1954
-
1955
1929
  /**
1956
- * Parse the string as an unsigned 32-bit integer.
1957
- * Returns .Some(value) on success, .None on failure (empty, invalid chars, overflow, negative sign).
1958
- */
1959
- parse_u32 : (fn(self: Self) -> Option(u32))(
1960
- match(self._bytes,
1961
- .None => .None,
1930
+ * Parse the string as an unsigned 32-bit integer.
1931
+ * Returns .Some(value) on success, .None on failure (empty, invalid chars, overflow, negative sign).
1932
+ */
1933
+ parse_u32 : (fn(self : Self) -> Option(u32))(
1934
+ match(
1935
+ self._bytes,
1936
+ .None =>.None,
1962
1937
  .Some(al) => {
1963
1938
  total_bytes := al.len();
1964
1939
  cond(
1965
- (total_bytes == usize(0)) => .None,
1940
+ (total_bytes == usize(0)) =>.None,
1966
1941
  true => {
1967
1942
  idx := usize(0);
1968
1943
  first_byte_opt := al.get(usize(0));
1969
- match(first_byte_opt,
1944
+ match(
1945
+ first_byte_opt,
1970
1946
  .Some(first_byte) => {
1971
1947
  cond(
1972
1948
  (first_byte == u8(45)) => {
1973
- return .None;
1949
+ return(.None);
1974
1950
  },
1975
1951
  (first_byte == u8(43)) => {
1976
1952
  idx = usize(1);
@@ -1979,44 +1955,40 @@ impl(String,
1979
1955
  );
1980
1956
  },
1981
1957
  .None => {
1982
- return .None;
1958
+ return(.None);
1983
1959
  }
1984
1960
  );
1985
-
1986
1961
  cond(
1987
- (idx >= total_bytes) => .None,
1962
+ (idx >= total_bytes) =>.None,
1988
1963
  true => {
1989
1964
  result := u64(0);
1990
1965
  has_digit := false;
1991
-
1992
- while ((idx < total_bytes)),
1993
- (idx = (idx + usize(1))),
1994
- {
1966
+ while(idx < total_bytes, idx = (idx + usize(1)), {
1995
1967
  byte_opt := al.get(idx);
1996
- match(byte_opt,
1968
+ match(
1969
+ byte_opt,
1997
1970
  .Some(byte) => {
1998
1971
  cond(
1999
1972
  Self._is_digit_byte(byte) => {
2000
- digit := u64((byte - u8(48)));
1973
+ digit := u64(byte - u8(48));
2001
1974
  result = ((result * u64(10)) + digit);
2002
1975
  has_digit = true;
2003
1976
  },
2004
1977
  true => {
2005
- return .None;
1978
+ return(.None);
2006
1979
  }
2007
1980
  );
2008
1981
  },
2009
1982
  .None => {
2010
- return .None;
1983
+ return(.None);
2011
1984
  }
2012
1985
  );
2013
- };
2014
-
1986
+ });
2015
1987
  cond(
2016
- (!(has_digit)) => .None,
1988
+ (!(has_digit)) =>.None,
2017
1989
  true => cond(
2018
- (result > u64(4294967295)) => .None,
2019
- true => .Some(u32(result))
1990
+ (result > u64(4294967295)) =>.None,
1991
+ true =>.Some(u32(result))
2020
1992
  )
2021
1993
  )
2022
1994
  }
@@ -2026,27 +1998,28 @@ impl(String,
2026
1998
  }
2027
1999
  )
2028
2000
  ),
2029
-
2030
2001
  /**
2031
- * Parse the string as an unsigned 64-bit integer.
2032
- * Returns .Some(value) on success, .None on failure.
2033
- * Note: does not detect u64 overflow during accumulation.
2034
- */
2035
- parse_u64 : (fn(self: Self) -> Option(u64))(
2036
- match(self._bytes,
2037
- .None => .None,
2002
+ * Parse the string as an unsigned 64-bit integer.
2003
+ * Returns .Some(value) on success, .None on failure.
2004
+ * Note: does not detect u64 overflow during accumulation.
2005
+ */
2006
+ parse_u64 : (fn(self : Self) -> Option(u64))(
2007
+ match(
2008
+ self._bytes,
2009
+ .None =>.None,
2038
2010
  .Some(al) => {
2039
2011
  total_bytes := al.len();
2040
2012
  cond(
2041
- (total_bytes == usize(0)) => .None,
2013
+ (total_bytes == usize(0)) =>.None,
2042
2014
  true => {
2043
2015
  idx := usize(0);
2044
2016
  first_byte_opt := al.get(usize(0));
2045
- match(first_byte_opt,
2017
+ match(
2018
+ first_byte_opt,
2046
2019
  .Some(first_byte) => {
2047
2020
  cond(
2048
2021
  (first_byte == u8(45)) => {
2049
- return .None;
2022
+ return(.None);
2050
2023
  },
2051
2024
  (first_byte == u8(43)) => {
2052
2025
  idx = usize(1);
@@ -2055,42 +2028,38 @@ impl(String,
2055
2028
  );
2056
2029
  },
2057
2030
  .None => {
2058
- return .None;
2031
+ return(.None);
2059
2032
  }
2060
2033
  );
2061
-
2062
2034
  cond(
2063
- (idx >= total_bytes) => .None,
2035
+ (idx >= total_bytes) =>.None,
2064
2036
  true => {
2065
2037
  result := u64(0);
2066
2038
  has_digit := false;
2067
-
2068
- while ((idx < total_bytes)),
2069
- (idx = (idx + usize(1))),
2070
- {
2039
+ while(idx < total_bytes, idx = (idx + usize(1)), {
2071
2040
  byte_opt := al.get(idx);
2072
- match(byte_opt,
2041
+ match(
2042
+ byte_opt,
2073
2043
  .Some(byte) => {
2074
2044
  cond(
2075
2045
  Self._is_digit_byte(byte) => {
2076
- digit := u64((byte - u8(48)));
2046
+ digit := u64(byte - u8(48));
2077
2047
  result = ((result * u64(10)) + digit);
2078
2048
  has_digit = true;
2079
2049
  },
2080
2050
  true => {
2081
- return .None;
2051
+ return(.None);
2082
2052
  }
2083
2053
  );
2084
2054
  },
2085
2055
  .None => {
2086
- return .None;
2056
+ return(.None);
2087
2057
  }
2088
2058
  );
2089
- };
2090
-
2059
+ });
2091
2060
  cond(
2092
- (!(has_digit)) => .None,
2093
- true => .Some(result)
2061
+ (!(has_digit)) =>.None,
2062
+ true =>.Some(result)
2094
2063
  )
2095
2064
  }
2096
2065
  )
@@ -2099,14 +2068,14 @@ impl(String,
2099
2068
  }
2100
2069
  )
2101
2070
  ),
2102
-
2103
2071
  /**
2104
- * Parse the string as a boolean.
2105
- * Returns .Some(true) for "true", .Some(false) for "false", .None for anything else.
2106
- */
2107
- parse_bool : (fn(self: Self) -> Option(bool))(
2108
- match(self._bytes,
2109
- .None => .None,
2072
+ * Parse the string as a boolean.
2073
+ * Returns .Some(true) for "true", .Some(false) for "false", .None for anything else.
2074
+ */
2075
+ parse_bool : (fn(self : Self) -> Option(bool))(
2076
+ match(
2077
+ self._bytes,
2078
+ .None =>.None,
2110
2079
  .Some(al) => {
2111
2080
  total_bytes := al.len();
2112
2081
  cond(
@@ -2118,7 +2087,7 @@ impl(String,
2118
2087
  cond(
2119
2088
  ((b0 == u8(116)) && ((b1 == u8(114)) && ((b2 == u8(117)) && (b3 == u8(101))))) =>
2120
2089
  .Some(true),
2121
- true => .None
2090
+ true =>.None
2122
2091
  )
2123
2092
  },
2124
2093
  (total_bytes == usize(5)) => {
@@ -2130,51 +2099,57 @@ impl(String,
2130
2099
  cond(
2131
2100
  ((b0 == u8(102)) && ((b1 == u8(97)) && ((b2 == u8(108)) && ((b3 == u8(115)) && (b4 == u8(101)))))) =>
2132
2101
  .Some(false),
2133
- true => .None
2102
+ true =>.None
2134
2103
  )
2135
2104
  },
2136
- true => .None
2105
+ true =>.None
2137
2106
  )
2138
2107
  }
2139
2108
  )
2140
2109
  )
2141
2110
  );
2142
-
2143
2111
  /// Index trait implementation — access a single byte by index.
2144
2112
  /// Panics if the string is empty.
2145
- impl(String, Index(usize)(
2146
- Output : u8,
2147
- index : (fn(self: *(Self), idx: usize) -> *(Self.Output))(
2148
- match(self.*._bytes,
2149
- .Some(bytes) => &(bytes(idx)),
2150
- .None => panic("String: index on empty string")
2113
+ impl(
2114
+ String,
2115
+ Index(usize)(
2116
+ Output : u8,
2117
+ index : (fn(self : *(Self), idx : usize) -> *(Self.Output))(
2118
+ match(
2119
+ self.*._bytes,
2120
+ .Some(bytes) => &(bytes(idx)),
2121
+ .None => panic("String: index on empty string")
2122
+ )
2151
2123
  )
2152
2124
  )
2153
- ));
2154
-
2125
+ );
2155
2126
  /// Clone implementation — produces an independent byte-level copy.
2156
- impl(String, Clone(
2157
- clone : (fn(self: *(Self)) -> Self)(
2158
- match(self._bytes,
2159
- .None => Self(_bytes: .None),
2160
- .Some(al) => {
2161
- n := al.len();
2162
- cond(
2163
- (n == usize(0)) => Self(_bytes: .None),
2164
- true => {
2165
- buf := ArrayList(u8).with_capacity(n);
2166
- match(al._ptr,
2167
- .Some(ptr) => buf.extend_from_ptr(ptr, n),
2168
- .None => ()
2169
- );
2170
- Self(_bytes: .Some(buf))
2171
- }
2172
- )
2173
- }
2127
+ impl(
2128
+ String,
2129
+ Clone(
2130
+ clone : (fn(self : *(Self)) -> Self)(
2131
+ match(
2132
+ self._bytes,
2133
+ .None => Self(_bytes :.None),
2134
+ .Some(al) => {
2135
+ n := al.len();
2136
+ cond(
2137
+ (n == usize(0)) => Self(_bytes :.None),
2138
+ true => {
2139
+ buf := ArrayList(u8).with_capacity(n);
2140
+ match(
2141
+ al._ptr,
2142
+ .Some(ptr) => buf.extend_from_ptr(ptr, n),
2143
+ .None => ()
2144
+ );
2145
+ Self(_bytes :.Some(buf))
2146
+ }
2147
+ )
2148
+ }
2149
+ )
2174
2150
  )
2175
2151
  )
2176
- ));
2177
-
2152
+ );
2178
2153
  /// Like `assert`, but accepts a runtime `String` message (e.g. a template
2179
2154
  /// string with interpolation: `` `error: ${value}` ``).
2180
2155
  ///
@@ -2184,7 +2159,6 @@ impl(String, Clone(
2184
2159
  assert_dyn :: (fn(flag : bool, msg : String) -> unit)({
2185
2160
  assert(flag, msg.as_str());
2186
2161
  });
2187
-
2188
2162
  /// Like `panic`, but accepts a runtime `String` message (e.g. a template
2189
2163
  /// string with interpolation: `` `error: ${value}` ``).
2190
2164
  ///
@@ -2193,8 +2167,7 @@ assert_dyn :: (fn(flag : bool, msg : String) -> unit)({
2193
2167
  panic_dyn :: (fn(msg : String) -> unit)({
2194
2168
  panic(msg.as_str());
2195
2169
  });
2196
-
2197
- export
2170
+ export(
2198
2171
  String,
2199
2172
  StringError,
2200
2173
  StringChars,
@@ -2202,4 +2175,4 @@ export
2202
2175
  StringLines,
2203
2176
  assert_dyn,
2204
2177
  panic_dyn
2205
- ;
2178
+ );