-
Notifications
You must be signed in to change notification settings - Fork 106
/
Copy pathintrinsics.mbt
3190 lines (3047 loc) · 91.3 KB
/
intrinsics.mbt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Evaluates an expression and discards its result. This is useful when you want
/// to execute an expression for its side effects but don't care about its return
/// value, or when you want to explicitly indicate that a value is intentionally
/// unused.
///
/// Parameters:
///
/// * `value` : The value to be ignored. Can be of any type.
///
/// Example:
///
/// ```moonbit
/// test "ignore" {
/// let x = 42
/// ignore(x) // Explicitly ignore the value
/// let mut sum = 0
/// ignore([1, 2, 3].iter().each(fn(x) { sum = sum + x })) // Ignore the Unit return value of each()
/// }
/// ```
pub fn ignore[T](t : T) -> Unit = "%ignore"
///|
/// Tests if two values are physically equal (i.e., point to the same memory
/// location). Unlike structural equality testing (`==`), this function checks if
/// two references point to exactly the same object in memory.
///
/// Parameters:
///
/// * `first` : The first value to compare.
/// * `second` : The second value to compare.
/// * `T` : The type parameter representing the type of values being compared.
///
/// Returns `true` if both values refer to the same object in memory, `false`
/// otherwise.
///
/// Example:
///
/// ```moonbit
/// test "physical_equal" {
/// let arr1 = [1, 2, 3]
/// let arr2 = arr1
/// let arr3 = [1, 2, 3]
/// inspect!(physical_equal(arr1, arr2), content="true") // Same object
/// inspect!(physical_equal(arr1, arr3), content="false") // Different objects with same content
/// }
/// ```
pub fn physical_equal[T](a : T, b : T) -> Bool = "%refeq"
///|
/// Aborts the program with an error message. Always causes a panic, regardless
/// of the message provided.
///
/// Parameters:
///
/// * `message` : A string containing the error message to be displayed when
/// aborting.
///
/// Returns a value of type `T`. However, this function never actually returns a
/// value as it always causes a panic.
///
/// Example:
///
/// ```moonbit
/// test "panic abort/with_message" {
/// let x : Int = abort("Something went wrong") // specify return type as Int
/// ignore(x)
/// }
/// ```
pub fn abort[T](msg : String) -> T {
ignore(msg)
panic()
}
///|
pub fn panic[T]() -> T = "%panic"
// Bool primitive ops
///|
/// Performs logical negation on a boolean value.
///
/// Parameters:
///
/// * `value` : The boolean value to negate.
///
/// Returns the logical NOT of the input value: `true` if the input is `false`,
/// and `false` if the input is `true`.
///
/// Example:
///
/// ```moonbit
/// test "not" {
/// inspect!(not(true), content="false")
/// inspect!(not(false), content="true")
/// }
/// ```
pub fn not(x : Bool) -> Bool = "%bool_not"
///|
/// Compares two boolean values for equality.
///
/// Parameters:
///
/// * `self` : The first boolean value to compare.
/// * `other` : The second boolean value to compare.
///
/// Returns `true` if both boolean values are equal (either both `true` or both
/// `false`), `false` otherwise.
///
/// Example:
///
/// ```moonbit
/// test "Bool::op_equal" {
/// inspect!(true == true, content="true")
/// inspect!(false == true, content="false")
/// inspect!(true == false, content="false")
/// inspect!(false == false, content="true")
/// }
/// ```
pub impl Eq for Bool with op_equal(self : Bool, other : Bool) -> Bool = "%bool_eq"
///|
/// Compares two boolean values and returns their relative order. This is a
/// deprecated method and users should use `compare` instead.
///
/// Parameters:
///
/// * `self` : The first boolean value to compare.
/// * `other` : The second boolean value to compare against.
///
/// Returns an integer indicating the relative order:
///
/// * A negative value if `self` is less than `other` (i.e., `self` is `false`
/// and `other` is `true`)
/// * Zero if `self` equals `other`
/// * A positive value if `self` is greater than `other` (i.e., `self` is `true`
/// and `other` is `false`)
///
/// Example:
///
/// ```moonbit
/// test "Bool::op_compare/deprecated" {
/// let t = true
/// let f = false
/// // This usage is deprecated, use compare() instead
/// inspect!(t.compare(f), content="1")
/// inspect!(f.compare(t), content="-1")
/// inspect!(t.compare(t), content="0")
/// }
/// ```
///
#deprecated("Use `compare` instead")
#coverage.skip
pub fn Bool::op_compare(self : Bool, other : Bool) -> Int = "%bool_compare"
///|
/// Compares two boolean values and returns their relative order. The comparison
/// follows the rule that `false` is less than `true`.
///
/// Parameters:
///
/// * `self` : The first boolean value to compare.
/// * `other` : The second boolean value to compare against.
///
/// Returns an integer indicating the relative order:
///
/// * A negative value if `self` is `false` and `other` is `true`
/// * Zero if `self` equals `other`
/// * A positive value if `self` is `true` and `other` is `false`
///
/// Example:
///
/// ```moonbit
/// test "Bool::compare" {
/// inspect!(true.compare(false), content="1") // true > false
/// inspect!(false.compare(true), content="-1") // false < true
/// inspect!(true.compare(true), content="0") // true = true
/// }
/// ```
pub impl Compare for Bool with compare(self, other) = "%bool_compare"
///|
/// Returns the default value for the `Bool` type, which is `false`.
///
/// Returns a `Bool` value that represents the default state of a boolean value.
///
/// Example:
///
/// ```moonbit
/// test "Bool::default" {
/// let b : Bool = Bool::default()
/// inspect!(b, content="false")
/// }
/// ```
pub impl Default for Bool with default() = "%bool_default"
// int32 primitive ops
///|
/// Performs arithmetic negation on an integer value, returning its additive
/// inverse.
///
/// Parameters:
///
/// * `self` : The integer value to negate.
///
/// Returns the negation of the input value. For all inputs except
/// `Int::min_value()`, returns the value with opposite sign. When the input is
/// `Int::min_value()`, returns `Int::min_value()` due to two's complement
/// representation.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_neg" {
/// inspect!(-42, content="-42")
/// inspect!(42, content="42")
/// inspect!(--2147483647, content="2147483647") // negating near min value
/// }
/// ```
pub impl Neg for Int with op_neg(self) = "%i32_neg"
///|
/// Adds two 32-bit signed integers. Performs two's complement arithmetic, which
/// means the operation will wrap around if the result exceeds the range of a
/// 32-bit integer.
///
/// Parameters:
///
/// * `self` : The first integer operand.
/// * `other` : The second integer operand.
///
/// Returns a new integer that is the sum of the two operands. If the
/// mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
/// 2,147,483,647), the result wraps around according to two's complement rules.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_add" {
/// inspect!(42 + 1, content="43")
/// inspect!(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
/// }
/// ```
pub impl Add for Int with op_add(self, other) = "%i32_add"
///|
/// Performs subtraction between two 32-bit integers, following standard two's
/// complement arithmetic rules. When the result overflows or underflows, it
/// wraps around within the 32-bit integer range.
///
/// Parameters:
///
/// * `self` : The minuend (the number being subtracted from).
/// * `other` : The subtrahend (the number to subtract).
///
/// Returns the difference between `self` and `other`.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_sub" {
/// let a = 42
/// let b = 10
/// inspect!(a - b, content="32")
/// let max = 2147483647 // Int maximum value
/// inspect!(max - -1, content="-2147483648") // Overflow case
/// }
/// ```
pub impl Sub for Int with op_sub(self, other) = "%i32_sub"
///|
/// Multiplies two 32-bit integers. This is the implementation of the `*`
/// operator for `Int`.
///
/// Parameters:
///
/// * `self` : The first integer operand.
/// * `other` : The second integer operand.
///
/// Returns the product of the two integers. If the result overflows the range of
/// `Int`, it wraps around according to two's complement arithmetic.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_mul" {
/// inspect!(42 * 2, content="84")
/// inspect!(-10 * 3, content="-30")
/// let max = 2147483647 // Int.max_value
/// inspect!(max * 2, content="-2") // Overflow wraps around
/// }
/// ```
pub impl Mul for Int with op_mul(self, other) = "%i32_mul"
///|
/// Performs integer division between two 32-bit integers. The result is
/// truncated towards zero (rounds down for positive numbers and up for negative
/// numbers).
///
/// Parameters:
///
/// * `dividend` : The first integer operand to be divided.
/// * `divisor` : The second integer operand that divides the dividend.
///
/// Returns the quotient of the division operation.
///
/// Throws a panic if `divisor` is zero.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_div" {
/// inspect!(10 / 3, content="3") // truncates towards zero
/// inspect!(-10 / 3, content="-3")
/// inspect!(10 / -3, content="-3")
/// }
///
/// test "panic Int::op_div/division_by_zero" {
/// ignore(42 / 0) // Panics with division by zero
/// }
/// ```
pub impl Div for Int with op_div(self, other) = "%i32_div"
///|
/// Calculates the remainder of dividing one integer by another. The result
/// follows the formula `dividend - (dividend / divisor) * divisor`, maintaining
/// the same sign as the dividend.
///
/// Parameters:
///
/// * `self` : The dividend (the number being divided).
/// * `other` : The divisor (the number to divide by).
///
/// Returns the remainder of the division. If `other` is 0, the behavior is
/// undefined.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_mod" {
/// inspect!(7 % 3, content="1")
/// inspect!(-7 % 3, content="-1")
/// inspect!(7 % -3, content="1")
/// }
///
/// test "panic Int::op_mod/division_by_zero" {
/// ignore(7 % 0) // Panics with division by zero
/// }
/// ```
pub impl Mod for Int with op_mod(self, other) = "%i32_mod"
///|
/// Performs a bitwise NOT operation on a 32-bit integer. Flips each bit in the
/// integer's binary representation (0 becomes 1 and 1 becomes 0).
///
/// Parameters:
///
/// * `value` : The 32-bit integer on which to perform the bitwise NOT operation.
///
/// Returns a new integer with all bits flipped from the input value.
///
/// Example:
///
/// ```moonbit
/// test "Int::lnot" {
/// let a = -1 // All bits are 1
/// let b = 0 // All bits are 0
/// inspect!(a.lnot(), content="0")
/// inspect!(b.lnot(), content="-1")
/// }
/// ```
pub fn Int::lnot(self : Int) -> Int = "%i32_lnot"
///|
/// Performs a bitwise AND operation between two 32-bit integers. Each bit in the
/// result is set to 1 only if the corresponding bits in both operands are 1.
///
/// Parameters:
///
/// * `self` : The first 32-bit integer operand.
/// * `other` : The second 32-bit integer operand.
///
/// Returns the result of the bitwise AND operation. The resulting value has a
/// bit set to 1 at each position where both input integers have a bit set to 1.
///
/// Example:
///
/// ```moonbit
/// test "Int::land" {
/// let x = 0xF0 // 11110000
/// let y = 0xAA // 10101010
/// inspect!(x & y, content="160") // 10100000 = 160
/// }
/// ```
pub fn Int::land(self : Int, other : Int) -> Int = "%i32_land"
///|
/// Performs a bitwise OR operation between two 32-bit integers. For each bit
/// position, the result is 1 if at least one of the corresponding bits in either
/// operand is 1.
///
/// Parameters:
///
/// * `self` : The first integer operand.
/// * `other` : The second integer operand.
///
/// Returns a new integer where each bit is set to 1 if at least one of the
/// corresponding bits in either operand is 1, and 0 otherwise.
///
/// Example:
///
/// ```moonbit
/// test "Int::lor" {
/// let x = 0xF0F0 // 1111_0000_1111_0000
/// let y = 0x0F0F // 0000_1111_0000_1111
/// inspect!(x | y, content="65535") // 1111_1111_1111_1111 = 65535
/// }
/// ```
pub fn Int::lor(self : Int, other : Int) -> Int = "%i32_lor"
///|
/// Performs a bitwise XOR operation between two integers.
///
/// Parameters:
///
/// * `self` : The first integer operand.
/// * `other` : The second integer operand.
///
/// Returns a new integer where each bit is set to 1 if the corresponding bits in
/// the operands are different, and 0 if they are the same.
///
/// Example:
///
/// ```moonbit
/// test "Int::lxor" {
/// let x = 0xF0F0 // 1111_0000_1111_0000
/// let y = 0x0F0F // 0000_1111_0000_1111
/// inspect!(x ^ y, content="65535") // 1111_1111_1111_1111
/// inspect!(x ^ x, content="0") // XOR with self gives 0
/// }
/// ```
pub fn Int::lxor(self : Int, other : Int) -> Int = "%i32_lxor"
///|
/// Performs a left shift operation on a 32-bit integer. Shifts each bit in the
/// integer to the left by the specified number of positions, filling the
/// rightmost positions with zeros.
///
/// Parameters:
///
/// * `self` : The integer value to be shifted.
/// * `shift` : The number of positions to shift. Must be a non-negative value
/// less than 32. Values outside this range will be masked with `& 31`.
///
/// Returns a new integer with bits shifted left by the specified number of
/// positions. For each position shifted, the rightmost bit is filled with 0, and
/// the leftmost bit is discarded.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_shl" {
/// let x = 1
/// inspect!(x << 3, content="8") // Binary: 1 -> 1000
/// let y = -4
/// inspect!(y << 2, content="-16") // Binary: 100 -> 10000
/// }
/// ```
pub impl Shl for Int with op_shl(self, other) = "%i32_shl"
///|
/// Performs an arithmetic right shift operation on an integer value. Shifts the
/// bits of the first operand to the right by the number of positions specified
/// by the second operand. The sign bit is preserved and copied to the leftmost
/// positions.
///
/// Parameters:
///
/// * `self` : The integer value to be shifted.
/// * `shift` : The number of positions to shift the bits to the right. Must be
/// non-negative.
///
/// Returns an integer representing the result of the arithmetic right shift
/// operation.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_shr" {
/// let n = -16
/// inspect!(n >> 2, content="-4") // Sign bit is preserved during shift
/// let p = 16
/// inspect!(p >> 2, content="4") // Regular right shift for positive numbers
/// }
/// ```
pub impl Shr for Int with op_shr(self, other) = "%i32_shr"
///|
/// Performs a left shift operation on a 32-bit integer. Shifts each bit in the
/// integer to the left by the specified number of positions, filling the vacated
/// bit positions with zeros.
///
/// Parameters:
///
/// * `self` : The integer value to be shifted.
/// * `shift` : The number of positions to shift the bits to the left.
///
/// Returns an integer containing the result of shifting `self` left by `shift`
/// positions.
///
/// Example:
///
/// ```moonbit
/// test "Int::lsl" {
/// let x = 1
/// inspect!(x << 3, content="8") // Binary: 1 -> 1000
/// let y = 42
/// inspect!(y << 2, content="168") // Binary: 101010 -> 10101000
/// }
/// ```
///
#deprecated("Use infix operator `<<` instead")
#coverage.skip
pub fn Int::lsl(self : Int, other : Int) -> Int = "%i32_shl"
///|
/// Performs a left shift operation on a 32-bit integer. Shifts the bits of the
/// first operand to the left by the specified number of positions. The rightmost
/// positions are filled with zeros.
///
/// Parameters:
///
/// * `value` : The integer value to be shifted.
/// * `shift` : The number of positions to shift left. Must be non-negative and
/// less than 32.
///
/// Returns a new integer value after performing the left shift operation. The
/// value is equal to multiplying the input by 2 raised to the power of the shift
/// count.
///
/// Example:
///
/// ```moonbit
/// test "Int::shl" {
/// let x = 1
/// inspect!(x << 3, content="8") // Equivalent to x << 3
/// }
/// ```
///
#deprecated("Use infix operator `<<` instead")
#coverage.skip
pub fn Int::shl(self : Int, other : Int) -> Int = "%i32_shl"
///|
/// Performs a logical right shift operation on a signed 32-bit integer. In a
/// logical right shift, zeros are shifted in from the left, regardless of the
/// sign bit. This function is DEPRECATED and users should use `UInt` type with
/// the infix operator `>>` instead.
///
/// Parameters:
///
/// * `self` : The signed 32-bit integer value to be shifted.
/// * `shift` : The number of positions to shift right. Must be non-negative.
///
/// Returns a signed 32-bit integer containing the same bits as if the input were
/// treated as an unsigned integer and shifted right logically.
///
/// Example:
///
/// ```moonbit
/// test "Int::lsr" {
/// let x = -4 // Binary: 11111...11100
/// let unsigned = x.reinterpret_as_uint() // Convert to UInt first
/// inspect!(unsigned >> 1, content="2147483646") // Using the recommended operator
/// }
/// ```
///
#deprecated("Use UInt type and infix operator `>>` instead")
#coverage.skip
pub fn Int::lsr(self : Int, other : Int) -> Int {
(self.reinterpret_as_uint() >> other).reinterpret_as_int()
}
///|
/// Performs an arithmetic right shift operation on a 32-bit integer value,
/// preserving the sign bit by replicating it into the positions vacated by the
/// shift. This is a deprecated function; use the infix operator `>>` instead.
///
/// Parameters:
///
/// * `self` : The integer value to be shifted.
/// * `shift` : The number of positions to shift right. Must be non-negative.
///
/// Returns a new integer value that is the result of arithmetically shifting
/// `self` right by `shift` positions.
///
/// Example:
///
/// ```moonbit
/// test "Int::asr" {
/// let x = -16
/// inspect!(x >> 2, content="-4") // Right shift preserves sign bit
/// }
/// ```
///
#deprecated("Use infix operator `>>` instead")
#coverage.skip
pub fn Int::asr(self : Int, other : Int) -> Int = "%i32_shr"
///|
/// Performs an arithmetic right shift operation on a 32-bit integer by the
/// specified number of positions. The operation preserves the sign bit,
/// replicating it into the positions vacated by the shift.
///
/// Parameters:
///
/// * `self` : The integer value to be shifted.
/// * `shift` : The number of positions to shift right.
///
/// Returns a new integer representing the result of shifting `self` right by
/// `shift` positions.
///
/// Example:
///
/// ```moonbit
/// test "Int::shr" {
/// let n = -1024
/// inspect!(n >> 3, content="-128") // Preserves sign bit during right shift
/// }
/// ```
///
#deprecated("Use infix operator `>>` instead")
#coverage.skip
pub fn Int::shr(self : Int, other : Int) -> Int = "%i32_shr"
///|
/// Counts the number of consecutive zero bits at the least significant end of
/// the integer's binary representation.
///
/// Parameters:
///
/// * `self` : The integer value whose trailing zeros are to be counted.
///
/// Returns the number of trailing zero bits (0 to 32). For example, returns 0 if
/// the value is odd (least significant bit is 1), returns 32 if the value is 0
/// (all bits are zeros).
///
/// Example:
///
/// ```moonbit
/// test "Int::ctz" {
/// let x = 0
/// inspect!(x.ctz(), content="32") // All bits are zero
/// let y = 1
/// inspect!(y.ctz(), content="0") // No trailing zeros
/// let z = 16
/// inspect!(z.ctz(), content="4") // Binary: ...10000
/// }
/// ```
pub fn Int::ctz(self : Int) -> Int = "%i32_ctz"
///|
pub fn Int::clz(self : Int) -> Int = "%i32_clz"
///|
/// Counts the number of set bits (1s) in the binary representation of a 32-bit
/// integer.
///
/// Parameters:
///
/// * `self` : The 32-bit integer whose bits are to be counted.
///
/// Returns the number of bits set to 1 in the binary representation of the input
/// integer.
///
/// Example:
///
/// ```moonbit
/// test "Int::popcnt" {
/// let x = 0b1011 // Binary: 1011 (3 bits set)
/// inspect!(x.popcnt(), content="3")
/// let y = -1 // All bits set in two's complement
/// inspect!(y.popcnt(), content="32")
/// }
/// ```
pub fn Int::popcnt(self : Int) -> Int = "%i32_popcnt"
///|
/// Compares two integers for equality.
///
/// Parameters:
///
/// * `self` : The first integer to compare.
/// * `other` : The second integer to compare.
///
/// Returns `true` if both integers have the same value, `false` otherwise.
///
/// Example:
///
/// ```moonbit
/// test "Int::op_equal" {
/// inspect!(42 == 42, content="true")
/// inspect!(42 == -42, content="false")
/// }
/// ```
pub impl Eq for Int with op_equal(self : Int, other : Int) -> Bool = "%i32_eq"
///|
/// Compares two integers and returns their relative order.
///
/// Parameters:
///
/// * `self` : The first integer to compare.
/// * `other` : The second integer to compare against.
///
/// Returns an integer indicating the relative order:
///
/// * A negative value if `self` is less than `other`
/// * Zero if `self` equals `other`
/// * A positive value if `self` is greater than `other`
///
/// Example:
///
/// ```moonbit
/// test "Int::compare" {
/// let a = 42
/// let b = 24
/// inspect!(a.compare(b), content="1") // 42 > 24
/// inspect!(b.compare(a), content="-1") // 24 < 42
/// inspect!(a.compare(a), content="0") // 42 = 42
/// }
/// ```
pub impl Compare for Int with compare(self, other) = "%i32_compare"
///|
pub fn Int::is_pos(self : Int) -> Bool = "%i32_is_pos"
///|
/// Tests whether an integer is negative.
///
/// Parameters:
///
/// * `self` : The integer to test.
///
/// Returns `true` if the integer is negative, `false` otherwise.
///
/// Example:
///
/// ```moonbit
/// test "Int::is_neg" {
/// let neg = -42
/// let zero = 0
/// let pos = 42
/// inspect!(neg.is_neg(), content="true")
/// inspect!(zero.is_neg(), content="false")
/// inspect!(pos.is_neg(), content="false")
/// }
/// ```
pub fn Int::is_neg(self : Int) -> Bool = "%i32_is_neg"
///|
pub fn Int::is_non_pos(self : Int) -> Bool = "%i32_is_non_pos"
///|
pub fn Int::is_non_neg(self : Int) -> Bool = "%i32_is_non_neg"
///|
/// Returns the default value for integers, which is 0.
///
/// Returns an integer value of 0.
///
/// Example:
///
/// ```moonbit
/// test "Int::default" {
/// let x : Int = Int::default()
/// inspect!(x, content="0")
/// }
/// ```
pub impl Default for Int with default() = "%i32_default"
///|
/// Converts a 32-bit integer to a double-precision floating-point number. The
/// conversion preserves the exact value since all integers in the range of `Int`
/// can be represented exactly as `Double` values.
///
/// Parameters:
///
/// * `self` : The 32-bit integer to be converted.
///
/// Returns a double-precision floating-point number that represents the same
/// numerical value as the input integer.
///
/// Example:
///
/// ```moonbit
/// test "Int::to_double" {
/// let n = 42
/// inspect!(n.to_double(), content="42")
/// let neg = -42
/// inspect!(neg.to_double(), content="-42")
/// }
/// ```
pub fn Int::to_double(self : Int) -> Double = "%i32_to_f64"
///|
/// Converts a double-precision floating-point number to an unsigned 32-bit
/// integer by truncating the decimal part. When the input is NaN or negative,
/// returns 0. When the input exceeds the maximum value of UInt (4294967295),
/// returns 4294967295.
///
/// Parameters:
///
/// * `value` : The double-precision floating-point number to be converted.
///
/// Returns an unsigned 32-bit integer representing the truncated value.
///
/// Example:
///
/// ```moonbit
/// test "UInt::trunc_double" {
/// inspect!(UInt::trunc_double(42.75), content="42")
/// }
/// ```
pub fn UInt::trunc_double(val : Double) -> UInt = "%f64.to_u32"
///|
/// reinterpret the signed int as unsigned int, when the value is
/// non-negative, i.e, 0..=2^31-1, the value is the same. When the
/// value is negative, it turns into a large number,
/// for example, -1 turns into 2^32-1
pub fn Int::reinterpret_as_uint(self : Int) -> UInt = "%i32.to_u32_reinterpret"
///|
/// Reinterprets a signed 32-bit integer as an unsigned 32-bit integer. For
/// numbers within the range \[0, 2^31-1], the value remains the same. For
/// negative numbers, they are reinterpreted as large positive numbers in the
/// range \[2^31, 2^32-1].
///
/// Parameters:
///
/// * `value` : The signed 32-bit integer to be reinterpreted.
///
/// Returns an unsigned 32-bit integer that has the same bit pattern as the
/// input.
///
/// Example:
///
/// ```moonbit
/// test "Int::to_uint" {
/// let pos = 42
/// let neg = -1
/// inspect!(pos.reinterpret_as_uint(), content="42")
/// inspect!(neg.reinterpret_as_uint(), content="4294967295") // 2^32 - 1
/// }
/// ```
///
#deprecated("Use `reinterpret_as_uint` instead")
#coverage.skip
pub fn Int::to_uint(self : Int) -> UInt = "%i32.to_u32_reinterpret"
// Double primitive ops
///|
/// Converts a 32-bit signed integer to an unsigned 64-bit integer by first
/// converting it to a signed 64-bit integer and then reinterpreting the bits as
/// an unsigned value.
///
/// Parameters:
///
/// * `value` : The 32-bit signed integer to be converted.
///
/// Returns an unsigned 64-bit integer representing the same bit pattern as the
/// input value when extended to 64 bits.
///
/// Example:
///
/// ```moonbit
/// test "Int::to_uint64" {
/// let pos = 42
/// inspect!(pos.to_uint64(), content="42")
/// let neg = -1
/// inspect!(neg.to_uint64(), content="18446744073709551615") // 2^64 - 1
/// }
/// ```
pub fn Int::to_uint64(self : Int) -> UInt64 {
self.to_int64().reinterpret_as_uint64()
}
///|
/// Negates a double-precision floating-point number. For non-NaN inputs, changes
/// the sign of the number. For NaN inputs, returns NaN.
///
/// Parameters:
///
/// * `number` : The double-precision floating-point number to negate.
///
/// Returns a new double-precision floating-point number that is the negation of
/// the input number.
///
/// Example:
///
/// ```moonbit
/// test "Double::op_neg" {
/// inspect!(-42.0, content="-42")
/// inspect!(--42.0, content="42")
/// inspect!(-(0.0 / 0.0), content="NaN") // Negating NaN returns NaN
/// }
/// ```
pub impl Neg for Double with op_neg(self) = "%f64_neg"
///|
/// Adds two double-precision floating-point numbers together following IEEE 754
/// standards.
///
/// Parameters:
///
/// * `self` : The first double-precision floating-point number.
/// * `other` : The second double-precision floating-point number to add.
///
/// Returns the sum of the two numbers. Special cases follow IEEE 754 rules:
///
/// * If either operand is NaN, returns NaN
/// * If adding +∞ and -∞, returns NaN
/// * If adding ±∞ with any finite number, returns ±∞
/// * If adding +0.0 and -0.0, returns +0.0
///
/// Example:
///
/// ```moonbit
/// test "Double::op_add" {
/// inspect!(2.5 + 3.7, content="6.2")
/// inspect!(1.0 / 0.0 + -1.0 / 0.0, content="NaN") // Infinity + -Infinity = NaN
/// }
/// ```
pub impl Add for Double with op_add(self, other) = "%f64_add"
///|
/// Performs subtraction between two double-precision floating-point numbers.
///
/// Parameters:
///
/// * `self` : The first operand (minuend).
/// * `other` : The second operand (subtrahend).
///
/// Returns the difference between the two numbers according to IEEE 754
/// double-precision arithmetic rules.
///
/// Example:
///
/// ```moonbit
/// test "Double::op_sub" {
/// let a = 5.0
/// let b = 3.0
/// inspect!(a - b, content="2")
/// inspect!(0.0 / 0.0 - 1.0, content="NaN") // NaN - anything = NaN
/// }
/// ```
pub impl Sub for Double with op_sub(self, other) = "%f64_sub"
///|
/// Multiplies two double-precision floating-point numbers. This is the
/// implementation of the `*` operator for `Double` type.
///
/// Parameters:
///
/// * `self` : The first double-precision floating-point operand.
/// * `other` : The second double-precision floating-point operand.
///
/// Returns a new double-precision floating-point number representing the product
/// of the two operands. Special cases follow IEEE 754 standard:
///
/// * If either operand is NaN, returns NaN
/// * If one operand is infinity and the other is zero, returns NaN
/// * If one operand is infinity and the other is a non-zero finite number,
/// returns infinity with the appropriate sign
/// * If both operands are infinity, returns infinity with the appropriate sign
///
/// Example:
///
/// ```moonbit
/// test "Double::op_mul" {
/// inspect!(2.5 * 2.0, content="5")
/// inspect!(-2.0 * 3.0, content="-6")
/// let nan = 0.0 / 0.0 // NaN