diff --git a/bigint/bigint_nonjs.mbt b/bigint/bigint_nonjs.mbt index 8941e0b92..12486c874 100644 --- a/bigint/bigint_nonjs.mbt +++ b/bigint/bigint_nonjs.mbt @@ -1002,7 +1002,7 @@ pub fn BigInt::from_string(input : String) -> BigInt { if x < 0 || x > 9 { abort("invalid character") } - let mut carry = x.reinterpret_as_uint().to_uint64() + let mut carry = x.to_uint64() for j in 0.. BigInt { /// ``` pub fn BigInt::from_hex(input : String) -> BigInt { // WARN: this implementation assumes that `radix_bit_len` is a multiple of 4. - fn char_from_hex(x : Int) -> UInt { + fn char_from_hex(x : UInt16) -> UInt { (match x { '0'..='9' => x - '0' 'A'..='F' => x + (10 - 'A') 'a'..='f' => x + (10 - 'a') _ => abort("invalid character") - }).reinterpret_as_uint() + }).to_uint() } let len = input.length() diff --git a/buffer/buffer.mbt b/buffer/buffer.mbt index 14140a13b..8db2605a4 100644 --- a/buffer/buffer.mbt +++ b/buffer/buffer.mbt @@ -689,7 +689,7 @@ pub fn Buffer::write_string_utf16le(buf : Self, string : @string.View) -> Unit { let len = string.length() buf.grow_if_necessary(buf.len + len * 2) for i = 0, j = buf.len; i < len; i = i + 1, j = j + 2 { - let c = string.unsafe_charcode_at(i).reinterpret_as_uint() + let c = string.unsafe_charcode_at(i).to_uint() buf.data[j] = (c & 0xff).to_byte() buf.data[j + 1] = (c >> 8).to_byte() } @@ -701,7 +701,7 @@ pub fn Buffer::write_string_utf16be(buf : Self, string : @string.View) -> Unit { let len = string.length() buf.grow_if_necessary(buf.len + len * 2) for i = 0, j = buf.len; i < len; i = i + 1, j = j + 2 { - let c = string.unsafe_charcode_at(i).reinterpret_as_uint() + let c = string.unsafe_charcode_at(i).to_uint() buf.data[j + 1] = (c & 0xff).to_byte() buf.data[j] = (c >> 8).to_byte() } diff --git a/builtin/bytes.mbt b/builtin/bytes.mbt index 5ade88805..993f414f0 100644 --- a/builtin/bytes.mbt +++ b/builtin/bytes.mbt @@ -132,7 +132,7 @@ pub fn FixedArray::blit_from_string( guard length >= 0 && s1 >= 0 && e1 < len1 && s2 >= 0 && e2 < len2 let end_str_offset = str_offset + length for i = str_offset, j = bytes_offset; i < end_str_offset; i = i + 1, j = j + 2 { - let c = str.unsafe_charcode_at(i).reinterpret_as_uint() + let c = str.unsafe_charcode_at(i) self[j] = (c & 0xff).to_byte() self[j + 1] = (c >> 8).to_byte() } diff --git a/builtin/deprecated.mbt b/builtin/deprecated.mbt index 4fe1a37e2..5f3fad55e 100644 --- a/builtin/deprecated.mbt +++ b/builtin/deprecated.mbt @@ -455,7 +455,7 @@ pub fn String::codepoint_length( ///| #deprecated("Use `s[i]` instead") pub fn String::charcode_at(self : String, index : Int) -> Int { - self[index] + self[index].to_int() } ///| diff --git a/builtin/hasher.mbt b/builtin/hasher.mbt index 1e9068beb..2ecbd3074 100644 --- a/builtin/hasher.mbt +++ b/builtin/hasher.mbt @@ -335,7 +335,7 @@ pub fn Hasher::combine_bytes(self : Hasher, value : Bytes) -> Unit { /// ``` pub fn Hasher::combine_string(self : Hasher, value : String) -> Unit { for i in 0.. Byte = "%i32_to_byte" ///| pub fn Int::unsafe_to_char(self : Int) -> Char = "%char_from_int" +///| +pub fn UInt16::unsafe_to_char(self : UInt16) -> Char = "%char_from_int" + ///| pub fn Int::to_char(self : Int) -> Char? { if self is (0..=0xD7FF) || self is (0xE000..=0x10FFFF) { @@ -1536,7 +1539,7 @@ pub fn String::charcode_length(self : String) -> Int = "%string_length" /// * `index` : The position in the string from which to retrieve the code unit. /// /// This method has O(1) complexity. -pub fn String::op_get(self : String, idx : Int) -> Int = "%string_get" +pub fn String::op_get(self : String, idx : Int) -> UInt16 = "%string_get" ///| /// Returns the UTF-16 code unit at a given position in the string without @@ -1563,7 +1566,7 @@ pub fn String::op_get(self : String, idx : Int) -> Int = "%string_get" /// ``` /// TODO: rename to `unsafe_get` #internal(unsafe, "Panic if index is out of bounds.") -pub fn String::unsafe_charcode_at(self : String, idx : Int) -> Int = "%string.unsafe_get" +pub fn String::unsafe_charcode_at(self : String, idx : Int) -> UInt16 = "%string.unsafe_get" ///| /// Concatenates two strings, creating a new string that contains all characters diff --git a/builtin/pkg.generated.mbti b/builtin/pkg.generated.mbti index 510e273d8..d4e7b8337 100644 --- a/builtin/pkg.generated.mbti +++ b/builtin/pkg.generated.mbti @@ -460,10 +460,16 @@ fn UInt::trunc_double(Double) -> UInt #deprecated fn UInt::upto(UInt, UInt, inclusive? : Bool) -> Iter[UInt] +fn UInt16::is_leading_surrogate(UInt16) -> Bool +fn UInt16::is_surrogate(UInt16) -> Bool +fn UInt16::is_trailing_surrogate(UInt16) -> Bool fn UInt16::to_byte(UInt16) -> Byte fn UInt16::to_int(UInt16) -> Int fn UInt16::to_int64(UInt16) -> Int64 fn UInt16::to_string(UInt16, radix? : Int) -> String +fn UInt16::to_uint(UInt16) -> UInt +fn UInt16::to_uint64(UInt16) -> UInt64 +fn UInt16::unsafe_to_char(UInt16) -> Char fn UInt64::clz(UInt64) -> Int fn UInt64::ctz(UInt64) -> Int @@ -531,13 +537,13 @@ fn String::codepoint_length(String, start_offset? : Int, end_offset? : Int) -> I fn String::escape(String) -> String fn String::length(String) -> Int fn String::make(Int, Char) -> String -fn String::op_get(String, Int) -> Int +fn String::op_get(String, Int) -> UInt16 #deprecated fn String::substring(String, start? : Int, end? : Int) -> String fn String::to_string(String) -> String #deprecated fn String::unsafe_char_at(String, Int) -> Char -fn String::unsafe_charcode_at(String, Int) -> Int +fn String::unsafe_charcode_at(String, Int) -> UInt16 fn String::unsafe_substring(String, start~ : Int, end~ : Int) -> String fn[X : Show] Option::to_string(X?) -> String @@ -592,6 +598,7 @@ impl Add for Byte impl Add for Int impl Add for Int64 impl Add for UInt +impl Add for UInt16 impl Add for UInt64 impl Add for Float impl Add for Double @@ -602,6 +609,7 @@ pub(open) trait BitAnd { } impl BitAnd for Byte impl BitAnd for Int64 +impl BitAnd for UInt16 impl BitAnd for UInt64 pub(open) trait BitOr { @@ -609,6 +617,7 @@ pub(open) trait BitOr { } impl BitOr for Byte impl BitOr for Int64 +impl BitOr for UInt16 impl BitOr for UInt64 pub(open) trait BitXOr { @@ -616,6 +625,7 @@ pub(open) trait BitXOr { } impl BitXOr for Byte impl BitXOr for Int64 +impl BitXOr for UInt16 impl BitXOr for UInt64 pub(open) trait Compare : Eq { @@ -627,6 +637,7 @@ impl Compare for Char impl Compare for Int impl Compare for Int64 impl Compare for UInt +impl Compare for UInt16 impl Compare for UInt64 impl Compare for Float impl Compare for Double @@ -667,6 +678,7 @@ impl Div for Byte impl Div for Int impl Div for Int64 impl Div for UInt +impl Div for UInt16 impl Div for UInt64 impl Div for Float impl Div for Double @@ -682,6 +694,7 @@ impl Eq for Char impl Eq for Int impl Eq for Int64 impl Eq for UInt +impl Eq for UInt16 impl Eq for UInt64 impl Eq for Float impl Eq for Double @@ -737,6 +750,7 @@ impl Mod for Byte impl Mod for Int impl Mod for Int64 impl Mod for UInt +impl Mod for UInt16 impl Mod for UInt64 pub(open) trait Mul { @@ -747,6 +761,7 @@ impl Mul for Byte impl Mul for Int impl Mul for Int64 impl Mul for UInt +impl Mul for UInt16 impl Mul for UInt64 impl Mul for Float impl Mul for Double @@ -768,6 +783,7 @@ impl Shl for Byte impl Shl for Int impl Shl for Int64 impl Shl for UInt +impl Shl for UInt16 impl Shl for UInt64 pub(open) trait Show { @@ -813,6 +829,7 @@ impl Shr for Byte impl Shr for Int impl Shr for Int64 impl Shr for UInt +impl Shr for UInt16 impl Shr for UInt64 pub(open) trait Sub { @@ -823,6 +840,7 @@ impl Sub for Byte impl Sub for Int impl Sub for Int64 impl Sub for UInt +impl Sub for UInt16 impl Sub for UInt64 impl Sub for Float impl Sub for Double diff --git a/builtin/show.mbt b/builtin/show.mbt index 3323daa91..efed80e95 100644 --- a/builtin/show.mbt +++ b/builtin/show.mbt @@ -62,7 +62,7 @@ pub impl Show for UInt16 with output(self, logger) { } ///| -fn to_hex_digit(i : Int) -> Char { +fn to_hex_digit(i : UInt16) -> Char { if i < 10 { (i + '0').unsafe_to_char() } else { @@ -73,12 +73,14 @@ fn to_hex_digit(i : Int) -> Char { ///| test "to_hex_digit" { for i in 0..<10 { - guard to_hex_digit(i) == ('0'.to_int() + i).unsafe_to_char() else { + let i = i.to_uint16() + guard to_hex_digit(i) == (i + '0').unsafe_to_char() else { fail("to_hex_digit(\{i}) does not match") } } for i in 10..<16 { - guard to_hex_digit(i) == ('a'.to_int() + (i - 10)).unsafe_to_char() else { + let i = i.to_uint16() + guard to_hex_digit(i) == (i + 'a' - 10).unsafe_to_char() else { fail("to_hex_digit(\{i}) does not match") } } @@ -88,7 +90,7 @@ test "to_hex_digit" { pub impl Show for Bytes with output(self, logger) { logger.write_string("b\"") for b in self { - let byte = b.to_int() + let byte = b.to_uint16() logger ..write_string("\\x") ..write_char(to_hex_digit(byte / 16)) diff --git a/builtin/string.mbt b/builtin/string.mbt index 716facc10..04775c2d6 100644 --- a/builtin/string.mbt +++ b/builtin/string.mbt @@ -35,7 +35,9 @@ pub fn String::make(length : Int, value : Char) -> String { } ///| -fn code_point_of_surrogate_pair(leading : Int, trailing : Int) -> Char { +fn code_point_of_surrogate_pair(leading : UInt16, trailing : UInt16) -> Char { + let leading = leading.to_int() + let trailing = trailing.to_int() ((leading - 0xD800) * 0x400 + trailing - 0xDC00 + 0x10000).unsafe_to_char() } diff --git a/builtin/uint16.mbt b/builtin/uint16.mbt new file mode 100644 index 000000000..187cecf58 --- /dev/null +++ b/builtin/uint16.mbt @@ -0,0 +1,164 @@ +// 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. + +///| +/// Checks if the integer value represents a UTF-16 leading surrogate. +/// Leading surrogates are in the range 0xD800 to 0xDBFF. +/// +/// Example: +/// ```moonbit +/// inspect((0xD800: UInt16).is_leading_surrogate(), content="true") +/// inspect((0xDBFF: UInt16).is_leading_surrogate(), content="true") +/// inspect((0xDC00: UInt16).is_leading_surrogate(), content="false") +/// inspect((0x41: UInt16).is_leading_surrogate(), content="false") // 'A' +/// ``` +pub fn UInt16::is_leading_surrogate(self : UInt16) -> Bool { + self >= 0xD800 && self <= 0xDBFF +} + +///| +/// Checks if the integer value represents a UTF-16 trailing surrogate. +/// Trailing surrogates are in the range 0xDC00 to 0xDFFF. +/// +/// Example: +/// ```moonbit +/// inspect((0xDC00: UInt16).is_trailing_surrogate(), content="true") +/// inspect((0xDFFF: UInt16).is_trailing_surrogate(), content="true") +/// inspect((0xD800: UInt16).is_trailing_surrogate(), content="false") +/// inspect((0x41: UInt16).is_trailing_surrogate(), content="false") // 'A' +/// ``` +pub fn UInt16::is_trailing_surrogate(self : UInt16) -> Bool { + self >= 0xDC00 && self <= 0xDFFF +} + +///| +/// Checks if the integer value represents any UTF-16 surrogate (leading or trailing). +/// Surrogates are in the range 0xD800 to 0xDFFF. +/// +/// Example: +/// ```moonbit +/// inspect((0xD800: UInt16).is_surrogate(), content="true") // leading surrogate +/// inspect((0xDC00: UInt16).is_surrogate(), content="true") // trailing surrogate +/// inspect((0xDFFF: UInt16).is_surrogate(), content="true") // trailing surrogate +/// inspect((0x41: UInt16).is_surrogate(), content="false") // 'A' +/// ``` +pub fn UInt16::is_surrogate(self : UInt16) -> Bool { + self >= 0xD800 && self <= 0xDFFF +} + +///| +pub impl Add for UInt16 with add(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() + that.to_int()).to_uint16() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Add for UInt16 with op_add(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() + that.to_int()).to_uint16() +} + +///| +pub impl Sub for UInt16 with sub(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() - that.to_int()).to_uint16() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Sub for UInt16 with op_sub(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() - that.to_int()).to_uint16() +} + +///| +pub impl Mul for UInt16 with mul(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() * that.to_int()).to_uint16() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Mul for UInt16 with op_mul(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() * that.to_int()).to_uint16() +} + +///| +pub impl Div for UInt16 with div(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() / that.to_int()).to_uint16() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Div for UInt16 with op_div(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() / that.to_int()).to_uint16() +} + +///| +pub impl Mod for UInt16 with mod(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() % that.to_int()).to_uint16() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Mod for UInt16 with op_mod(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() % that.to_int()).to_uint16() +} + +///| +pub impl Shl for UInt16 with shl(self : UInt16, that : Int) -> UInt16 { + (self.to_int() << that).to_uint16() +} + +///| +pub impl Shr for UInt16 with shr(self : UInt16, that : Int) -> UInt16 { + (self.to_int() >> that).to_uint16() +} + +///| +pub impl BitOr for UInt16 with lor(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() | that.to_int()).to_uint16() +} + +///| +pub impl BitAnd for UInt16 with land(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() & that.to_int()).to_uint16() +} + +///| +pub impl BitXOr for UInt16 with lxor(self : UInt16, that : UInt16) -> UInt16 { + (self.to_int() ^ that.to_int()).to_uint16() +} + +///| +pub impl Eq for UInt16 with equal(self, that) { + self.to_int() == that.to_int() +} + +///| +// TODO: remove this after we migrate compiler to new names +pub impl Eq for UInt16 with op_equal(self, that) { + self.to_int() == that.to_int() +} + +///| +pub impl Compare for UInt16 with compare(self, that) { + self.to_int().compare(that.to_int()) +} + +///| +pub fn UInt16::to_uint(self : UInt16) -> UInt { + self.to_int().reinterpret_as_uint() +} + +///| +pub fn UInt16::to_uint64(self : UInt16) -> UInt64 { + self.to_int().to_uint64() +} diff --git a/json/from_json.mbt b/json/from_json.mbt index ca4e025ca..4fa0bdbda 100644 --- a/json/from_json.mbt +++ b/json/from_json.mbt @@ -141,7 +141,7 @@ pub impl FromJson for Char with from_json(json, path) { let c1 = a.unsafe_charcode_at(0) let c2 = a.unsafe_charcode_at(1) if c1 is (0xD800..=0xDBFF) && c2 is (0xDC00..=0xDFFF) { - let c3 = (c1 << 10) + c2 - 0x35fdc00 + let c3 = (c1.to_int() << 10) + c2.to_int() - 0x35fdc00 c3.unsafe_to_char() } else { decode_error(path, "Char::from_json: invalid surrogate pair") diff --git a/json/lex_misc.mbt b/json/lex_misc.mbt index ded622cd4..5b9481565 100644 --- a/json/lex_misc.mbt +++ b/json/lex_misc.mbt @@ -22,7 +22,7 @@ fn ParseContext::read_char(ctx : ParseContext) -> Char? { let c2 = ctx.input.unsafe_charcode_at(ctx.offset) if c2 >= 0xDC00 && c2 <= 0xDFFF { ctx.offset += 1 - let c3 = (c1 << 10) + c2 - 0x35fdc00 + let c3 = (c1.to_int() << 10) + c2.to_int() - 0x35fdc00 return Some(c3.unsafe_to_char()) } } @@ -35,11 +35,11 @@ fn ParseContext::read_char(ctx : ParseContext) -> Char? { ///| /// low surrogate -const SURROGATE_LOW_CHAR = 0xD800 +const SURROGATE_LOW_CHAR : UInt16 = 0xD800 ///| /// high surrogate -const SURROGATE_HIGH_CHAR = 0xDFFF +const SURROGATE_HIGH_CHAR : UInt16 = 0xDFFF ///| /// `ctx.expect_char(c)` check the current context is c, @@ -56,7 +56,7 @@ fn ParseContext::expect_char( if c0 < 0xFFFF { // c0 < SURROGATE_LOW_CHAR || c0 is (0xE000..=0XFFFF) // c0 is a valid char so only need check if c0<0xFFFF is BMP code point - if c0 != c1 { + if c0 != c1.to_int() { ctx.invalid_char(shift=-1) } } else { @@ -67,7 +67,7 @@ fn ParseContext::expect_char( ctx.invalid_char(shift=-1) } let c2 = ctx.input.unsafe_charcode_at(ctx.offset) - let c3 = (c1 << 10) + c2 - 0x35fdc00 + let c3 = (c1.to_int() << 10) + c2.to_int() - 0x35fdc00 if c3 != c0 { ctx.invalid_char(shift=-1) } else { @@ -86,7 +86,7 @@ fn ParseContext::expect_ascii_char( guard ctx.offset < ctx.end_offset else { raise InvalidEof } let c1 = ctx.input.unsafe_charcode_at(ctx.offset) ctx.offset += 1 - if c.to_int() != c1 { + if c.to_uint16() != c1 { ctx.invalid_char(shift=-1) } } diff --git a/strconv/decimal.mbt b/strconv/decimal.mbt index a861835a2..98e9edc37 100644 --- a/strconv/decimal.mbt +++ b/strconv/decimal.mbt @@ -449,8 +449,8 @@ fn new_digits(self : Decimal, s : Int) -> Int { break } let d = cheat_num.unsafe_charcode_at(i) - '0' - if self.digits[i].to_int() != d { - less = self.digits[i].to_int() < d + if self.digits[i].to_uint16() != d { + less = self.digits[i].to_uint16() < d break } } diff --git a/string/methods.mbt b/string/methods.mbt index 4ea8f9f3f..b9802bdc7 100644 --- a/string/methods.mbt +++ b/string/methods.mbt @@ -67,11 +67,14 @@ fn boyer_moore_horspool_find(haystack : View, needle : View) -> Int? { // Build skip table let skip_table = FixedArray::make(1 << 8, needle_len) for i in 0..<(needle_len - 1) { - skip_table[needle.unsafe_charcode_at(i) & 0xFF] = needle_len - 1 - i + skip_table[(needle.unsafe_charcode_at(i) & 0xFF).to_int()] = needle_len - + 1 - + i } for i = 0 i <= haystack_len - needle_len - i = i + skip_table[haystack.unsafe_charcode_at(i + needle_len - 1) & 0xFF] { + i = i + + skip_table[(haystack.unsafe_charcode_at(i + needle_len - 1) & 0xFF).to_int()] { // Check all charcodes for match at current position for j in 0..=(needle_len - 1) { if haystack.unsafe_charcode_at(i + j) != needle.unsafe_charcode_at(j) { @@ -212,11 +215,11 @@ fn boyer_moore_horspool_rev_find(haystack : View, needle : View) -> Int? { guard haystack_len >= needle_len else { return None } let skip_table = FixedArray::make(1 << 8, needle_len) for i = needle_len - 1; i > 0; i = i - 1 { - skip_table[needle.unsafe_charcode_at(i) & 0xFF] = i + skip_table[(needle.unsafe_charcode_at(i) & 0xFF).to_int()] = i } for i = haystack_len - needle_len i >= 0 - i = i - skip_table[haystack.unsafe_charcode_at(i) & 0xFF] { + i = i - skip_table[(haystack.unsafe_charcode_at(i) & 0xFF).to_int()] { // Check all charcodes for match at current position for j in 0.. Bool { let c = c.to_int() if c <= 0xFFFF { // Search BMP + let c = c.to_uint16() for i in 0.. Bool { guard len >= 2 else { return false } // Calc surrogate pair let adj = c - 0x10000 - let high = 0xD800 + (adj >> 10) - let low = 0xDC00 + (adj & 0x3FF) + let high = (0xD800 + (adj >> 10)).to_uint16() + let low = (0xDC00 + (adj & 0x3FF)).to_uint16() // Search surrogate pair let mut i = 0 while i < len - 1 { @@ -1479,7 +1483,7 @@ test "rev_fold" { ///| /// Returns the UTF-16 code unit at the given index. Returns `None` if the index /// is out of bounds. -pub fn String::get(self : String, idx : Int) -> Int? { +pub fn String::get(self : String, idx : Int) -> UInt16? { guard idx >= 0 && idx < self.length() else { return None } Some(self.unsafe_charcode_at(idx)) } @@ -1487,7 +1491,7 @@ pub fn String::get(self : String, idx : Int) -> Int? { ///| /// Returns the UTF-16 code unit at the given index. Returns `None` if the index /// is out of bounds. -pub fn View::get(self : View, idx : Int) -> Int? { +pub fn View::get(self : View, idx : Int) -> UInt16? { guard idx >= 0 && idx < self.length() else { return None } Some(self.unsafe_charcode_at(idx)) } diff --git a/string/pkg.generated.mbti b/string/pkg.generated.mbti index 59bc31f4c..c6a3440ac 100644 --- a/string/pkg.generated.mbti +++ b/string/pkg.generated.mbti @@ -24,7 +24,7 @@ fn View::find_by(Self, (Char) -> Bool) -> Int? fn[A] View::fold(Self, init~ : A, (A, Char) -> A) -> A fn View::from_array(Array[Char]) -> Self fn View::from_iter(Iter[Char]) -> Self -fn View::get(Self, Int) -> Int? +fn View::get(Self, Int) -> UInt16? fn View::get_char(Self, Int) -> Char? #alias(starts_with, deprecated) fn View::has_prefix(Self, Self) -> Bool @@ -37,7 +37,7 @@ fn View::iter2(Self) -> Iter2[Int, Char] fn View::length(Self) -> Int fn View::make(Int, Char) -> Self fn View::offset_of_nth_char(Self, Int) -> Int? -fn View::op_get(Self, Int) -> Int +fn View::op_get(Self, Int) -> UInt16 fn View::pad_end(Self, Int, Char) -> String fn View::pad_start(Self, Int, Char) -> String fn View::repeat(Self, Int) -> Self @@ -61,7 +61,7 @@ fn View::trim(Self, Self) -> Self fn View::trim_end(Self, Self) -> Self fn View::trim_space(Self) -> Self fn View::trim_start(Self, Self) -> Self -fn View::unsafe_charcode_at(Self, Int) -> Int +fn View::unsafe_charcode_at(Self, Int) -> UInt16 fn View::view(Self, start_offset? : Int, end_offset? : Int) -> Self impl Add for View impl Compare for View @@ -83,7 +83,7 @@ fn[A] String::fold(String, init~ : A, (A, Char) -> A) -> A fn String::from_array(Array[Char]) -> String #as_free_fn fn String::from_iter(Iter[Char]) -> String -fn String::get(String, Int) -> Int? +fn String::get(String, Int) -> UInt16? fn String::get_char(String, Int) -> Char? #alias(starts_with, deprecated) fn String::has_prefix(String, View) -> Bool diff --git a/string/utils.mbt b/string/utils.mbt index c784e1477..458ac6abf 100644 --- a/string/utils.mbt +++ b/string/utils.mbt @@ -13,15 +13,17 @@ // limitations under the License. ///| -fn code_point_of_surrogate_pair(leading : Int, trailing : Int) -> Char { +fn code_point_of_surrogate_pair(leading : UInt16, trailing : UInt16) -> Char { + let leading = leading.to_int() + let trailing = trailing.to_int() ((leading - 0xD800) * 0x400 + trailing - 0xDC00 + 0x10000).unsafe_to_char() } ///| test "code_point_of_surrogate_pair" { let s = "😀" - let leading = s.charcode_at(0) - let trailing = s.charcode_at(1) + let leading = s.unsafe_charcode_at(0) + let trailing = s.unsafe_charcode_at(1) inspect(code_point_of_surrogate_pair(leading, trailing), content="😀") } diff --git a/string/view.mbt b/string/view.mbt index c914be3ba..b45fb9e4f 100644 --- a/string/view.mbt +++ b/string/view.mbt @@ -44,10 +44,10 @@ fn View::make_view(str : String, start : Int, end : Int) -> View = "%stringview. /// ```mbt /// let str = "Hello🤣🤣🤣" /// let view = str.view(start_offset = str.offset_of_nth_char(1).unwrap(), end_offset = str.offset_of_nth_char(6).unwrap()) -/// inspect(view[0].to_char(), content="Some('e')") +/// inspect(view[0].to_int().to_char(), content="Some('e')") /// inspect(view[4], content="55358") /// ``` -pub fn View::op_get(self : View, index : Int) -> Int { +pub fn View::op_get(self : View, index : Int) -> UInt16 { guard index >= 0 && index < self.length() else { abort("Index out of bounds") } @@ -160,7 +160,7 @@ pub fn View::offset_of_nth_char(self : View, i : Int) -> Int? { /// inspect(view.unsafe_charcode_at(5), content="67") /// ``` /// TODO: rename to `unsafe_get` -pub fn View::unsafe_charcode_at(self : View, index : Int) -> Int { +pub fn View::unsafe_charcode_at(self : View, index : Int) -> UInt16 { self.str().unsafe_charcode_at(self.start() + index) } @@ -352,7 +352,7 @@ pub impl ToJson for View with to_json(self) { ///| pub impl Hash for View with hash_combine(self : View, hasher : Hasher) -> Unit { for i in 0.. UInt -fn UInt16::to_uint64(UInt16) -> UInt64 -impl Add for UInt16 -impl BitAnd for UInt16 -impl BitOr for UInt16 -impl BitXOr for UInt16 -impl Compare for UInt16 impl Default for UInt16 -impl Div for UInt16 -impl Eq for UInt16 impl Hash for UInt16 -impl Mod for UInt16 -impl Mul for UInt16 -impl Shl for UInt16 -impl Shr for UInt16 -impl Sub for UInt16 impl ToJson for UInt16 // Type aliases diff --git a/uint16/uint16.mbt b/uint16/uint16.mbt index d0c65f40b..bafd21644 100644 --- a/uint16/uint16.mbt +++ b/uint16/uint16.mbt @@ -18,77 +18,6 @@ pub let max_value : UInt16 = 65535 ///| pub let min_value : UInt16 = 0 -///| -pub impl Add for UInt16 with add(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() + that.to_int()).to_uint16() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Add for UInt16 with op_add(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() + that.to_int()).to_uint16() -} - -///| -pub impl Sub for UInt16 with sub(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() - that.to_int()).to_uint16() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Sub for UInt16 with op_sub(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() - that.to_int()).to_uint16() -} - -///| -pub impl Mul for UInt16 with mul(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() * that.to_int()).to_uint16() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Mul for UInt16 with op_mul(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() * that.to_int()).to_uint16() -} - -///| -pub impl Div for UInt16 with div(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() / that.to_int()).to_uint16() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Div for UInt16 with op_div(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() / that.to_int()).to_uint16() -} - -///| -pub impl Mod for UInt16 with mod(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() % that.to_int()).to_uint16() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Mod for UInt16 with op_mod(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() % that.to_int()).to_uint16() -} - -///| -pub impl Eq for UInt16 with equal(self, that) { - self.to_int() == that.to_int() -} - -///| -// TODO: remove this after we migrate compiler to new names -pub impl Eq for UInt16 with op_equal(self, that) { - self.to_int() == that.to_int() -} - -///| -pub impl Compare for UInt16 with compare(self, that) { - self.to_int().compare(that.to_int()) -} - ///| pub impl Hash for UInt16 with hash(self) { self.to_int() @@ -99,31 +28,6 @@ pub impl Hash for UInt16 with hash_combine(self, hasher) { hasher.combine_int(self.to_int()) } -///| -pub impl Shl for UInt16 with shl(self : UInt16, that : Int) -> UInt16 { - (self.to_int() << that).to_uint16() -} - -///| -pub impl Shr for UInt16 with shr(self : UInt16, that : Int) -> UInt16 { - (self.to_int() >> that).to_uint16() -} - -///| -pub impl BitOr for UInt16 with lor(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() | that.to_int()).to_uint16() -} - -///| -pub impl BitAnd for UInt16 with land(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() & that.to_int()).to_uint16() -} - -///| -pub impl BitXOr for UInt16 with lxor(self : UInt16, that : UInt16) -> UInt16 { - (self.to_int() ^ that.to_int()).to_uint16() -} - ///| pub impl Default for UInt16 with default() { 0 @@ -133,13 +37,3 @@ pub impl Default for UInt16 with default() { pub impl ToJson for UInt16 with to_json(self : UInt16) -> Json { Json::number(self.to_int().to_double()) } - -///| -pub fn UInt16::to_uint(self : UInt16) -> UInt { - self.to_int().reinterpret_as_uint() -} - -///| -pub fn UInt16::to_uint64(self : UInt16) -> UInt64 { - self.to_int().to_uint64() -}