1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Basic integers of fixed-precision
13 # All classes defined here have C-equivalents and the semantics of their
14 # operations are the same as C's
18 # * UInt16 => uint16_t
20 # * UInt32 => uint32_t
22 # NOTE: No UInt8 is provided as Byte is the same
26 # All classes can be instanciated via a literal rule.
27 # Namely, a suffix to append after the literal integer.
45 # The Int8 equivalent of `self`
47 # assert (-1).to_i8 == 0xFFFFi8
48 # assert (1.9).to_i8 == 1i8
49 fun to_i8
: Int8 do return self.to_i
.to_i8
51 # The Int16 equivalent of `self`
53 # assert (-1).to_i16 == 0xFFFFi16
54 # assert (1.9).to_i16 == 1i16
55 fun to_i16
: Int16 do return self.to_i
.to_i16
57 # The UInt16 equivalent of `self`
59 # assert (-1).to_u16 == 0xFFFFu16
60 # assert (1.9).to_u16 == 1u16
61 fun to_u16
: UInt16 do return self.to_i
.to_u16
63 # The Int32 equivalent of `self`
65 # assert (-1).to_i32 == 0xFFFFFFFFi32
66 # assert (1.9).to_i32 == 1i32
67 fun to_i32
: Int32 do return self.to_i
.to_i32
69 # The UInt32 equivalent of `self`
71 # assert (-1).to_u32 == 0xFFFFFFFFu32
72 # assert (1.9).to_u32 == 1u32
73 fun to_u32
: UInt32 do return self.to_i
.to_u32
78 redef fun to_i8
is intern
79 redef fun to_i16
is intern
80 redef fun to_u16
is intern
81 redef fun to_i32
is intern
82 redef fun to_u32
is intern
86 redef fun to_i8
is intern
87 redef fun to_i16
is intern
88 redef fun to_u16
is intern
89 redef fun to_i32
is intern
90 redef fun to_u32
is intern
94 redef fun to_i8
is intern
95 redef fun to_i16
is intern
96 redef fun to_u16
is intern
97 redef fun to_i32
is intern
98 redef fun to_u32
is intern
101 # Native 8-bit signed integer.
102 # Same as a C `int8_t`
107 redef type OTHER: Int8
109 redef fun successor
(i
) do return self + i
.to_i8
110 redef fun predecessor
(i
) do return self - i
.to_i8
112 redef fun object_id
is intern
113 redef fun hash
do return self.to_i
114 redef fun ==(i
) is intern
115 redef fun !=(i
) is intern
116 redef fun output
is intern
118 redef fun <=(i
) is intern
119 redef fun <(i
) is intern
120 redef fun >=(i
) is intern
121 redef fun >(i
) is intern
122 redef fun +(i
) is intern
124 # assert -1i8 == 0xFFi8
125 # assert -0i8 == 0x00i8
126 redef fun - is intern
127 redef fun -(i
) is intern
128 redef fun *(i
) is intern
129 redef fun /(i
) is intern
131 # Modulo of `self` with `i`.
133 # Returns the remainder of division of `self` by `i`.
135 # assert 5i8 % 2i8 == 1i8
136 # assert 10i8 % 2i8 == 0i8
137 fun %(i
: Int8): Int8 is intern
139 redef fun zero
do return 0.to_i8
140 redef fun value_of
(val
) do return val
.to_i8
142 # `i` bits shift to the left
144 # assert 5i8 << 1 == 10i8
145 fun <<(i
: Int): Int8 is intern
147 # `i` bits shift to the right
149 # assert 5i8 >> 1 == 2i8
150 fun >>(i
: Int): Int8 is intern
152 redef fun to_i
is intern
153 redef fun to_f
is intern
154 redef fun to_b
is intern
155 redef fun to_i8
do return self
156 redef fun to_i16
is intern
157 redef fun to_u16
is intern
158 redef fun to_i32
is intern
159 redef fun to_u32
is intern
161 redef fun distance
(i
) do return (self - i
).to_i
167 else if other
< self then
174 redef fun is_between
(c
, d
)
176 if self < c
or d
< self then
201 # Returns the result of a binary AND operation on `self` and `i`
203 # assert 0x10i8 & 0x01i8 == 0i8
204 fun &(i
: Int8): Int8 is intern
206 # Returns the result of a binary OR operation on `self` and `i`
208 # assert 0x10i8 | 0x01i8 == 0x11i8
209 fun |(i
: Int8): Int8 is intern
211 # Returns the result of a binary XOR operation on `self` and `i`
213 # assert 0x101i8 ^ 0x110i8 == 0x11i8
214 fun ^
(i
: Int8): Int8 is intern
216 # Returns the 1's complement of `self`
218 # assert ~0x2Fi8 == 0xD0i8
219 fun ~
: Int8 is intern
221 # C function to calculate the length of the `NativeString` to receive `self`
222 private fun to_s_len
: Int `{
223 return snprintf(NULL, 0, "%"PRIi8, self);
226 # C function to convert a nit Int to a NativeString (char*)
227 private fun native_to_s
(nstr
: NativeString, strlen
: Int) `{
228 snprintf(nstr, strlen, "%"PRIi8, self);
233 # assert 1i8.to_s == "1"
234 # assert (-123i8).to_s == "-123"
237 var ns
= new NativeString(nslen
+ 1)
239 native_to_s
(ns
, nslen
+ 1)
240 return ns
.to_s_with_length
(nslen
)
244 # Native 16-bit signed integer.
245 # Same as a C `int16_t`
250 redef type OTHER: Int16
252 redef fun successor
(i
) do return self + i
.to_i16
253 redef fun predecessor
(i
) do return self - i
.to_i16
255 redef fun object_id
is intern
256 redef fun hash
do return self.to_i
257 redef fun ==(i
) is intern
258 redef fun !=(i
) is intern
259 redef fun output
is intern
261 redef fun <=(i
) is intern
262 redef fun <(i
) is intern
263 redef fun >=(i
) is intern
264 redef fun >(i
) is intern
265 redef fun +(i
) is intern
267 # assert -1i16 == 0xFFFFi16
268 # assert -0i16 == 0i16
269 redef fun - is intern
270 redef fun -(i
) is intern
271 redef fun *(i
) is intern
272 redef fun /(i
) is intern
274 # Modulo of `self` with `i`.
276 # Returns the remainder of division of `self` by `i`.
278 # assert 5i16 % 2i16 == 1i16
279 # assert 10i16 % 2i16 == 0i16
280 fun %(i
: Int16): Int16 is intern
282 redef fun zero
do return 0.to_i16
283 redef fun value_of
(val
) do return val
.to_i16
285 # `i` bits shift to the left
287 # assert 5i16 << 1 == 10i16
288 fun <<(i
: Int): Int16 is intern
290 # `i` bits shift to the right
292 # assert 5i16 >> 1 == 2i16
293 fun >>(i
: Int): Int16 is intern
295 redef fun to_i
is intern
296 redef fun to_f
is intern
297 redef fun to_b
is intern
298 redef fun to_i8
is intern
299 redef fun to_i16
do return self
300 redef fun to_u16
is intern
301 redef fun to_i32
is intern
302 redef fun to_u32
is intern
304 redef fun distance
(i
) do return (self - i
).to_i
310 else if other
< self then
317 redef fun is_between
(c
, d
)
319 if self < c
or d
< self then
344 # Returns the result of a binary AND operation on `self` and `i`
346 # assert 0x10i16 & 0x01i16 == 0i16
347 fun &(i
: Int16): Int16 is intern
349 # Returns the result of a binary OR operation on `self` and `i`
351 # assert 0x10i16 | 0x01i16 == 0x11i16
352 fun |(i
: Int16): Int16 is intern
354 # Returns the result of a binary XOR operation on `self` and `i`
356 # assert 0x101i16 ^ 0x110i16 == 0x11i16
357 fun ^
(i
: Int16): Int16 is intern
359 # Returns the 1's complement of `self`
361 # assert ~0x2Fi16 == 0xFFD0i16
362 fun ~
: Int16 is intern
364 # C function to calculate the length of the `NativeString` to receive `self`
365 private fun to_s_len
: Int `{
366 return snprintf(NULL, 0, "%"PRIi16, self);
369 # C function to convert a nit Int to a NativeString (char*)
370 private fun native_to_s
(nstr
: NativeString, strlen
: Int) `{
371 snprintf(nstr, strlen, "%"PRIi16, self);
376 # assert 1i16.to_s == "1"
377 # assert (-123i16).to_s == "-123"
380 var ns
= new NativeString(nslen
+ 1)
382 native_to_s
(ns
, nslen
+ 1)
383 return ns
.to_s_with_length
(nslen
)
387 # Native 16-bit unsigned integer.
388 # Same as a C `uint16_t`
393 redef type OTHER: UInt16
395 redef fun successor
(i
) do return self + i
.to_u16
396 redef fun predecessor
(i
) do return self - i
.to_u16
398 redef fun object_id
is intern
399 redef fun hash
do return self.to_i
400 redef fun ==(i
) is intern
401 redef fun !=(i
) is intern
402 redef fun output
is intern
404 redef fun <=(i
) is intern
405 redef fun <(i
) is intern
406 redef fun >=(i
) is intern
407 redef fun >(i
) is intern
408 redef fun +(i
) is intern
410 # assert -1u16 == 0xFFFFu16
411 # assert -0u16 == 0u16
412 redef fun - is intern
413 redef fun -(i
) is intern
414 redef fun *(i
) is intern
415 redef fun /(i
) is intern
417 # Modulo of `self` with `i`.
419 # Returns the remainder of division of `self` by `i`.
421 # assert 5u16 % 2u16 == 1u16
422 # assert 10u16 % 2u16 == 0u16
423 fun %(i
: UInt16): UInt16 is intern
425 redef fun zero
do return 0.to_u16
426 redef fun value_of
(val
) do return val
.to_u16
428 # `i` bits shift to the left
430 # assert 5u16 << 1 == 10u16
431 fun <<(i
: Int): UInt16 is intern
433 # `i` bits shift to the right
435 # assert 5u16 >> 1 == 2u16
436 fun >>(i
: Int): UInt16 is intern
438 redef fun to_i
is intern
439 redef fun to_f
is intern
440 redef fun to_b
is intern
441 redef fun to_i8
is intern
442 redef fun to_i16
is intern
443 redef fun to_u16
do return self
444 redef fun to_i32
is intern
445 redef fun to_u32
is intern
447 redef fun distance
(i
) do return (self - i
).to_i
453 else if other
< self then
460 redef fun is_between
(c
, d
)
462 if self < c
or d
< self then
487 # Returns the result of a binary AND operation on `self` and `i`
489 # assert 0x10u16 & 0x01u16 == 0u16
490 fun &(i
: UInt16): UInt16 is intern
492 # Returns the result of a binary OR operation on `self` and `i`
494 # assert 0x10u16 | 0x01u16 == 0x11u16
495 fun |(i
: UInt16): UInt16 is intern
497 # Returns the result of a binary XOR operation on `self` and `i`
499 # assert 0x101u16 ^ 0x110u16 == 0x11u16
500 fun ^
(i
: UInt16): UInt16 is intern
502 # Returns the 1's complement of `self`
504 # assert ~0x2Fu16 == 0xFFD0u16
505 fun ~
: UInt16 is intern
507 # C function to calculate the length of the `NativeString` to receive `self`
508 private fun to_s_len
: Int `{
509 return snprintf(NULL, 0, "%"PRIu16, self);
512 # C function to convert a nit Int to a NativeString (char*)
513 private fun native_to_s
(nstr
: NativeString, strlen
: Int) `{
514 snprintf(nstr, strlen, "%"PRIu16, self);
519 # assert 1u16.to_s == "1"
520 # assert (-123u16).to_s == "65413"
523 var ns
= new NativeString(nslen
+ 1)
525 native_to_s
(ns
, nslen
+ 1)
526 return ns
.to_s_with_length
(nslen
)
531 # Native 32-bit signed integer.
532 # Same as a C `int32_t`
537 redef type OTHER: Int32
539 redef fun successor
(i
) do return self + i
.to_i32
540 redef fun predecessor
(i
) do return self - i
.to_i32
542 redef fun object_id
is intern
543 redef fun hash
do return self.to_i
544 redef fun ==(i
) is intern
545 redef fun !=(i
) is intern
546 redef fun output
is intern
548 redef fun <=(i
) is intern
549 redef fun <(i
) is intern
550 redef fun >=(i
) is intern
551 redef fun >(i
) is intern
552 redef fun +(i
) is intern
554 # assert -1i32 == 0xFFFFFFFFi32
555 # assert -0i32 == 0x00i32
556 redef fun - is intern
557 redef fun -(i
) is intern
558 redef fun *(i
) is intern
559 redef fun /(i
) is intern
561 # Modulo of `self` with `i`.
563 # Returns the remainder of division of `self` by `i`.
565 # assert 5i32 % 2i32 == 1i32
566 # assert 10i32 % 2i32 == 0i32
567 fun %(i
: Int32): Int32 is intern
569 redef fun zero
do return 0.to_i32
570 redef fun value_of
(val
) do return val
.to_i32
572 # `i` bits shift to the left
574 # assert 5i32 << 1 == 10i32
575 fun <<(i
: Int): Int32 is intern
577 # `i` bits shift to the right
579 # assert 5i32 >> 1 == 2i32
580 fun >>(i
: Int): Int32 is intern
582 redef fun to_i
is intern
583 redef fun to_f
is intern
584 redef fun to_b
is intern
585 redef fun to_i8
is intern
586 redef fun to_i16
is intern
587 redef fun to_u16
is intern
588 redef fun to_i32
do return self
589 redef fun to_u32
is intern
591 redef fun distance
(i
) do return (self - i
).to_i
597 else if other
< self then
604 redef fun is_between
(c
, d
)
606 if self < c
or d
< self then
631 # Returns the result of a binary AND operation on `self` and `i`
633 # assert 0x10i32 & 0x01i32 == 0i32
634 fun &(i
: Int32): Int32 is intern
636 # Returns the result of a binary OR operation on `self` and `i`
638 # assert 0x10i32 | 0x01i32 == 0x11i32
639 fun |(i
: Int32): Int32 is intern
641 # Returns the result of a binary XOR operation on `self` and `i`
643 # assert 0x101i32 ^ 0x110i32 == 0x11i32
644 fun ^
(i
: Int32): Int32 is intern
646 # Returns the 1's complement of `self`
648 # assert ~0x2Fi32 == 0xFFFFFFD0i32
649 fun ~
: Int32 is intern
651 # C function to calculate the length of the `NativeString` to receive `self`
652 private fun to_s_len
: Int `{
653 return snprintf(NULL, 0, "%"PRIi32, self);
656 # C function to convert a nit Int to a NativeString (char*)
657 private fun native_to_s
(nstr
: NativeString, strlen
: Int) `{
658 snprintf(nstr, strlen, "%"PRIi32, self);
663 # assert 1i32.to_s == "1"
664 # assert (-123i32).to_s == "-123"
667 var ns
= new NativeString(nslen
+ 1)
669 native_to_s
(ns
, nslen
+ 1)
670 return ns
.to_s_with_length
(nslen
)
674 # Native 32-bit unsigned integer.
675 # Same as a C `uint32_t`
680 redef type OTHER: UInt32
682 redef fun successor
(i
) do return self + i
.to_u32
683 redef fun predecessor
(i
) do return self - i
.to_u32
685 redef fun object_id
is intern
686 redef fun hash
do return self.to_i
687 redef fun ==(i
) is intern
688 redef fun !=(i
) is intern
689 redef fun output
is intern
691 redef fun <=(i
) is intern
692 redef fun <(i
) is intern
693 redef fun >=(i
) is intern
694 redef fun >(i
) is intern
695 redef fun +(i
) is intern
697 # assert -1u32 == 0xFFFFFFFFu32
698 # assert -0u32 == 0x00u32
699 redef fun - is intern
700 redef fun -(i
) is intern
701 redef fun *(i
) is intern
702 redef fun /(i
) is intern
704 # Modulo of `self` with `i`.
706 # Returns the remainder of division of `self` by `i`.
708 # assert 5u32 % 2u32 == 1u32
709 # assert 10u32 % 2u32 == 0u32
710 fun %(i
: UInt32): UInt32 is intern
712 redef fun zero
do return 0.to_u32
713 redef fun value_of
(val
) do return val
.to_u32
715 # `i` bits shift to the left
717 # assert 5u32 << 1 == 10u32
718 fun <<(i
: Int): UInt32 is intern
720 # `i` bits shift to the right
722 # assert 5u32 >> 1 == 2u32
723 fun >>(i
: Int): UInt32 is intern
725 redef fun to_i
is intern
726 redef fun to_f
is intern
727 redef fun to_b
is intern
728 redef fun to_i8
is intern
729 redef fun to_i16
is intern
730 redef fun to_u16
is intern
731 redef fun to_i32
is intern
732 redef fun to_u32
do return self
734 redef fun distance
(i
) do return (self - i
).to_i
740 else if other
< self then
747 redef fun is_between
(c
, d
)
749 if self < c
or d
< self then
774 # Returns the result of a binary AND operation on `self` and `i`
776 # assert 0x10u32 & 0x01u32 == 0u32
777 fun &(i
: UInt32): UInt32 is intern
779 # Returns the result of a binary OR operation on `self` and `i`
781 # assert 0x10u32 | 0x01u32 == 0x11u32
782 fun |(i
: UInt32): UInt32 is intern
784 # Returns the result of a binary XOR operation on `self` and `i`
786 # assert 0x101u32 ^ 0x110u32 == 0x11u32
787 fun ^
(i
: UInt32): UInt32 is intern
789 # Returns the 1's complement of `self`
791 # assert ~0x2Fu32 == 0xFFFFFFD0u32
792 fun ~
: UInt32 is intern
794 # C function to calculate the length of the `NativeString` to receive `self`
795 private fun to_s_len
: Int `{
796 return snprintf(NULL, 0, "%"PRIu32, self);
799 # C function to convert a nit Int to a NativeString (char*)
800 private fun native_to_s
(nstr
: NativeString, strlen
: Int) `{
801 snprintf(nstr, strlen, "%"PRIu32, self);
806 # assert 1u32.to_s == "1"
807 # assert (-123u32).to_s == "4294967173"
810 var ns
= new NativeString(nslen
+ 1)
812 native_to_s
(ns
, nslen
+ 1)
813 return ns
.to_s_with_length
(nslen
)
819 # Removes the numeric head of `self` if present
821 # intrude import core::fixed_ints
822 # assert "0xFFEF".strip_numhead == "FFEF"
823 # assert "0o7364".strip_numhead == "7364"
824 # assert "0b01001".strip_numhead == "01001"
825 # assert "98".strip_numhead == "98"
826 private fun strip_numhead
: Text do
827 if get_numhead
!= "" then return substring_from
(2)
831 # Gets the numeric head of `self` if present
832 # Returns "" otherwise
834 # intrude import core::fixed_ints
835 # assert "0xFEFF".get_numhead == "0x"
836 # assert "0b01001".get_numhead == "0b"
837 # assert "0o872".get_numhead == "0o"
838 # assert "98".get_numhead == ""
839 private fun get_numhead
: Text do
840 if self.length
< 2 then return ""
842 if c
!= '0' then return ""
844 if c
== 'x' or c
== 'b' or c
== 'o' or
845 c
== 'X' or c
== 'B' or c
== 'O' then return substring
(0, 2)
849 # Removes the numeric extension if present
851 # intrude import core::fixed_ints
852 # assert "0xFEFFu8".strip_numext == "0xFEFF"
853 # assert "0b01001u8".strip_numext == "0b01001"
854 # assert "0o872u8".strip_numext == "0o872"
855 # assert "98".strip_numext == "98"
856 private fun strip_numext
: Text do
858 if ext
!= "" then return substring
(0, length
- ext
.length
)
862 # Gets the numeric extension (i/u 8/16/32) in `self` is present
863 # Returns "" otherwise
865 # intrude import core::fixed_ints
866 # assert "0xFEFFu8".get_numext == "u8"
867 # assert "0b01001u8".get_numext == "u8"
868 # assert "0o872u8".get_numext == "u8"
869 # assert "98".get_numext == ""
870 private fun get_numext
: Text do
871 var len
= self.length
872 var max
= if self.length
< 3 then self.length
else 3
873 for i
in [1 .. max
] do
874 var c
= self[len
- i
]
875 if c
== 'i' or c
== 'u' then return substring_from
(len
- i
)
880 # Is `self` a well-formed Integer (i.e. parsable via `to_i`)
882 # assert "123".is_int
883 # assert "0b1011".is_int
884 # assert not "0x_".is_int
885 # assert not "0xGE".is_int
886 # assert not "".is_int
888 if bytelen
== 0 then return false
889 var s
= remove_all
('_')
891 while s
[pos
] == '-' do
894 s
= s
.substring_from
(pos
)
895 var rets
= s
.strip_numhead
896 if rets
== "" then return false
898 if hd
== "0x" or hd
== "0X" then return rets
.is_hex
899 if hd
== "0b" or hd
== "0B" then return rets
.is_bin
900 if hd
== "0o" or hd
== "0O" then return rets
.is_oct
907 var s
= remove_all
('_')
911 while s
[pos
] == '-' do
915 s
= s
.substring_from
(pos
)
916 if s
.length
>= 2 then
918 if s1
== 'x' or s1
== 'X' then
919 val
= s
.substring_from
(2).to_hex
920 else if s1
== 'o' or s1
== 'O' then
921 val
= s
.substring_from
(2).to_oct
922 else if s1
== 'b' or s1
== 'B' then
923 val
= s
.substring_from
(2).to_bin
924 else if s1
.is_numeric
then
930 return if neg
then -val
else val
933 # Is `self` a valid integer ?
935 # assert "0xFE46u8".is_num
936 # assert "0b0100".is_num
937 # assert "0o645".is_num
938 # assert "897u8".is_num
940 var prefix
= get_numhead
941 var s
= strip_numhead
.strip_numext
.remove_all
('_')
944 if c
== 'x' or c
== 'X' then return s
.is_hex
945 if c
== 'o' or c
== 'O' then return s
.is_oct
946 if c
== 'b' or c
== 'B' then return s
.is_bin
951 # If `self` is a properly formatted integer, returns the corresponding value
952 # Returns `null` otherwise
954 # assert "0xFEu8".to_num == 254u8
955 # assert "0b10_10".to_num != 10u8
956 fun to_num
: nullable Numeric do
957 if not is_num
then return null
958 var s
= remove_all
('_')
959 var ext
= s
.get_numext
960 var trunk
= s
.strip_numext
961 if trunk
.strip_numhead
== "" then return null
962 var trval
= trunk
.to_i
965 else if ext
== "i8" then
967 else if ext
== "i16" then
969 else if ext
== "u16" then
971 else if ext
== "i32" then
973 else if ext
== "u32" then
975 else if ext
== "" then