@shd101wyy/yo 0.1.4 → 0.1.6

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 (38) hide show
  1. package/README.md +7 -6
  2. package/out/cjs/index.cjs +546 -535
  3. package/out/cjs/yo-cli.cjs +636 -623
  4. package/out/esm/index.mjs +478 -467
  5. package/out/types/src/codegen/codegen-c.d.ts +2 -0
  6. package/out/types/src/codegen/functions/context.d.ts +1 -0
  7. package/out/types/src/codegen/functions/generation.d.ts +10 -0
  8. package/out/types/src/codegen/utils/index.d.ts +1 -0
  9. package/out/types/src/env.d.ts +12 -1
  10. package/out/types/src/evaluator/builtins/build.d.ts +1 -0
  11. package/out/types/src/evaluator/context.d.ts +1 -0
  12. package/out/types/src/evaluator/types/enum.d.ts +1 -1
  13. package/out/types/src/evaluator/types/synthesizer.d.ts +6 -1
  14. package/out/types/src/expr.d.ts +2 -0
  15. package/out/types/src/target.d.ts +1 -0
  16. package/out/types/src/types/compatibility.d.ts +1 -1
  17. package/out/types/src/types/creators.d.ts +2 -1
  18. package/out/types/src/types/definitions.d.ts +11 -0
  19. package/out/types/src/types/guards.d.ts +2 -1
  20. package/out/types/src/types/tags.d.ts +2 -1
  21. package/out/types/src/value.d.ts +2 -1
  22. package/out/types/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +1 -1
  24. package/std/build.yo +2 -1
  25. package/std/collections/array_list.yo +133 -1
  26. package/std/encoding/html.yo +283 -0
  27. package/std/encoding/html_char_utils.yo +36 -0
  28. package/std/encoding/html_entities.yo +2262 -0
  29. package/std/encoding/punycode.yo +366 -0
  30. package/std/fmt/to_string.yo +5 -4
  31. package/std/glob/index.yo +2 -2
  32. package/std/libc/wctype.yo +55 -0
  33. package/std/path.yo +6 -6
  34. package/std/prelude.yo +193 -7
  35. package/std/regex/parser.yo +69 -4
  36. package/std/regex/vm.yo +18 -31
  37. package/std/string/string.yo +1388 -1337
  38. package/std/string/unicode.yo +242 -0
package/std/prelude.yo CHANGED
@@ -96,6 +96,8 @@ extern "Yo",
96
96
  fn(forall(T: Type), slice: Slice(T)) -> usize,
97
97
  __yo_slice_new :
98
98
  fn(forall(T: Type), ptr: *(T), length: usize) -> Slice(T),
99
+ __yo_slice_ptr :
100
+ fn(forall(T: Type), slice: Slice(T)) -> *(T),
99
101
 
100
102
  // C macro related
101
103
  __yo_c_macro_defined : (fn(comptime(name) : comptime_string) -> comptime(bool)),
@@ -110,13 +112,7 @@ extern "Yo",
110
112
  ;
111
113
  export __yo_as;
112
114
 
113
- assert :: (fn(flag : bool, (comptime(msg) : comptime_string) ?= "Assertion failed.") -> unit)
114
- cond(
115
- flag => (),
116
- true => panic(msg)
117
- )
118
- ;
119
- export assert;
115
+
120
116
 
121
117
  // unsafe module
122
118
  unsafe :: impl {
@@ -3202,6 +3198,9 @@ impl(forall(T : Type), Slice(T),
3202
3198
  ),
3203
3199
  len : (fn(self : Self) -> usize)(
3204
3200
  __yo_slice_len(self)
3201
+ ),
3202
+ ptr : (fn(self : Self) -> *(T))(
3203
+ __yo_slice_ptr(self)
3205
3204
  )
3206
3205
  );
3207
3206
 
@@ -3215,6 +3214,9 @@ impl(str,
3215
3214
  ),
3216
3215
  len : (fn(self : Self) -> usize)(
3217
3216
  __yo_slice_len(self.bytes)
3217
+ ),
3218
+ ptr : (fn(self : Self) -> *(u8))(
3219
+ __yo_slice_ptr(self.bytes)
3218
3220
  )
3219
3221
  );
3220
3222
 
@@ -3271,6 +3273,14 @@ impl(str, Ord(str)(
3271
3273
 
3272
3274
  export str;
3273
3275
 
3276
+ assert :: (fn(flag : bool, (msg : str) ?= "Assertion failed.") -> unit)
3277
+ cond(
3278
+ flag => (),
3279
+ true => panic(msg)
3280
+ )
3281
+ ;
3282
+ export assert;
3283
+
3274
3284
 
3275
3285
  /// ComptimeList
3276
3286
  impl(forall(T : Type), ComptimeList(T), Comptime());
@@ -3419,6 +3429,85 @@ impl(forall(T : Type), Option(T),
3419
3429
  )
3420
3430
  );
3421
3431
 
3432
+ // Functional combinators for Option(T)
3433
+ impl(forall(T : Type), Option(T),
3434
+ map : (fn(forall(B : Type), self : Self, f : Impl(Fn(a : T) -> B)) -> Option(B))(
3435
+ match(self,
3436
+ .Some(value) => Option(B).Some(f(value)),
3437
+ .None => Option(B).None
3438
+ )
3439
+ ),
3440
+
3441
+ and_then : (fn(forall(B : Type), self : Self, f : Impl(Fn(a : T) -> Option(B))) -> Option(B))(
3442
+ match(self,
3443
+ .Some(value) => f(value),
3444
+ .None => Option(B).None
3445
+ )
3446
+ ),
3447
+
3448
+ filter : (fn(self : Self, predicate : Impl(Fn(a : T) -> bool)) -> Option(T))(
3449
+ match(self,
3450
+ .Some(value) => cond(
3451
+ predicate(value) => Option(T).Some(value),
3452
+ true => Option(T).None
3453
+ ),
3454
+ .None => Option(T).None
3455
+ )
3456
+ ),
3457
+
3458
+ or_else : (fn(self : Self, f : Impl(Fn() -> Option(T))) -> Option(T))(
3459
+ match(self,
3460
+ .Some(value) => Option(T).Some(value),
3461
+ .None => f()
3462
+ )
3463
+ ),
3464
+
3465
+ map_or : (fn(forall(B : Type), self : Self, default_val : B, f : Impl(Fn(a : T) -> B)) -> B)(
3466
+ match(self,
3467
+ .Some(value) => f(value),
3468
+ .None => default_val
3469
+ )
3470
+ ),
3471
+
3472
+ map_or_else : (fn(forall(B : Type), self : Self, default_fn : Impl(Fn() -> B), f : Impl(Fn(a : T) -> B)) -> B)(
3473
+ match(self,
3474
+ .Some(value) => f(value),
3475
+ .None => default_fn()
3476
+ )
3477
+ ),
3478
+
3479
+ and : (fn(forall(B : Type), self : Self, optb : Option(B)) -> Option(B))(
3480
+ match(self,
3481
+ .Some(_) => optb,
3482
+ .None => Option(B).None
3483
+ )
3484
+ ),
3485
+
3486
+ or : (fn(self : Self, optb : Option(T)) -> Option(T))(
3487
+ match(self,
3488
+ .Some(value) => Option(T).Some(value),
3489
+ .None => optb
3490
+ )
3491
+ ),
3492
+
3493
+ unwrap_or_else : (fn(self : Self, f : Impl(Fn() -> T)) -> T)(
3494
+ match(self,
3495
+ .Some(value) => value,
3496
+ .None => f()
3497
+ )
3498
+ )
3499
+ );
3500
+
3501
+ // Flatten for nested Option
3502
+ impl(forall(T : Type), Option(Option(T)),
3503
+ flatten : (fn(self : Self) -> Option(T))(
3504
+ match(self,
3505
+ .Some(inner) => inner,
3506
+ .None => Option(T).None
3507
+ )
3508
+ )
3509
+ );
3510
+
3422
3511
  // Option(T) implements Comptime when T implements Comptime
3423
3512
  impl(forall(T : Type), where(T <: Comptime), Option(T), Comptime());
3424
3513
 
@@ -3503,6 +3592,103 @@ impl(forall(OkType : Type, ErrorType : Type), Result(OkType, ErrorType),
3503
3592
  )
3504
3593
  );
3505
3594
 
3595
+ // Functional combinators for Result(OkType, ErrorType)
3596
+ impl(forall(OkType : Type, ErrorType : Type), Result(OkType, ErrorType),
3597
+ map : (fn(forall(B : Type), self : Self, f : Impl(Fn(a : OkType) -> B)) -> Result(B, ErrorType))(
3598
+ match(self,
3599
+ .Ok(value) => Result(B, ErrorType).Ok(f(value)),
3600
+ .Err(error) => Result(B, ErrorType).Err(error)
3601
+ )
3602
+ ),
3603
+
3604
+ map_err : (fn(forall(F : Type), self : Self, f : Impl(Fn(a : ErrorType) -> F)) -> Result(OkType, F))(
3605
+ match(self,
3606
+ .Ok(value) => Result(OkType, F).Ok(value),
3607
+ .Err(error) => Result(OkType, F).Err(f(error))
3608
+ )
3609
+ ),
3610
+
3611
+ and_then : (fn(forall(B : Type), self : Self, f : Impl(Fn(a : OkType) -> Result(B, ErrorType))) -> Result(B, ErrorType))(
3612
+ match(self,
3613
+ .Ok(value) => f(value),
3614
+ .Err(error) => Result(B, ErrorType).Err(error)
3615
+ )
3616
+ ),
3617
+
3618
+ or_else : (fn(forall(F : Type), self : Self, f : Impl(Fn(a : ErrorType) -> Result(OkType, F))) -> Result(OkType, F))(
3619
+ match(self,
3620
+ .Ok(value) => Result(OkType, F).Ok(value),
3621
+ .Err(error) => f(error)
3622
+ )
3623
+ ),
3624
+
3625
+ and : (fn(forall(B : Type), self : Self, res : Result(B, ErrorType)) -> Result(B, ErrorType))(
3626
+ match(self,
3627
+ .Ok(_) => res,
3628
+ .Err(error) => Result(B, ErrorType).Err(error)
3629
+ )
3630
+ ),
3631
+
3632
+ or : (fn(forall(F : Type), self : Self, res : Result(OkType, F)) -> Result(OkType, F))(
3633
+ match(self,
3634
+ .Ok(value) => Result(OkType, F).Ok(value),
3635
+ .Err(_) => res
3636
+ )
3637
+ ),
3638
+
3639
+ ok : (fn(self : Self) -> Option(OkType))(
3640
+ match(self,
3641
+ .Ok(value) => Option(OkType).Some(value),
3642
+ .Err(_) => Option(OkType).None
3643
+ )
3644
+ ),
3645
+
3646
+ err : (fn(self : Self) -> Option(ErrorType))(
3647
+ match(self,
3648
+ .Ok(_) => Option(ErrorType).None,
3649
+ .Err(error) => Option(ErrorType).Some(error)
3650
+ )
3651
+ ),
3652
+
3653
+ map_or : (fn(forall(B : Type), self : Self, default_val : B, f : Impl(Fn(a : OkType) -> B)) -> B)(
3654
+ match(self,
3655
+ .Ok(value) => f(value),
3656
+ .Err(_) => default_val
3657
+ )
3658
+ ),
3659
+
3660
+ map_or_else : (fn(forall(B : Type), self : Self, default_fn : Impl(Fn(a : ErrorType) -> B), f : Impl(Fn(a : OkType) -> B)) -> B)(
3661
+ match(self,
3662
+ .Ok(value) => f(value),
3663
+ .Err(error) => default_fn(error)
3664
+ )
3665
+ ),
3666
+
3667
+ unwrap_or_else : (fn(self : Self, f : Impl(Fn(a : ErrorType) -> OkType)) -> OkType)(
3668
+ match(self,
3669
+ .Ok(value) => value,
3670
+ .Err(error) => f(error)
3671
+ )
3672
+ )
3673
+ );
3674
+
3675
+ // Option -> Result conversion (defined after Result)
3676
+ impl(forall(T : Type), Option(T),
3677
+ ok_or : (fn(forall(E : Type), self : Self, err : E) -> Result(T, E))(
3678
+ match(self,
3679
+ .Some(value) => Result(T, E).Ok(value),
3680
+ .None => Result(T, E).Err(err)
3681
+ )
3682
+ ),
3683
+
3684
+ ok_or_else : (fn(forall(E : Type), self : Self, err_fn : Impl(Fn() -> E)) -> Result(T, E))(
3685
+ match(self,
3686
+ .Some(value) => Result(T, E).Ok(value),
3687
+ .None => Result(T, E).Err(err_fn())
3688
+ )
3689
+ )
3690
+ );
3691
+
3506
3692
  // Result(OkType, ErrorType) implements Comptime when both types implement Comptime
3507
3693
  impl(forall(OkType : Type, ErrorType : Type), where(OkType <: Comptime, ErrorType <: Comptime), Result(OkType, ErrorType), Comptime());
3508
3694
 
@@ -189,6 +189,27 @@ impl(RegexParser,
189
189
  r
190
190
  }),
191
191
 
192
+ // Parse \xHH hex escape — reads exactly 2 hex digits and returns the codepoint.
193
+ _parse_hex_byte : (fn(self : Self) -> Option(u32))({
194
+ if(((self._pos + usize(2)) > self._bytes.len()), { return .None; });
195
+ (h1 : u8) = self._bytes.get(self._pos).unwrap();
196
+ (h2 : u8) = self._bytes.get((self._pos + usize(1))).unwrap();
197
+ (v1 : i32) = cond(
198
+ ((h1 >= u8(48)) && (h1 <= u8(57))) => (i32(h1) - i32(48)),
199
+ ((h1 >= u8(65)) && (h1 <= u8(70))) => ((i32(h1) - i32(65)) + i32(10)),
200
+ ((h1 >= u8(97)) && (h1 <= u8(102))) => ((i32(h1) - i32(97)) + i32(10)),
201
+ true => { return .None; }
202
+ );
203
+ (v2 : i32) = cond(
204
+ ((h2 >= u8(48)) && (h2 <= u8(57))) => (i32(h2) - i32(48)),
205
+ ((h2 >= u8(65)) && (h2 <= u8(70))) => ((i32(h2) - i32(65)) + i32(10)),
206
+ ((h2 >= u8(97)) && (h2 <= u8(102))) => ((i32(h2) - i32(97)) + i32(10)),
207
+ true => { return .None; }
208
+ );
209
+ self._pos = (self._pos + usize(2));
210
+ .Some(u32(((v1 << i32(4)) | v2)))
211
+ }),
212
+
192
213
  _parse_class_escape : (fn(self : Self) -> Result(ArrayList(CharRange), String))({
193
214
  b := self._advance();
194
215
  match(b,
@@ -219,6 +240,14 @@ impl(RegexParser,
219
240
  r.push(CharRange(low: u32(33), high: u32(0x10FFFF)));
220
241
  .Ok(r)
221
242
  },
243
+ (ch == u8(120)) => {
244
+ r := ArrayList(CharRange).new();
245
+ match(self._parse_hex_byte(),
246
+ .Some(v) => r.push(CharRange(low: v, high: v)),
247
+ .None => r.push(CharRange(low: u32(ch), high: u32(ch)))
248
+ );
249
+ .Ok(r)
250
+ },
222
251
  true => {
223
252
  r := ArrayList(CharRange).new();
224
253
  codepoint := self._escape_char_codepoint(ch);
@@ -246,6 +275,31 @@ impl(RegexParser,
246
275
  (end_first == u8(93)) => {
247
276
  ranges.push(CharRange(low: low, high: low));
248
277
  },
278
+ (end_first == u8(92)) => {
279
+ // High end is an escape sequence (e.g. \x20, \0, \n)
280
+ self._pos = (self._pos + usize(1));
281
+ self._pos = (self._pos + usize(1));
282
+ esc := self._parse_class_escape();
283
+ match(esc,
284
+ .Ok(esc_ranges) => {
285
+ if(((esc_ranges.len() == usize(1)) && (esc_ranges.get(usize(0)).unwrap().low == esc_ranges.get(usize(0)).unwrap().high)), {
286
+ (high : u32) = esc_ranges.get(usize(0)).unwrap().low;
287
+ ranges.push(CharRange(low: low, high: high));
288
+ }, {
289
+ // Multi-range escape like \d can't be range endpoint; treat dash as literal
290
+ ranges.push(CharRange(low: low, high: low));
291
+ ranges.push(CharRange(low: u32(45), high: u32(45)));
292
+ j := usize(0);
293
+ while (j < esc_ranges.len()), (j = (j + usize(1))), {
294
+ ranges.push(esc_ranges.get(j).unwrap());
295
+ };
296
+ });
297
+ },
298
+ .Err(_e) => {
299
+ ranges.push(CharRange(low: low, high: low));
300
+ }
301
+ );
302
+ },
249
303
  true => {
250
304
  // Consume dash
251
305
  self._pos = (self._pos + usize(1));
@@ -284,10 +338,16 @@ impl(RegexParser,
284
338
  esc := self._parse_class_escape();
285
339
  match(esc,
286
340
  .Ok(esc_ranges) => {
287
- j := usize(0);
288
- while (j < esc_ranges.len()), (j = (j + usize(1))), {
289
- ranges.push(esc_ranges.get(j).unwrap());
290
- };
341
+ // If escape produced a single codepoint, check for range (e.g. \0-\x20)
342
+ if(((esc_ranges.len() == usize(1)) && (esc_ranges.get(usize(0)).unwrap().low == esc_ranges.get(usize(0)).unwrap().high)), {
343
+ (low : u32) = esc_ranges.get(usize(0)).unwrap().low;
344
+ self._try_parse_char_range(ranges, low);
345
+ }, {
346
+ j := usize(0);
347
+ while (j < esc_ranges.len()), (j = (j + usize(1))), {
348
+ ranges.push(esc_ranges.get(j).unwrap());
349
+ };
350
+ });
291
351
  },
292
352
  .Err(e) => { return .Err(e); }
293
353
  );
@@ -452,6 +512,11 @@ impl(RegexParser,
452
512
  (ch == u8(112)) => self._parse_unicode_property(false),
453
513
  // Negated unicode property \P{Name}
454
514
  (ch == u8(80)) => self._parse_unicode_property(true),
515
+ // Hex escape \xHH
516
+ (ch == u8(120)) => match(self._parse_hex_byte(),
517
+ .Some(v) => .Ok(RegexNode.literal(v)),
518
+ .None => .Ok(RegexNode.literal(u32(ch)))
519
+ ),
455
520
  true => .Ok(RegexNode.literal(self._escape_char_codepoint(ch)))
456
521
  ),
457
522
  .None => .Err(`Unexpected end of pattern after backslash`)
package/std/regex/vm.yo CHANGED
@@ -22,21 +22,18 @@ NfaThread :: object(
22
22
  impl(NfaThread,
23
23
  new : (fn(pc : usize, n_slots : usize) -> Self)({
24
24
  s := ArrayList(usize).with_capacity(n_slots);
25
- i := usize(0);
26
- while (i < n_slots), (i = (i + usize(1))), {
27
- // usize.MAX signals "unset"
28
- s.push(usize.MAX);
29
- };
25
+ // usize.MAX = 0xFF..FF, so memset with 0xFF fills each byte
26
+ s.resize_with_byte(n_slots, int(255));
30
27
  Self(pc: pc, slots: s)
31
28
  }),
32
29
 
33
30
  // Clone a thread with a new PC
34
31
  fork : (fn(self : Self, new_pc : usize) -> Self)({
35
32
  new_slots := ArrayList(usize).with_capacity(self.slots.len());
36
- i := usize(0);
37
- while (i < self.slots.len()), (i = (i + usize(1))), {
38
- new_slots.push(self.slots.get(i).unwrap());
39
- };
33
+ match(self.slots.ptr(),
34
+ .Some(src) => new_slots.extend_from_ptr(src, self.slots.len()),
35
+ .None => ()
36
+ );
40
37
  Self(pc: new_pc, slots: new_slots)
41
38
  })
42
39
  );
@@ -233,14 +230,15 @@ impl(NfaVm,
233
230
  true => ()
234
231
  );
235
232
 
236
- is_seen := seen.*.get(thread.pc).unwrap();
233
+ // Already checked bounds above: thread.pc < instructions.len()
234
+ is_seen := seen.*.get_unchecked(thread.pc);
237
235
  cond(
238
236
  is_seen => { return (); },
239
237
  true => ()
240
238
  );
241
- seen.*.set(thread.pc, true);
239
+ seen.*.set_unchecked(thread.pc, true);
242
240
 
243
- instr := self._program.instructions.get(thread.pc).unwrap();
241
+ instr := self._program.instructions.get_unchecked(thread.pc);
244
242
 
245
243
  match(instr.kind,
246
244
  .Split => {
@@ -326,10 +324,7 @@ impl(NfaVm,
326
324
  sub_next := ArrayList(NfaThread).new();
327
325
 
328
326
  sub_seen := ArrayList(bool).with_capacity(self._program.instructions.len());
329
- si := usize(0);
330
- while (si < self._program.instructions.len()), (si = (si + usize(1))), {
331
- sub_seen.push(false);
332
- };
327
+ sub_seen.resize_with_byte(self._program.instructions.len(), int(0));
333
328
 
334
329
  initial := NfaThread.new(sub_start_pc, self._n_slots);
335
330
  self._add_thread(&(sub_current), initial, start_byte, &(sub_seen));
@@ -376,10 +371,7 @@ impl(NfaVm,
376
371
  sub_blen := decoded.byte_len;
377
372
 
378
373
  // Clear seen
379
- sj := usize(0);
380
- while (sj < sub_seen.len()), (sj = (sj + usize(1))), {
381
- sub_seen.set(sj, false);
382
- };
374
+ sub_seen.fill_with_byte(int(0));
383
375
 
384
376
  // Process consuming instructions
385
377
  st2 := usize(0);
@@ -446,11 +438,9 @@ impl(NfaVm,
446
438
 
447
439
  seen := ArrayList(bool).with_capacity(self._program.instructions.len());
448
440
  next_seen := ArrayList(bool).with_capacity(self._program.instructions.len());
449
- i := usize(0);
450
- while (i < self._program.instructions.len()), (i = (i + usize(1))), {
451
- seen.push(false);
452
- next_seen.push(false);
453
- };
441
+ // Fill with false (0x00) using memset
442
+ seen.resize_with_byte(self._program.instructions.len(), int(0));
443
+ next_seen.resize_with_byte(self._program.instructions.len(), int(0));
454
444
 
455
445
  initial := NfaThread.new(usize(0), self._n_slots);
456
446
  self._add_thread(&(current), initial, start_byte, &(seen));
@@ -474,12 +464,9 @@ impl(NfaVm,
474
464
  true => ()
475
465
  );
476
466
 
477
- // Clear seen flags for this generation
478
- j := usize(0);
479
- while (j < seen.len()), (j = (j + usize(1))), {
480
- seen.set(j, false);
481
- next_seen.set(j, false);
482
- };
467
+ // Clear seen flags for this generation using memset
468
+ seen.fill_with_byte(int(0));
469
+ next_seen.fill_with_byte(int(0));
483
470
 
484
471
  // Process deferred threads targeting this byte_pos
485
472
  new_deferred := ArrayList(DeferredThread).new();