From 8f1539d5bda90ef3a81fe0c122eacc81ba1639f1 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 14:32:35 +0800 Subject: [PATCH 01/35] Add truncate to array and join/drain/flatten to deque --- array/array.mbt | 37 +++++++++++++ array/array.mbti | 1 + deque/deque.mbt | 135 +++++++++++++++++++++++++++++++++++++++++++++++ deque/deque.mbti | 3 ++ 4 files changed, 176 insertions(+) diff --git a/array/array.mbt b/array/array.mbt index 4d188470f..6305532a8 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -291,6 +291,43 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { }) } +///| +/// Truncates the array in-place to the specified length. +/// +/// If `len` is greater than or equal to the current array length, +/// the function does nothing. If `len` is 0, the array is cleared. +/// Otherwise, removes elements from the end until the array reaches the given length. +/// +/// Parameters: +/// +/// * `self` : The target array (modified in-place). +/// * `len` : The new desired length (must be non-negative). +/// +/// Important: +/// - If `len` is negative, the function does nothing. +/// - If `len` exceeds current length, the array remains unchanged. +/// +/// Example: +/// +/// ```moonbit +/// test "truncate" { +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") +/// } +/// ``` +pub fn truncate[A](self : Array[A], len : Int) -> Unit { + guard len >= 0 && len < self.length() else { return } + if len == 0 { + self.clear() + return + } + let length = self.length() - len + for i = 0; i < length; i = i + 1 { + ignore(self.pop_exn()) + } +} + ///| pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbitrary( size, diff --git a/array/array.mbti b/array/array.mbti index 1d3a8eaca..7d8f7f454 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -83,6 +83,7 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit +fn[T] Array::truncate[A](Self[A], Int) -> Unit fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] diff --git a/deque/deque.mbt b/deque/deque.mbt index db419bb29..46defacad 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1243,6 +1243,141 @@ pub fn[A] to_array(self : T[A]) -> Array[A] { } } +///| +/// Joins the elements of a string deque into a single string, +/// separated by the specified separator. +/// +/// Parameters: +/// +/// * `self` : The deque of strings to join. +/// * `separator` : The separator to insert between elements (as a string view). +/// +/// Returns the concatenated string. +/// - If the deque is empty, returns an empty string. +/// - Efficiently pre-allocates memory based on calculated size hint. +/// - Handles empty separators efficiently by direct concatenation. +/// +/// Example: +/// +/// ```moonbit +/// test "join" { +/// let deque = @deque.of(["a","b","c"]) +/// let s1 = deque.join("") +/// inspect(s1, content="abc") +/// +/// let s2 = deque.join(",") +/// inspect(s2, content="a,b,c") +/// } +/// ``` +pub fn join(self : T[String], separator : @string.View) -> String { + let len = self.length() + if len == 0 { + "" + } else { + let first = self[0] + let mut size_hint = first.length() + for i = 1; i < len; i = i + 1 { + size_hint += separator.length() + self[i].length() + } + let string = StringBuilder::new(size_hint~) + string.write_string(self[0]) + if separator.is_empty() { + for i = 1; i < len; i = i + 1 { + string.write_string(self[i]) + } + } else { + for i = 1; i < len; i = i + 1 { + string.write_string(separator.to_string()) + string.write_string(self[i]) + } + } + string.to_string() + } +} + +///| +/// Removes and returns elements in the specified range [begin, end) from the deque. +/// +/// Parameters: +/// +/// * `self` : The target deque (modified in-place). +/// * `begin` : Start index of the range (inclusive). +/// * `end` : End index of the range (exclusive). +/// +/// Important: +/// - Requires `0 <= begin <= end <= self.length()` +/// - Returns a new deque containing the drained elements. +/// - Original deque retains elements outside [begin, end) in original order. +/// +/// Example: +/// +/// ```moonbit +/// test "drain" { +/// let deque = @deque.of([1,2,3,4,5,6,7,8,9]) +/// let deque_test = deque.drain(2, 6) +/// inspect(deque_test, content="@deque.of([3, 4, 5, 6])") +/// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") +/// } +/// ``` +pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { + guard begin >= 0 && end <= self.length() && begin <= end + let deque = self.copy() + deque.clear() + let length = self.length() + for i = 0; i < length; i = i + 1 { + match self.pop_front() { + Some(pop) => + if i > begin - 1 && i < end { + deque.push_back(pop) + } else { + self.push_back(pop) + } + None => () + } + } + deque +} + +///| +/// Flattens a high-dimensional deque into a lower-dimensional deque +/// by concatenating all inner deques in order. +/// +/// Parameters: +/// +/// * `self` : The high-dimensional deque to flatten. +/// +/// Returns a new lower-dimensional deque containing all elements +/// from inner deques in sequence. +/// +/// Note: +/// - Uses the first inner deque as base and appends subsequent deques. +/// - Efficiently preserves element order across all inner deques. +/// +/// Example: +/// +/// ```moonbit +/// test "flatten" { +/// let deque = @deque.of([@deque.of([1,2,3]),@deque.of([4,5,6]),@deque.of([7,8])]) +/// let deque_test = deque.flatten() +/// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") +/// } +/// ``` +pub fn flatten[A](self : T[T[A]]) -> T[A] { + let deque = self[0].copy() + let len = self.length() + let mut selflen = 0 + for i = 1; i < len; i = i + 1 { + selflen = self[i].length() + for j = 0; j < selflen; j = j + 1 { + match self[i].pop_front() { + Some(pop) => deque.push_back(pop) + None => () + } + } + } + deque +} + ///| pub impl[A : ToJson] ToJson for T[A] with to_json(self : T[A]) -> Json { let res = Array::make(self.length(), Json::null()) diff --git a/deque/deque.mbti b/deque/deque.mbti index 208c6a120..20c95f93b 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -96,14 +96,17 @@ fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool fn[A] T::copy(Self[A]) -> Self[A] +fn[A] T::drain[A] (Self[A], Int, Int) -> Self[A] fn[A] T::each(Self[A], (A) -> Unit) -> Unit fn[A] T::eachi(Self[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] T::filter_map_inplace(Self[A], (A) -> A?) -> Unit +fn[A] T::flatten[A](Self[Self[A]]) -> Self[A] fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] +fn T::join(Self[String], String) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From c66b6902c97f957608d5017e26cd60debf98ad75 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 14:48:33 +0800 Subject: [PATCH 02/35] add string package for deque --- deque/moon.pkg.json | 1 + 1 file changed, 1 insertion(+) diff --git a/deque/moon.pkg.json b/deque/moon.pkg.json index af0404932..5fcb9ec81 100644 --- a/deque/moon.pkg.json +++ b/deque/moon.pkg.json @@ -2,6 +2,7 @@ "import": [ "moonbitlang/core/builtin", "moonbitlang/core/json", + "moonbitlang/core/string", "moonbitlang/core/array" ], "targets": { From c8132b43ce6a548c5b017e8c1fd90d3d3c8a744f Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 16:57:55 +0800 Subject: [PATCH 03/35] format code --- array/array.mbti | 4 +++- deque/deque.mbti | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/array/array.mbti b/array/array.mbti index 7d8f7f454..a8e515955 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -27,6 +27,8 @@ fn[T] sort_by(Array[T], (T, T) -> Int) -> Unit fn[T, K : Compare] sort_by_key(Array[T], (T) -> K) -> Unit +fn[A] truncate(Array[A], Int) -> Unit + fn[A, B] zip(Array[A], Array[B]) -> Array[(A, B)] fn[A, B] zip_to_iter2(Array[A], Array[B]) -> Iter2[A, B] @@ -83,7 +85,7 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit -fn[T] Array::truncate[A](Self[A], Int) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] diff --git a/deque/deque.mbti b/deque/deque.mbti index 20c95f93b..bff5883ee 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -2,6 +2,7 @@ package "moonbitlang/core/deque" import( "moonbitlang/core/json" + "moonbitlang/core/string" ) // Values @@ -15,6 +16,8 @@ fn[A : Eq] contains(T[A], A) -> Bool fn[A] copy(T[A]) -> T[A] +fn[A] drain(T[A], Int, Int) -> T[A] + fn[A] each(T[A], (A) -> Unit) -> Unit fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit @@ -22,6 +25,8 @@ fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] filter_map_inplace(T[A], (A) -> A?) -> Unit +fn[A] flatten(T[T[A]]) -> T[A] + fn[A] from_array(Array[A]) -> T[A] fn[A] from_iter(Iter[A]) -> T[A] @@ -34,6 +39,8 @@ fn[A] iter(T[A]) -> Iter[A] fn[A] iter2(T[A]) -> Iter2[Int, A] +fn join(T[String], @string.StringView) -> String + fn[A] length(T[A]) -> Int fn[A, U] map(T[A], (A) -> U) -> T[U] @@ -96,17 +103,17 @@ fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool fn[A] T::copy(Self[A]) -> Self[A] -fn[A] T::drain[A] (Self[A], Int, Int) -> Self[A] +fn[A] T::drain(Self[A], Int, Int) -> Self[A] fn[A] T::each(Self[A], (A) -> Unit) -> Unit fn[A] T::eachi(Self[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] T::filter_map_inplace(Self[A], (A) -> A?) -> Unit -fn[A] T::flatten[A](Self[Self[A]]) -> Self[A] +fn[A] T::flatten(Self[Self[A]]) -> Self[A] fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] -fn T::join(Self[String], String) -> String +fn T::join(Self[String], @string.StringView) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From 847e61ba00ca0287ccbbf3f891da77301a4c3cf3 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 17:12:31 +0800 Subject: [PATCH 04/35] format code --- array/array.mbt | 2 +- deque/deque.mbt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index 6305532a8..e609e1942 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -316,7 +316,7 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { /// inspect(arr, content="[1, 2, 3]") /// } /// ``` -pub fn truncate[A](self : Array[A], len : Int) -> Unit { +pub fn[A] truncate(self : Array[A], len : Int) -> Unit { guard len >= 0 && len < self.length() else { return } if len == 0 { self.clear() diff --git a/deque/deque.mbt b/deque/deque.mbt index 46defacad..1cfc82e1f 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1319,7 +1319,7 @@ pub fn join(self : T[String], separator : @string.View) -> String { /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// } /// ``` -pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { +pub fn[A] drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end let deque = self.copy() deque.clear() @@ -1362,7 +1362,7 @@ pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { /// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") /// } /// ``` -pub fn flatten[A](self : T[T[A]]) -> T[A] { +pub fn[A] flatten(self : T[T[A]]) -> T[A] { let deque = self[0].copy() let len = self.length() let mut selflen = 0 From c01e2a1a4813b4777728aca510efe8e8e6787d29 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 14:32:35 +0800 Subject: [PATCH 05/35] Add truncate to array and join/drain/flatten to deque --- array/array.mbt | 37 +++++++++++++ array/array.mbti | 1 + deque/deque.mbt | 135 +++++++++++++++++++++++++++++++++++++++++++++++ deque/deque.mbti | 3 ++ 4 files changed, 176 insertions(+) diff --git a/array/array.mbt b/array/array.mbt index 4d188470f..6305532a8 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -291,6 +291,43 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { }) } +///| +/// Truncates the array in-place to the specified length. +/// +/// If `len` is greater than or equal to the current array length, +/// the function does nothing. If `len` is 0, the array is cleared. +/// Otherwise, removes elements from the end until the array reaches the given length. +/// +/// Parameters: +/// +/// * `self` : The target array (modified in-place). +/// * `len` : The new desired length (must be non-negative). +/// +/// Important: +/// - If `len` is negative, the function does nothing. +/// - If `len` exceeds current length, the array remains unchanged. +/// +/// Example: +/// +/// ```moonbit +/// test "truncate" { +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") +/// } +/// ``` +pub fn truncate[A](self : Array[A], len : Int) -> Unit { + guard len >= 0 && len < self.length() else { return } + if len == 0 { + self.clear() + return + } + let length = self.length() - len + for i = 0; i < length; i = i + 1 { + ignore(self.pop_exn()) + } +} + ///| pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbitrary( size, diff --git a/array/array.mbti b/array/array.mbti index 1d3a8eaca..7d8f7f454 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -83,6 +83,7 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit +fn[T] Array::truncate[A](Self[A], Int) -> Unit fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] diff --git a/deque/deque.mbt b/deque/deque.mbt index db419bb29..46defacad 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1243,6 +1243,141 @@ pub fn[A] to_array(self : T[A]) -> Array[A] { } } +///| +/// Joins the elements of a string deque into a single string, +/// separated by the specified separator. +/// +/// Parameters: +/// +/// * `self` : The deque of strings to join. +/// * `separator` : The separator to insert between elements (as a string view). +/// +/// Returns the concatenated string. +/// - If the deque is empty, returns an empty string. +/// - Efficiently pre-allocates memory based on calculated size hint. +/// - Handles empty separators efficiently by direct concatenation. +/// +/// Example: +/// +/// ```moonbit +/// test "join" { +/// let deque = @deque.of(["a","b","c"]) +/// let s1 = deque.join("") +/// inspect(s1, content="abc") +/// +/// let s2 = deque.join(",") +/// inspect(s2, content="a,b,c") +/// } +/// ``` +pub fn join(self : T[String], separator : @string.View) -> String { + let len = self.length() + if len == 0 { + "" + } else { + let first = self[0] + let mut size_hint = first.length() + for i = 1; i < len; i = i + 1 { + size_hint += separator.length() + self[i].length() + } + let string = StringBuilder::new(size_hint~) + string.write_string(self[0]) + if separator.is_empty() { + for i = 1; i < len; i = i + 1 { + string.write_string(self[i]) + } + } else { + for i = 1; i < len; i = i + 1 { + string.write_string(separator.to_string()) + string.write_string(self[i]) + } + } + string.to_string() + } +} + +///| +/// Removes and returns elements in the specified range [begin, end) from the deque. +/// +/// Parameters: +/// +/// * `self` : The target deque (modified in-place). +/// * `begin` : Start index of the range (inclusive). +/// * `end` : End index of the range (exclusive). +/// +/// Important: +/// - Requires `0 <= begin <= end <= self.length()` +/// - Returns a new deque containing the drained elements. +/// - Original deque retains elements outside [begin, end) in original order. +/// +/// Example: +/// +/// ```moonbit +/// test "drain" { +/// let deque = @deque.of([1,2,3,4,5,6,7,8,9]) +/// let deque_test = deque.drain(2, 6) +/// inspect(deque_test, content="@deque.of([3, 4, 5, 6])") +/// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") +/// } +/// ``` +pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { + guard begin >= 0 && end <= self.length() && begin <= end + let deque = self.copy() + deque.clear() + let length = self.length() + for i = 0; i < length; i = i + 1 { + match self.pop_front() { + Some(pop) => + if i > begin - 1 && i < end { + deque.push_back(pop) + } else { + self.push_back(pop) + } + None => () + } + } + deque +} + +///| +/// Flattens a high-dimensional deque into a lower-dimensional deque +/// by concatenating all inner deques in order. +/// +/// Parameters: +/// +/// * `self` : The high-dimensional deque to flatten. +/// +/// Returns a new lower-dimensional deque containing all elements +/// from inner deques in sequence. +/// +/// Note: +/// - Uses the first inner deque as base and appends subsequent deques. +/// - Efficiently preserves element order across all inner deques. +/// +/// Example: +/// +/// ```moonbit +/// test "flatten" { +/// let deque = @deque.of([@deque.of([1,2,3]),@deque.of([4,5,6]),@deque.of([7,8])]) +/// let deque_test = deque.flatten() +/// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") +/// } +/// ``` +pub fn flatten[A](self : T[T[A]]) -> T[A] { + let deque = self[0].copy() + let len = self.length() + let mut selflen = 0 + for i = 1; i < len; i = i + 1 { + selflen = self[i].length() + for j = 0; j < selflen; j = j + 1 { + match self[i].pop_front() { + Some(pop) => deque.push_back(pop) + None => () + } + } + } + deque +} + ///| pub impl[A : ToJson] ToJson for T[A] with to_json(self : T[A]) -> Json { let res = Array::make(self.length(), Json::null()) diff --git a/deque/deque.mbti b/deque/deque.mbti index 208c6a120..20c95f93b 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -96,14 +96,17 @@ fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool fn[A] T::copy(Self[A]) -> Self[A] +fn[A] T::drain[A] (Self[A], Int, Int) -> Self[A] fn[A] T::each(Self[A], (A) -> Unit) -> Unit fn[A] T::eachi(Self[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] T::filter_map_inplace(Self[A], (A) -> A?) -> Unit +fn[A] T::flatten[A](Self[Self[A]]) -> Self[A] fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] +fn T::join(Self[String], String) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From 40f9691833f247b1e1b7bcf7b4bac51cbb81c910 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 14:48:33 +0800 Subject: [PATCH 06/35] add string package for deque --- deque/moon.pkg.json | 1 + 1 file changed, 1 insertion(+) diff --git a/deque/moon.pkg.json b/deque/moon.pkg.json index af0404932..5fcb9ec81 100644 --- a/deque/moon.pkg.json +++ b/deque/moon.pkg.json @@ -2,6 +2,7 @@ "import": [ "moonbitlang/core/builtin", "moonbitlang/core/json", + "moonbitlang/core/string", "moonbitlang/core/array" ], "targets": { From bc585ad5faef26e5629a08911e64ec893977285b Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 16:57:55 +0800 Subject: [PATCH 07/35] format code --- array/array.mbti | 4 +++- deque/deque.mbti | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/array/array.mbti b/array/array.mbti index 7d8f7f454..a8e515955 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -27,6 +27,8 @@ fn[T] sort_by(Array[T], (T, T) -> Int) -> Unit fn[T, K : Compare] sort_by_key(Array[T], (T) -> K) -> Unit +fn[A] truncate(Array[A], Int) -> Unit + fn[A, B] zip(Array[A], Array[B]) -> Array[(A, B)] fn[A, B] zip_to_iter2(Array[A], Array[B]) -> Iter2[A, B] @@ -83,7 +85,7 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit -fn[T] Array::truncate[A](Self[A], Int) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] diff --git a/deque/deque.mbti b/deque/deque.mbti index 20c95f93b..bff5883ee 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -2,6 +2,7 @@ package "moonbitlang/core/deque" import( "moonbitlang/core/json" + "moonbitlang/core/string" ) // Values @@ -15,6 +16,8 @@ fn[A : Eq] contains(T[A], A) -> Bool fn[A] copy(T[A]) -> T[A] +fn[A] drain(T[A], Int, Int) -> T[A] + fn[A] each(T[A], (A) -> Unit) -> Unit fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit @@ -22,6 +25,8 @@ fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] filter_map_inplace(T[A], (A) -> A?) -> Unit +fn[A] flatten(T[T[A]]) -> T[A] + fn[A] from_array(Array[A]) -> T[A] fn[A] from_iter(Iter[A]) -> T[A] @@ -34,6 +39,8 @@ fn[A] iter(T[A]) -> Iter[A] fn[A] iter2(T[A]) -> Iter2[Int, A] +fn join(T[String], @string.StringView) -> String + fn[A] length(T[A]) -> Int fn[A, U] map(T[A], (A) -> U) -> T[U] @@ -96,17 +103,17 @@ fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool fn[A] T::copy(Self[A]) -> Self[A] -fn[A] T::drain[A] (Self[A], Int, Int) -> Self[A] +fn[A] T::drain(Self[A], Int, Int) -> Self[A] fn[A] T::each(Self[A], (A) -> Unit) -> Unit fn[A] T::eachi(Self[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] T::filter_map_inplace(Self[A], (A) -> A?) -> Unit -fn[A] T::flatten[A](Self[Self[A]]) -> Self[A] +fn[A] T::flatten(Self[Self[A]]) -> Self[A] fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] -fn T::join(Self[String], String) -> String +fn T::join(Self[String], @string.StringView) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From 231b5c4b6a9b4750fef3340663f242d2ac7ba96a Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 31 May 2025 17:12:31 +0800 Subject: [PATCH 08/35] format code --- array/array.mbt | 2 +- deque/deque.mbt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index 6305532a8..e609e1942 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -316,7 +316,7 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { /// inspect(arr, content="[1, 2, 3]") /// } /// ``` -pub fn truncate[A](self : Array[A], len : Int) -> Unit { +pub fn[A] truncate(self : Array[A], len : Int) -> Unit { guard len >= 0 && len < self.length() else { return } if len == 0 { self.clear() diff --git a/deque/deque.mbt b/deque/deque.mbt index 46defacad..1cfc82e1f 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1319,7 +1319,7 @@ pub fn join(self : T[String], separator : @string.View) -> String { /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// } /// ``` -pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { +pub fn[A] drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end let deque = self.copy() deque.clear() @@ -1362,7 +1362,7 @@ pub fn drain[A](self : T[A], begin : Int, end : Int) -> T[A] { /// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") /// } /// ``` -pub fn flatten[A](self : T[T[A]]) -> T[A] { +pub fn[A] flatten(self : T[T[A]]) -> T[A] { let deque = self[0].copy() let len = self.length() let mut selflen = 0 From 88e38dca70b4d710cbd5507c08176c5958d18b72 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sun, 1 Jun 2025 12:09:37 +0800 Subject: [PATCH 09/35] Change implementation of Array::truncate Change implementation of deque::join Change truncate from function to array method Change join,drain,flatten from function to deque method --- array/array.mbt | 10 +++++----- deque/deque.mbt | 30 ++++-------------------------- deque/deque.mbti | 1 - deque/moon.pkg.json | 1 - 4 files changed, 9 insertions(+), 33 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index e609e1942..fb8667d8a 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -316,16 +316,16 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { /// inspect(arr, content="[1, 2, 3]") /// } /// ``` -pub fn[A] truncate(self : Array[A], len : Int) -> Unit { +pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { guard len >= 0 && len < self.length() else { return } if len == 0 { self.clear() return } - let length = self.length() - len - for i = 0; i < length; i = i + 1 { - ignore(self.pop_exn()) - } + let a = self[0:length] + let array = a.to_array() + self.clear() + self.append(array) } ///| diff --git a/deque/deque.mbt b/deque/deque.mbt index 1cfc82e1f..22085cd7b 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1269,30 +1269,8 @@ pub fn[A] to_array(self : T[A]) -> Array[A] { /// inspect(s2, content="a,b,c") /// } /// ``` -pub fn join(self : T[String], separator : @string.View) -> String { - let len = self.length() - if len == 0 { - "" - } else { - let first = self[0] - let mut size_hint = first.length() - for i = 1; i < len; i = i + 1 { - size_hint += separator.length() + self[i].length() - } - let string = StringBuilder::new(size_hint~) - string.write_string(self[0]) - if separator.is_empty() { - for i = 1; i < len; i = i + 1 { - string.write_string(self[i]) - } - } else { - for i = 1; i < len; i = i + 1 { - string.write_string(separator.to_string()) - string.write_string(self[i]) - } - } - string.to_string() - } +pub fn T::join(self : T[String], separator : String) -> String { + self.iter().join(separator) } ///| @@ -1319,7 +1297,7 @@ pub fn join(self : T[String], separator : @string.View) -> String { /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// } /// ``` -pub fn[A] drain(self : T[A], begin : Int, end : Int) -> T[A] { +pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end let deque = self.copy() deque.clear() @@ -1362,7 +1340,7 @@ pub fn[A] drain(self : T[A], begin : Int, end : Int) -> T[A] { /// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") /// } /// ``` -pub fn[A] flatten(self : T[T[A]]) -> T[A] { +pub fn[A] T::flatten(self : T[T[A]]) -> T[A] { let deque = self[0].copy() let len = self.length() let mut selflen = 0 diff --git a/deque/deque.mbti b/deque/deque.mbti index bff5883ee..b9e83b5c2 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -2,7 +2,6 @@ package "moonbitlang/core/deque" import( "moonbitlang/core/json" - "moonbitlang/core/string" ) // Values diff --git a/deque/moon.pkg.json b/deque/moon.pkg.json index 5fcb9ec81..af0404932 100644 --- a/deque/moon.pkg.json +++ b/deque/moon.pkg.json @@ -2,7 +2,6 @@ "import": [ "moonbitlang/core/builtin", "moonbitlang/core/json", - "moonbitlang/core/string", "moonbitlang/core/array" ], "targets": { From bef5f72d4373ed0c1a26492d8c1a703cd7fd2747 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sun, 1 Jun 2025 14:37:50 +0800 Subject: [PATCH 10/35] correct variable typo from 'length' to 'len'" --- array/array.mbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array/array.mbt b/array/array.mbt index fb8667d8a..eb7b8f28c 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -322,7 +322,7 @@ pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { self.clear() return } - let a = self[0:length] + let a = self[0:len] let array = a.to_array() self.clear() self.append(array) From be3017411a4a87ed85b31ef09ea5b82ff6ae352c Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sun, 1 Jun 2025 15:30:00 +0800 Subject: [PATCH 11/35] remove redundant import of string module --- deque/deque.mbti | 1 - deque/moon.pkg.json | 1 - 2 files changed, 2 deletions(-) diff --git a/deque/deque.mbti b/deque/deque.mbti index bff5883ee..b9e83b5c2 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -2,7 +2,6 @@ package "moonbitlang/core/deque" import( "moonbitlang/core/json" - "moonbitlang/core/string" ) // Values diff --git a/deque/moon.pkg.json b/deque/moon.pkg.json index 5fcb9ec81..af0404932 100644 --- a/deque/moon.pkg.json +++ b/deque/moon.pkg.json @@ -2,7 +2,6 @@ "import": [ "moonbitlang/core/builtin", "moonbitlang/core/json", - "moonbitlang/core/string", "moonbitlang/core/array" ], "targets": { From 0f66422e0363530baeb71740bfe90b9de96a8b74 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sun, 1 Jun 2025 17:23:20 +0800 Subject: [PATCH 12/35] correct parameter type --- deque/deque.mbti | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deque/deque.mbti b/deque/deque.mbti index b9e83b5c2..0f6cc1deb 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -38,7 +38,7 @@ fn[A] iter(T[A]) -> Iter[A] fn[A] iter2(T[A]) -> Iter2[Int, A] -fn join(T[String], @string.StringView) -> String +fn join(T[String], String) -> String fn[A] length(T[A]) -> Int @@ -112,7 +112,7 @@ fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] -fn T::join(Self[String], @string.StringView) -> String +fn T::join(Self[String], String) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From b99b5ab6cfc5324ae1a70ba1d8b3a2de38219f8d Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Thu, 5 Jun 2025 10:39:01 +0800 Subject: [PATCH 13/35] improve code consistency --- array/array.mbti | 2 -- deque/deque.mbti | 6 ------ 2 files changed, 8 deletions(-) diff --git a/array/array.mbti b/array/array.mbti index a8e515955..68d4210f1 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -27,8 +27,6 @@ fn[T] sort_by(Array[T], (T, T) -> Int) -> Unit fn[T, K : Compare] sort_by_key(Array[T], (T) -> K) -> Unit -fn[A] truncate(Array[A], Int) -> Unit - fn[A, B] zip(Array[A], Array[B]) -> Array[(A, B)] fn[A, B] zip_to_iter2(Array[A], Array[B]) -> Iter2[A, B] diff --git a/deque/deque.mbti b/deque/deque.mbti index 0f6cc1deb..8ad92a0f6 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -15,8 +15,6 @@ fn[A : Eq] contains(T[A], A) -> Bool fn[A] copy(T[A]) -> T[A] -fn[A] drain(T[A], Int, Int) -> T[A] - fn[A] each(T[A], (A) -> Unit) -> Unit fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit @@ -24,8 +22,6 @@ fn[A] eachi(T[A], (Int, A) -> Unit) -> Unit #deprecated fn[A] filter_map_inplace(T[A], (A) -> A?) -> Unit -fn[A] flatten(T[T[A]]) -> T[A] - fn[A] from_array(Array[A]) -> T[A] fn[A] from_iter(Iter[A]) -> T[A] @@ -38,8 +34,6 @@ fn[A] iter(T[A]) -> Iter[A] fn[A] iter2(T[A]) -> Iter2[Int, A] -fn join(T[String], String) -> String - fn[A] length(T[A]) -> Int fn[A, U] map(T[A], (A) -> U) -> T[U] From 80f3aeb440a048789f791b70e96233aa8d2043fe Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Mon, 16 Jun 2025 20:47:56 +0800 Subject: [PATCH 14/35] Replaced `copy + clear` with direct capacity reservation --- deque/deque.mbt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index 462e2fc46..64a5f2c3d 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1335,21 +1335,20 @@ pub fn T::join(self : T[String], separator : String) -> String { /// ``` pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end - let deque = self.copy() - deque.clear() + let dq = new(capacity=(end - begin)) let length = self.length() for i = 0; i < length; i = i + 1 { match self.pop_front() { Some(pop) => if i > begin - 1 && i < end { - deque.push_back(pop) + dq.push_back(pop) } else { self.push_back(pop) } None => () } } - deque + dq } ///| From 54e3cf48f4247a3e1214f1cc37f9a831b7b06915 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Mon, 16 Jun 2025 20:59:06 +0800 Subject: [PATCH 15/35] Move and improve implementation of Array::truncate --- array/array.mbt | 36 ------------------------------------ array/array.mbti | 1 - builtin/arraycore_nonjs.mbt | 34 ++++++++++++++++++++++++++++++++++ builtin/builtin.mbti | 1 + 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index 4b43dacd0..859e1f72d 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -295,42 +295,6 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { }) } -///| -/// Truncates the array in-place to the specified length. -/// -/// If `len` is greater than or equal to the current array length, -/// the function does nothing. If `len` is 0, the array is cleared. -/// Otherwise, removes elements from the end until the array reaches the given length. -/// -/// Parameters: -/// -/// * `self` : The target array (modified in-place). -/// * `len` : The new desired length (must be non-negative). -/// -/// Important: -/// - If `len` is negative, the function does nothing. -/// - If `len` exceeds current length, the array remains unchanged. -/// -/// Example: -/// -/// ```moonbit -/// test "truncate" { -/// let arr = [1, 2, 3, 4, 5] -/// arr.truncate(3) -/// inspect(arr, content="[1, 2, 3]") -/// } -/// ``` -pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { - guard len >= 0 && len < self.length() else { return } - if len == 0 { - self.clear() - return - } - let a = self[0:len] - let array = a.to_array() - self.clear() - self.append(array) -} ///| pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbitrary( diff --git a/array/array.mbti b/array/array.mbti index 68d4210f1..1d3a8eaca 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -83,7 +83,6 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit -fn[A] Array::truncate(Self[A], Int) -> Unit fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] diff --git a/builtin/arraycore_nonjs.mbt b/builtin/arraycore_nonjs.mbt index bb965214f..cfb63f01a 100644 --- a/builtin/arraycore_nonjs.mbt +++ b/builtin/arraycore_nonjs.mbt @@ -439,3 +439,37 @@ fn[T] Array::unsafe_grow_to_length(self : Array[T], new_len : Int) -> Unit { self.len = new_len self.buf = new_buf } + +///| +/// Truncates the array in-place to the specified length. +/// +/// If `len` is greater than or equal to the current array length, +/// the function does nothing. If `len` is 0, the array is cleared. +/// Otherwise, removes elements from the end until the array reaches the given length. +/// +/// Parameters: +/// +/// * `self` : The target array (modified in-place). +/// * `len` : The new desired length (must be non-negative). +/// +/// Important: +/// - If `len` is negative, the function does nothing. +/// - If `len` exceeds current length, the array remains unchanged. +/// +/// Example: +/// +/// ```moonbit +/// test "truncate" { +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") +/// } +/// ``` +pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { + guard len >= 0 && len < self.length() else { return } + if len == 0 { + self.clear() + return + } + self.unsafe_truncate_to_length(len) +} \ No newline at end of file diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 7e3be6509..3fc141c52 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -117,6 +117,7 @@ fn[T : Eq] Array::starts_with(Self[T], Self[T]) -> Bool fn[T : Eq] Array::strip_prefix(Self[T], Self[T]) -> Self[T]? fn[T : Eq] Array::strip_suffix(Self[T], Self[T]) -> Self[T]? fn[T] Array::swap(Self[T], Int, Int) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[A] Array::unsafe_blit(Self[A], Int, Self[A], Int, Int) -> Unit fn[A] Array::unsafe_blit_fixed(Self[A], Int, FixedArray[A], Int, Int) -> Unit fn[T] Array::unsafe_get(Self[T], Int) -> T From 0e08f15d238ca908b5d01fec4df6a33879927b1f Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Tue, 17 Jun 2025 20:58:32 +0800 Subject: [PATCH 16/35] Change the separator from string to string.view --- builtin/builtin.mbti | 1 - deque/deque.mbt | 5 +++-- deque/moon.pkg.json | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 83cf7a136..2a983280f 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -117,7 +117,6 @@ fn[T : Eq] Array::starts_with(Self[T], Self[T]) -> Bool fn[T : Eq] Array::strip_prefix(Self[T], Self[T]) -> Self[T]? fn[T : Eq] Array::strip_suffix(Self[T], Self[T]) -> Self[T]? fn[T] Array::swap(Self[T], Int, Int) -> Unit -fn[A] Array::truncate(Self[A], Int) -> Unit fn[A] Array::unsafe_blit(Self[A], Int, Self[A], Int, Int) -> Unit fn[A] Array::unsafe_blit_fixed(Self[A], Int, FixedArray[A], Int, Int) -> Unit fn[T] Array::unsafe_get(Self[T], Int) -> T diff --git a/deque/deque.mbt b/deque/deque.mbt index 55c8d8125..813d2e907 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1323,8 +1323,9 @@ pub fn[A] to_array(self : T[A]) -> Array[A] { /// inspect(s2, content="a,b,c") /// } /// ``` -pub fn T::join(self : T[String], separator : String) -> String { - self.iter().join(separator) +pub fn T::join(self : T[String], separator : @string.View) -> String { + let str = separator.to_string() + self.iter().join(str) } ///| diff --git a/deque/moon.pkg.json b/deque/moon.pkg.json index af0404932..a7272b4dd 100644 --- a/deque/moon.pkg.json +++ b/deque/moon.pkg.json @@ -2,7 +2,8 @@ "import": [ "moonbitlang/core/builtin", "moonbitlang/core/json", - "moonbitlang/core/array" + "moonbitlang/core/array", + "moonbitlang/core/string" ], "targets": { "panic_test.mbt": ["not", "native", "llvm"] From e201873d1cd1a979634e443c5d2aa37797a8703b Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 18 Jun 2025 10:58:39 +0800 Subject: [PATCH 17/35] add UninitializedArray::blit and Change the implementation of T::drain --- builtin/uninitialized_array.mbt | 47 +++++++++++++++++++++++++++++++++ deque/deque.mbt | 25 +++++++++--------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/builtin/uninitialized_array.mbt b/builtin/uninitialized_array.mbt index f385ca50e..f6a7ea05f 100644 --- a/builtin/uninitialized_array.mbt +++ b/builtin/uninitialized_array.mbt @@ -107,6 +107,53 @@ fn[T] UninitializedArray::unsafe_blit( FixedArray::unsafe_blit(dst._, dst_offset, src._, src_offset, len) } +///| +/// Copies a range of elements from one `UninitializedArray` to another, ensuring the destination array has enough space. +/// +/// If the destination array is not large enough to hold the copied elements at the specified offset, a new larger array is created and returned. +/// +/// Parameters: +/// +/// * `self` : The source array (not modified). +/// * `dst` : The destination array. May be modified in-place or replaced by a new array. +/// * `len` : Number of elements to copy. +/// * `src_offset` : Start index in the source array (default: 0). +/// * `dst_offset` : Start index in the destination array (default: 0). +/// +/// Returns: +/// A new array if reallocation was necessary, otherwise the original `dst`. +/// +/// Important: +/// - Requires: `len >= 0` +/// - Requires: `src_offset >= 0` +/// - Requires: `dst_offset >= 0` +/// - Requires: `src_offset + len <= self.length()` +/// - Ensures: `dst_offset + len <= dst.length()` after call (either by expanding `dst` or using a new array) +/// - Does not initialize or drop values; assumes caller handles memory safety. +/// +pub fn[A] UninitializedArray::blit( + self : UninitializedArray[A], + dst : UninitializedArray[A], + len~ : Int, + src_offset~ : Int = 0, + dst_offset~ : Int = 0 +) -> UninitializedArray[A] { + guard len >= 0 && + dst_offset >= 0 && + src_offset >= 0 && + dst_offset <= dst.length() && + src_offset + len <= self.length() + if dst_offset + len > dst.length() { + let new_dst = UninitializedArray::make(dst_offset + len) + UninitializedArray::unsafe_blit(new_dst, 0, dst, 0, dst.length()) + UninitializedArray::unsafe_blit(new_dst, dst_offset, self, src_offset, len) + new_dst + } else{ + UninitializedArray::unsafe_blit(dst, dst_offset, self, src_offset, len) + dst + } +} + ///| test "op_as_view with valid_range" { let arr : UninitializedArray[Int] = UninitializedArray::make(5) diff --git a/deque/deque.mbt b/deque/deque.mbt index 813d2e907..da48bbbf6 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1354,20 +1354,19 @@ pub fn T::join(self : T[String], separator : @string.View) -> String { /// ``` pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end - let dq = new(capacity=(end - begin)) - let length = self.length() - for i = 0; i < length; i = i + 1 { - match self.pop_front() { - Some(pop) => - if i > begin - 1 && i < end { - dq.push_back(pop) - } else { - self.push_back(pop) - } - None => () - } + let long = end - begin + let dq = new(capacity=long) + dq.buf = self.buf.blit(dq.buf, len = long, src_offset = begin, dst_offset = 0) + ignore(self.buf.blit(self.buf, len = self.length() - end, src_offset = end, dst_offset = begin)) + self.tail = self.length() - end + self.len = self.length() - long + let deq1 = T::{ + buf: dq.buf, + len: long, + head: 0, + tail: long - 1, } - dq + deq1 } ///| From 66146875b29dad0a9bb47e40e396adbda3aa3d23 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 18 Jun 2025 11:37:57 +0800 Subject: [PATCH 18/35] Change the implementation of T::flatten use blit --- deque/deque.mbt | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index da48bbbf6..b34d0f11c 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1394,19 +1394,23 @@ pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { /// } /// ``` pub fn[A] T::flatten(self : T[T[A]]) -> T[A] { - let deque = self[0].copy() - let len = self.length() - let mut selflen = 0 - for i = 1; i < len; i = i + 1 { - selflen = self[i].length() - for j = 0; j < selflen; j = j + 1 { - match self[i].pop_front() { - Some(pop) => deque.push_back(pop) - None => () - } - } + let mut len = 0 + for i in self { + len += i.length() + } + let dq = new(capacity=len) + let mut i = 0 + for t in self { + dq.buf=t.buf.blit(dq.buf, len=t.length(), dst_offset=i, src_offset=0) + i += t.length() } - deque + let deq = T::{ + buf: dq.buf, + len: len, + head: 0, + tail: len - 1, + } + deq } ///| From 79851e7ae67c9280d150f7ba265581072b0c7337 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 18 Jun 2025 11:55:10 +0800 Subject: [PATCH 19/35] format code --- array/array.mbti | 1 - builtin/builtin.mbti | 2 ++ deque/deque.mbti | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/array/array.mbti b/array/array.mbti index 27b92ebaf..f9b8372ee 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -86,7 +86,6 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit -fn[A] Array::truncate(Self[A], Int) -> Unit fn[T1, T2] Array::unzip(Self[(T1, T2)]) -> (Self[T1], Self[T2]) fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 2a983280f..dc0a63087 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -117,6 +117,7 @@ fn[T : Eq] Array::starts_with(Self[T], Self[T]) -> Bool fn[T : Eq] Array::strip_prefix(Self[T], Self[T]) -> Self[T]? fn[T : Eq] Array::strip_suffix(Self[T], Self[T]) -> Self[T]? fn[T] Array::swap(Self[T], Int, Int) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[A] Array::unsafe_blit(Self[A], Int, Self[A], Int, Int) -> Unit fn[A] Array::unsafe_blit_fixed(Self[A], Int, FixedArray[A], Int, Int) -> Unit fn[T] Array::unsafe_get(Self[T], Int) -> T @@ -298,6 +299,7 @@ impl Logger for StringBuilder impl Show for StringBuilder type UninitializedArray[T] +fn[A] UninitializedArray::blit(Self[A], Self[A], len~ : Int, src_offset~ : Int = .., dst_offset~ : Int = ..) -> Self[A] fn[A] UninitializedArray::length(Self[A]) -> Int fn[T] UninitializedArray::make(Int) -> Self[T] fn[T] UninitializedArray::op_as_view(Self[T], start~ : Int = .., end? : Int) -> ArrayView[T] diff --git a/deque/deque.mbti b/deque/deque.mbti index 8ad92a0f6..4d7f75f31 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -2,6 +2,7 @@ package "moonbitlang/core/deque" import( "moonbitlang/core/json" + "moonbitlang/core/string" ) // Values @@ -106,7 +107,7 @@ fn[A] T::front(Self[A]) -> A? fn[A] T::is_empty(Self[A]) -> Bool fn[A] T::iter(Self[A]) -> Iter[A] fn[A] T::iter2(Self[A]) -> Iter2[Int, A] -fn T::join(Self[String], String) -> String +fn T::join(Self[String], @string.StringView) -> String fn[A] T::length(Self[A]) -> Int fn[A, U] T::map(Self[A], (A) -> U) -> Self[U] fn[A, U] T::mapi(Self[A], (Int, A) -> U) -> Self[U] From cfe6885e03894ae696cb983536c58f7c453dd33e Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 18 Jun 2025 20:31:33 +0800 Subject: [PATCH 20/35] format code --- array/array.mbt | 1 - deque/deque.mbt | 6 ------ 2 files changed, 7 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index 538118875..2bded37ac 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -310,7 +310,6 @@ pub fn[A, B] zip_to_iter2(self : Array[A], other : Array[B]) -> Iter2[A, B] { }) } - ///| pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbitrary( size, diff --git a/deque/deque.mbt b/deque/deque.mbt index a08c7d1c9..af0f34932 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1235,14 +1235,12 @@ pub fn[A] to_array(self : T[A]) -> Array[A] { /// Example: /// /// ```moonbit -/// test "join" { /// let deque = @deque.of(["a","b","c"]) /// let s1 = deque.join("") /// inspect(s1, content="abc") /// /// let s2 = deque.join(",") /// inspect(s2, content="a,b,c") -/// } /// ``` pub fn T::join(self : T[String], separator : @string.View) -> String { let str = separator.to_string() @@ -1266,12 +1264,10 @@ pub fn T::join(self : T[String], separator : @string.View) -> String { /// Example: /// /// ```moonbit -/// test "drain" { /// let deque = @deque.of([1,2,3,4,5,6,7,8,9]) /// let deque_test = deque.drain(2, 6) /// inspect(deque_test, content="@deque.of([3, 4, 5, 6])") /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") -/// } /// ``` pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end @@ -1308,11 +1304,9 @@ pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { /// Example: /// /// ```moonbit -/// test "flatten" { /// let deque = @deque.of([@deque.of([1,2,3]),@deque.of([4,5,6]),@deque.of([7,8])]) /// let deque_test = deque.flatten() /// inspect(deque_test, content="@deque.of([1, 2, 3, 4, 5, 6, 7, 8])") -/// } /// ``` pub fn[A] T::flatten(self : T[T[A]]) -> T[A] { let mut len = 0 From b7f467bbc80d0b2b3455bd2801877d23e54ee3ce Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Thu, 19 Jun 2025 11:35:13 +0800 Subject: [PATCH 21/35] Move `Array::truncate` from arraycore_nonjs.mbt to array.mbt --- array/array.mbt | 32 ++++++++++++++++++++++++++++++++ builtin/arraycore_nonjs.mbt | 4 ++++ 2 files changed, 36 insertions(+) diff --git a/array/array.mbt b/array/array.mbt index 2bded37ac..2615128dc 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -329,3 +329,35 @@ pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbi pub fn join(self : Array[String], separator : @string.View) -> String { self[:].join(separator) } + +///| +/// Truncates the array in-place to the specified length. +/// +/// If `len` is greater than or equal to the current array length, +/// the function does nothing. If `len` is 0, the array is cleared. +/// Otherwise, removes elements from the end until the array reaches the given length. +/// +/// Parameters: +/// +/// * `self` : The target array (modified in-place). +/// * `len` : The new desired length (must be non-negative). +/// +/// Important: +/// - If `len` is negative, the function does nothing. +/// - If `len` exceeds current length, the array remains unchanged. +/// +/// Example: +/// +/// ```moonbit +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") +/// ``` +pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { + guard len >= 0 && len < self.length() else { return } + if len == 0 { + self.clear() + return + } + self.truncate_to_length(len) +} \ No newline at end of file diff --git a/builtin/arraycore_nonjs.mbt b/builtin/arraycore_nonjs.mbt index c4fb6c69d..ecca0fb8c 100644 --- a/builtin/arraycore_nonjs.mbt +++ b/builtin/arraycore_nonjs.mbt @@ -110,6 +110,10 @@ fn[T] Array::unsafe_truncate_to_length(self : Array[T], new_len : Int) -> Unit { self.len = new_len } +pub fn[T] Array::truncate_to_length(self : Array[T], len : Int) -> Unit { + self.unsafe_truncate_to_length(len) +} + ///| test "unsafe_truncate_to_length" { let arr = [1, 2, 3, 4, 5] From c48a266dec07a2d825d9fd2a5f81422fcf95f058 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Thu, 19 Jun 2025 11:43:47 +0800 Subject: [PATCH 22/35] format code --- array/array.mbti | 1 + builtin/arraycore_nonjs.mbt | 34 ---------------------------------- builtin/builtin.mbti | 2 +- 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/array/array.mbti b/array/array.mbti index 2537b23c6..2b21beb4d 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -62,6 +62,7 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[T1, T2] Array::unzip(Self[(T1, T2)]) -> (Self[T1], Self[T2]) fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] diff --git a/builtin/arraycore_nonjs.mbt b/builtin/arraycore_nonjs.mbt index ecca0fb8c..fd651a7d7 100644 --- a/builtin/arraycore_nonjs.mbt +++ b/builtin/arraycore_nonjs.mbt @@ -416,37 +416,3 @@ fn[T] Array::unsafe_grow_to_length(self : Array[T], new_len : Int) -> Unit { self.len = new_len self.buf = new_buf } - -///| -/// Truncates the array in-place to the specified length. -/// -/// If `len` is greater than or equal to the current array length, -/// the function does nothing. If `len` is 0, the array is cleared. -/// Otherwise, removes elements from the end until the array reaches the given length. -/// -/// Parameters: -/// -/// * `self` : The target array (modified in-place). -/// * `len` : The new desired length (must be non-negative). -/// -/// Important: -/// - If `len` is negative, the function does nothing. -/// - If `len` exceeds current length, the array remains unchanged. -/// -/// Example: -/// -/// ```moonbit -/// test "truncate" { -/// let arr = [1, 2, 3, 4, 5] -/// arr.truncate(3) -/// inspect(arr, content="[1, 2, 3]") -/// } -/// ``` -pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { - guard len >= 0 && len < self.length() else { return } - if len == 0 { - self.clear() - return - } - self.unsafe_truncate_to_length(len) -} \ No newline at end of file diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 5b2df4e75..74e0ebfb2 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -118,7 +118,7 @@ fn[T : Eq] Array::starts_with(Self[T], Self[T]) -> Bool fn[T : Eq] Array::strip_prefix(Self[T], Self[T]) -> Self[T]? fn[T : Eq] Array::strip_suffix(Self[T], Self[T]) -> Self[T]? fn[T] Array::swap(Self[T], Int, Int) -> Unit -fn[A] Array::truncate(Self[A], Int) -> Unit +fn[T] Array::truncate_to_length(Self[A], Int) -> Unit fn[A] Array::unsafe_blit(Self[A], Int, Self[A], Int, Int) -> Unit fn[A] Array::unsafe_blit_fixed(Self[A], Int, FixedArray[A], Int, Int) -> Unit fn[T] Array::unsafe_get(Self[T], Int) -> T From 0cfca9a092b35917e7190cf2f6db3a75d30695ce Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Thu, 19 Jun 2025 12:19:21 +0800 Subject: [PATCH 23/35] Move Array::truncate --- array/array.mbt | 32 -------------------------------- array/array.mbti | 1 - builtin/array.mbt | 34 ++++++++++++++++++++++++++++++++++ builtin/arraycore_nonjs.mbt | 4 ---- builtin/builtin.mbti | 2 +- 5 files changed, 35 insertions(+), 38 deletions(-) diff --git a/array/array.mbt b/array/array.mbt index 2615128dc..2bded37ac 100644 --- a/array/array.mbt +++ b/array/array.mbt @@ -329,35 +329,3 @@ pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbi pub fn join(self : Array[String], separator : @string.View) -> String { self[:].join(separator) } - -///| -/// Truncates the array in-place to the specified length. -/// -/// If `len` is greater than or equal to the current array length, -/// the function does nothing. If `len` is 0, the array is cleared. -/// Otherwise, removes elements from the end until the array reaches the given length. -/// -/// Parameters: -/// -/// * `self` : The target array (modified in-place). -/// * `len` : The new desired length (must be non-negative). -/// -/// Important: -/// - If `len` is negative, the function does nothing. -/// - If `len` exceeds current length, the array remains unchanged. -/// -/// Example: -/// -/// ```moonbit -/// let arr = [1, 2, 3, 4, 5] -/// arr.truncate(3) -/// inspect(arr, content="[1, 2, 3]") -/// ``` -pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { - guard len >= 0 && len < self.length() else { return } - if len == 0 { - self.clear() - return - } - self.truncate_to_length(len) -} \ No newline at end of file diff --git a/array/array.mbti b/array/array.mbti index 2b21beb4d..2537b23c6 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -62,7 +62,6 @@ fn[T] Array::shuffle_in_place(Self[T], rand~ : (Int) -> Int) -> Unit fn[T : Compare] Array::sort(Self[T]) -> Unit fn[T] Array::sort_by(Self[T], (T, T) -> Int) -> Unit fn[T, K : Compare] Array::sort_by_key(Self[T], (T) -> K) -> Unit -fn[A] Array::truncate(Self[A], Int) -> Unit fn[T1, T2] Array::unzip(Self[(T1, T2)]) -> (Self[T1], Self[T2]) fn[A, B] Array::zip(Self[A], Self[B]) -> Self[(A, B)] fn[A, B] Array::zip_to_iter2(Self[A], Self[B]) -> Iter2[A, B] diff --git a/builtin/array.mbt b/builtin/array.mbt index 9574f5503..82f593b78 100644 --- a/builtin/array.mbt +++ b/builtin/array.mbt @@ -1759,3 +1759,37 @@ pub impl[T] Default for Array[T] with default() { pub fn[A] Array::unsafe_pop_back(self : Array[A]) -> Unit { self.unsafe_pop() |> ignore } + +///| +/// Truncates the array in-place to the specified length. +/// +/// If `len` is greater than or equal to the current array length, +/// the function does nothing. If `len` is 0, the array is cleared. +/// Otherwise, removes elements from the end until the array reaches the given length. +/// +/// Parameters: +/// +/// * `self` : The target array (modified in-place). +/// * `len` : The new desired length (must be non-negative). +/// +/// Important: +/// - If `len` is negative, the function does nothing. +/// - If `len` exceeds current length, the array remains unchanged. +/// +/// Example: +/// +/// ```moonbit +/// test "truncate" { +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") +/// } +/// ``` +pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { + guard len >= 0 && len < self.length() else { return } + if len == 0 { + self.clear() + return + } + self.unsafe_truncate_to_length(len) +} \ No newline at end of file diff --git a/builtin/arraycore_nonjs.mbt b/builtin/arraycore_nonjs.mbt index fd651a7d7..d7e8f5e47 100644 --- a/builtin/arraycore_nonjs.mbt +++ b/builtin/arraycore_nonjs.mbt @@ -110,10 +110,6 @@ fn[T] Array::unsafe_truncate_to_length(self : Array[T], new_len : Int) -> Unit { self.len = new_len } -pub fn[T] Array::truncate_to_length(self : Array[T], len : Int) -> Unit { - self.unsafe_truncate_to_length(len) -} - ///| test "unsafe_truncate_to_length" { let arr = [1, 2, 3, 4, 5] diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 74e0ebfb2..5b2df4e75 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -118,7 +118,7 @@ fn[T : Eq] Array::starts_with(Self[T], Self[T]) -> Bool fn[T : Eq] Array::strip_prefix(Self[T], Self[T]) -> Self[T]? fn[T : Eq] Array::strip_suffix(Self[T], Self[T]) -> Self[T]? fn[T] Array::swap(Self[T], Int, Int) -> Unit -fn[T] Array::truncate_to_length(Self[A], Int) -> Unit +fn[A] Array::truncate(Self[A], Int) -> Unit fn[A] Array::unsafe_blit(Self[A], Int, Self[A], Int, Int) -> Unit fn[A] Array::unsafe_blit_fixed(Self[A], Int, FixedArray[A], Int, Int) -> Unit fn[T] Array::unsafe_get(Self[T], Int) -> T From e72883973df97e34ce44da46474adf0a50c94645 Mon Sep 17 00:00:00 2001 From: zihang Date: Thu, 19 Jun 2025 15:03:51 +0800 Subject: [PATCH 24/35] chore: fmt & fix warning --- builtin/array.mbt | 10 ++++------ builtin/uninitialized_array.mbt | 2 +- deque/deque.mbt | 27 ++++++++++++--------------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/builtin/array.mbt b/builtin/array.mbt index 82f593b78..b501abbfd 100644 --- a/builtin/array.mbt +++ b/builtin/array.mbt @@ -1779,11 +1779,9 @@ pub fn[A] Array::unsafe_pop_back(self : Array[A]) -> Unit { /// Example: /// /// ```moonbit -/// test "truncate" { -/// let arr = [1, 2, 3, 4, 5] -/// arr.truncate(3) -/// inspect(arr, content="[1, 2, 3]") -/// } +/// let arr = [1, 2, 3, 4, 5] +/// arr.truncate(3) +/// inspect(arr, content="[1, 2, 3]") /// ``` pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { guard len >= 0 && len < self.length() else { return } @@ -1792,4 +1790,4 @@ pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { return } self.unsafe_truncate_to_length(len) -} \ No newline at end of file +} diff --git a/builtin/uninitialized_array.mbt b/builtin/uninitialized_array.mbt index 1376792a2..5fc8d11f7 100644 --- a/builtin/uninitialized_array.mbt +++ b/builtin/uninitialized_array.mbt @@ -149,7 +149,7 @@ pub fn[A] UninitializedArray::blit( UninitializedArray::unsafe_blit(new_dst, 0, dst, 0, dst.length()) UninitializedArray::unsafe_blit(new_dst, dst_offset, self, src_offset, len) new_dst - } else{ + } else { UninitializedArray::unsafe_blit(dst, dst_offset, self, src_offset, len) dst } diff --git a/deque/deque.mbt b/deque/deque.mbt index 1851aafc9..620840697 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1290,16 +1290,18 @@ pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end let long = end - begin let dq = new(capacity=long) - dq.buf = self.buf.blit(dq.buf, len = long, src_offset = begin, dst_offset = 0) - ignore(self.buf.blit(self.buf, len = self.length() - end, src_offset = end, dst_offset = begin)) + dq.buf = self.buf.blit(dq.buf, len=long, src_offset=begin, dst_offset=0) + ignore( + self.buf.blit( + self.buf, + len=self.length() - end, + src_offset=end, + dst_offset=begin, + ), + ) self.tail = self.length() - end self.len = self.length() - long - let deq1 = T::{ - buf: dq.buf, - len: long, - head: 0, - tail: long - 1, - } + let deq1 = T::{ buf: dq.buf, len: long, head: 0, tail: long - 1 } deq1 } @@ -1333,15 +1335,10 @@ pub fn[A] T::flatten(self : T[T[A]]) -> T[A] { let dq = new(capacity=len) let mut i = 0 for t in self { - dq.buf=t.buf.blit(dq.buf, len=t.length(), dst_offset=i, src_offset=0) + dq.buf = t.buf.blit(dq.buf, len=t.length(), dst_offset=i, src_offset=0) i += t.length() } - let deq = T::{ - buf: dq.buf, - len: len, - head: 0, - tail: len - 1, - } + let deq = T::{ buf: dq.buf, len, head: 0, tail: len - 1 } deq } From bb0815bc6fd6d3633790b0092c0b34e28bf3a807 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Fri, 20 Jun 2025 17:45:17 +0800 Subject: [PATCH 25/35] Update deque/deque.mbt Co-authored-by: Zihang Ye --- deque/deque.mbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index 620840697..5c3ebb87b 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1286,7 +1286,7 @@ pub fn T::join(self : T[String], separator : @string.View) -> String { /// inspect(deque_test, content="@deque.of([3, 4, 5, 6])") /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// ``` -pub fn[A] T::drain(self : T[A], begin : Int, end : Int) -> T[A] { +pub fn[A] T::drain(self : T[A], start~ : Int, len~ : Int) -> T[A] { guard begin >= 0 && end <= self.length() && begin <= end let long = end - begin let dq = new(capacity=long) From b4313a5713971aafc4b9d2c58cbce2ce18ecc5cb Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Tue, 24 Jun 2025 15:00:22 +0800 Subject: [PATCH 26/35] Change the implementation of T::drain --- deque/deque.mbt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index 5c3ebb87b..14d21f767 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1287,21 +1287,21 @@ pub fn T::join(self : T[String], separator : @string.View) -> String { /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// ``` pub fn[A] T::drain(self : T[A], start~ : Int, len~ : Int) -> T[A] { - guard begin >= 0 && end <= self.length() && begin <= end - let long = end - begin - let dq = new(capacity=long) - dq.buf = self.buf.blit(dq.buf, len=long, src_offset=begin, dst_offset=0) + let end = start + len + guard start >= 0 && end <= self.length() + let dq = new(capacity=len) + dq.buf = self.buf.blit(dq.buf, len=len, src_offset=start, dst_offset=0) ignore( self.buf.blit( self.buf, len=self.length() - end, src_offset=end, - dst_offset=begin, + dst_offset=start, ), ) self.tail = self.length() - end - self.len = self.length() - long - let deq1 = T::{ buf: dq.buf, len: long, head: 0, tail: long - 1 } + self.len = self.length() - len + let deq1 = T::{ buf: dq.buf, len: len, head: 0, tail: len - 1 } deq1 } From 08d9778afcdd228baa4cb56bd11e2abc2a1a4d63 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Tue, 24 Jun 2025 15:05:23 +0800 Subject: [PATCH 27/35] Format code --- deque/deque.mbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index 14d21f767..b3fce9058 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1282,7 +1282,7 @@ pub fn T::join(self : T[String], separator : @string.View) -> String { /// /// ```moonbit /// let deque = @deque.of([1,2,3,4,5,6,7,8,9]) -/// let deque_test = deque.drain(2, 6) +/// let deque_test = deque.drain(start=2, len=4) /// inspect(deque_test, content="@deque.of([3, 4, 5, 6])") /// inspect(deque, content="@deque.of([1, 2, 7, 8, 9])") /// ``` From 851c896871a7b60b0a12c28736f831b05b1da343 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Tue, 24 Jun 2025 16:58:01 +0800 Subject: [PATCH 28/35] Format code --- deque/deque.mbti | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deque/deque.mbti b/deque/deque.mbti index 6e9ea337d..68c2d0558 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -22,7 +22,7 @@ fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool fn[A] T::copy(Self[A]) -> Self[A] -fn[A] T::drain(Self[A], Int, Int) -> Self[A] +fn[A] T::drain(Self[A], start~ : Int, len~ : Int) -> Self[A] fn[A] T::each(Self[A], (A) -> Unit) -> Unit fn[A] T::eachi(Self[A], (Int, A) -> Unit) -> Unit #deprecated From a798caff9e9d64923ed67c9fbccfe66cd6dbfd7a Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Tue, 24 Jun 2025 17:10:32 +0800 Subject: [PATCH 29/35] Format code --- deque/deque.mbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index b3fce9058..fdffac295 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1290,7 +1290,7 @@ pub fn[A] T::drain(self : T[A], start~ : Int, len~ : Int) -> T[A] { let end = start + len guard start >= 0 && end <= self.length() let dq = new(capacity=len) - dq.buf = self.buf.blit(dq.buf, len=len, src_offset=start, dst_offset=0) + dq.buf = self.buf.blit(dq.buf, len~, src_offset=start, dst_offset=0) ignore( self.buf.blit( self.buf, @@ -1301,7 +1301,7 @@ pub fn[A] T::drain(self : T[A], start~ : Int, len~ : Int) -> T[A] { ) self.tail = self.length() - end self.len = self.length() - len - let deq1 = T::{ buf: dq.buf, len: len, head: 0, tail: len - 1 } + let deq1 = T::{ buf: dq.buf, len, head: 0, tail: len - 1 } deq1 } From a2a33707ad8261e96674a8d8169cee2e2714fcdf Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 2 Jul 2025 17:58:58 +0800 Subject: [PATCH 30/35] feat(deque): Add append method --- deque/deque.mbt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/deque/deque.mbt b/deque/deque.mbt index 30eb8568d..1ebc60f1a 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1558,3 +1558,34 @@ pub fn[A] get(self : T[A], index : Int) -> A? { pub fn[A : Compare] binary_search(self : T[A], value : A) -> Result[Int, Int] { self.binary_search_by(x => x.compare(value)) } + +///| +/// Appends all elements from one deque to the end of another deque. +/// +/// Parameters: +/// +/// * `self` : The deque to which elements will be appended. +/// * `other` : The deque whose elements will be appended to `self`. +/// +/// Returns nothing (`Unit`). Modifies `self` in place by pushing +/// +/// Example: +/// +/// ```moonbit +/// test "append" { +/// let deque1 = @deque.of([1, 2, 3]) +/// let deque2 = @deque.of([4, 5, 6]) +/// deque1.append(deque2) +/// inspect(deque1, content="@deque.of([1, 2, 3, 4, 5, 6])") +/// } +/// ``` +pub fn[A] T::append(self : T[A], other : T[A]) -> Unit { + let dst_len = self.length() + let src_len = other.length() + let new_dst = UninitializedArray::make(dst_len + src_len) + UninitializedArray::unsafe_blit(new_dst, 0, self.buf, 0, dst_len) + UninitializedArray::unsafe_blit(new_dst, dst_len, other.buf, 0, src_len) + self.buf = new_dst + self.len = dst_len + src_len + self.tail = self.tail + src_len +} \ No newline at end of file From 53d8fdb8475007c87f8ff886828c262c51942888 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 2 Jul 2025 18:10:34 +0800 Subject: [PATCH 31/35] Delet UninitializedArray::blit --- builtin/builtin.mbti | 1 - builtin/uninitialized_array.mbt | 47 --------------------------------- 2 files changed, 48 deletions(-) diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index 19bc2f7de..3ae35e46c 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -303,7 +303,6 @@ impl Logger for StringBuilder impl Show for StringBuilder type UninitializedArray[T] -fn[A] UninitializedArray::blit(Self[A], Self[A], len~ : Int, src_offset~ : Int = .., dst_offset~ : Int = ..) -> Self[A] fn[A] UninitializedArray::length(Self[A]) -> Int fn[T] UninitializedArray::make(Int) -> Self[T] fn[T] UninitializedArray::op_as_view(Self[T], start~ : Int = .., end? : Int) -> ArrayView[T] diff --git a/builtin/uninitialized_array.mbt b/builtin/uninitialized_array.mbt index a9a428da9..64218afc1 100644 --- a/builtin/uninitialized_array.mbt +++ b/builtin/uninitialized_array.mbt @@ -109,53 +109,6 @@ pub fn[T] UninitializedArray::unsafe_blit( FixedArray::unsafe_blit(dst.inner(), dst_offset, src.inner(), src_offset, len) } -///| -/// Copies a range of elements from one `UninitializedArray` to another, ensuring the destination array has enough space. -/// -/// If the destination array is not large enough to hold the copied elements at the specified offset, a new larger array is created and returned. -/// -/// Parameters: -/// -/// * `self` : The source array (not modified). -/// * `dst` : The destination array. May be modified in-place or replaced by a new array. -/// * `len` : Number of elements to copy. -/// * `src_offset` : Start index in the source array (default: 0). -/// * `dst_offset` : Start index in the destination array (default: 0). -/// -/// Returns: -/// A new array if reallocation was necessary, otherwise the original `dst`. -/// -/// Important: -/// - Requires: `len >= 0` -/// - Requires: `src_offset >= 0` -/// - Requires: `dst_offset >= 0` -/// - Requires: `src_offset + len <= self.length()` -/// - Ensures: `dst_offset + len <= dst.length()` after call (either by expanding `dst` or using a new array) -/// - Does not initialize or drop values; assumes caller handles memory safety. -/// -pub fn[A] UninitializedArray::blit( - self : UninitializedArray[A], - dst : UninitializedArray[A], - len~ : Int, - src_offset~ : Int = 0, - dst_offset~ : Int = 0 -) -> UninitializedArray[A] { - guard len >= 0 && - dst_offset >= 0 && - src_offset >= 0 && - dst_offset <= dst.length() && - src_offset + len <= self.length() - if dst_offset + len > dst.length() { - let new_dst = UninitializedArray::make(dst_offset + len) - UninitializedArray::unsafe_blit(new_dst, 0, dst, 0, dst.length()) - UninitializedArray::unsafe_blit(new_dst, dst_offset, self, src_offset, len) - new_dst - } else { - UninitializedArray::unsafe_blit(dst, dst_offset, self, src_offset, len) - dst - } -} - ///| test "op_as_view with valid_range" { let arr : UninitializedArray[Int] = UninitializedArray::make(5) From 48164ea17ea5425d1326dbec1683a468e1a1062d Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Wed, 2 Jul 2025 18:56:56 +0800 Subject: [PATCH 32/35] feat(deque): Add blit_to method --- deque/deque.mbt | 58 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index e86f37194..b74305ba7 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1572,12 +1572,10 @@ pub fn[A : Compare] binary_search(self : T[A], value : A) -> Result[Int, Int] { /// Example: /// /// ```moonbit -/// test "append" { -/// let deque1 = @deque.of([1, 2, 3]) -/// let deque2 = @deque.of([4, 5, 6]) -/// deque1.append(deque2) -/// inspect(deque1, content="@deque.of([1, 2, 3, 4, 5, 6])") -/// } +/// let deque1 = @deque.of([1, 2, 3]) +/// let deque2 = @deque.of([4, 5, 6]) +/// deque1.append(deque2) +/// inspect(deque1, content="@deque.of([1, 2, 3, 4, 5, 6])") /// ``` pub fn[A] T::append(self : T[A], other : T[A]) -> Unit { let dst_len = self.length() @@ -1588,4 +1586,52 @@ pub fn[A] T::append(self : T[A], other : T[A]) -> Unit { self.buf = new_dst self.len = dst_len + src_len self.tail = self.tail + src_len +} + +///| +/// Copies a segment of elements from the source deque into a destination deque. +/// +/// Copies `len` elements starting from `src_offset` in the source deque (`self`) +/// into the destination deque (`dst`) starting at `dst_offset`. Modifies the destination deque in place. +/// +/// * If `dst_offset + len` exceeds the destination deque's current length, +/// the destination is automatically **resized** to accommodate the new elements. +/// * If the destination has sufficient capacity, elements are overwritten in-place. +/// +/// +/// Parameters: +/// * `self` : Source deque (`T[A]`) to copy elements from. +/// * `dst` : Destination deque (`T[A]`) to copy elements into (modified in place). +/// * `len~` : Number of elements to copy (labeled argument). +/// * `src_offset~` : Starting index in source deque (default = 0). +/// * `dst_offset~` : Starting index in destination deque (default = 0). +/// +/// ```moonbit +/// let src = @deque.of([10, 20, 30, 40]) +/// let dst = @deque.of([1, 2, 3, 4]) +/// src.blit_to(dst, len=3, src_offset=1, dst_offset=3) +/// inspect(dst, content="@deque.of([1, 2, 3, 20, 30, 40])") +/// ``` +pub fn[A] T::blit_to( + self : T[A], + dst : T[A], + len~ : Int, + src_offset~ : Int = 0, + dst_offset~ : Int = 0 +) -> Unit { + guard len >= 0 && + dst_offset >= 0 && + src_offset >= 0 && + dst_offset <= dst.length() && + src_offset + len <= self.length() + if dst_offset + len > dst.length() { + let new_dst = UninitializedArray::make(dst_offset + len) + UninitializedArray::unsafe_blit(new_dst, 0, dst.buf, 0, dst.length()) + UninitializedArray::unsafe_blit(new_dst, dst_offset, self.buf, src_offset, len) + dst.buf = new_dst + dst.len = dst_offset + len + dst.tail = dst.len - 1 + } else { + UninitializedArray::unsafe_blit(dst.buf, dst_offset, self.buf, src_offset, len) + } } \ No newline at end of file From 944aad00c310d1d4f0ee8237c4479f7652b603f4 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 5 Jul 2025 20:59:01 +0800 Subject: [PATCH 33/35] Format code --- deque/deque.mbti | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deque/deque.mbti b/deque/deque.mbti index be0ecbeb2..9e1a1cb92 100644 --- a/deque/deque.mbti +++ b/deque/deque.mbti @@ -16,10 +16,12 @@ fn[A] of(FixedArray[A]) -> T[A] // Types and methods type T[A] +fn[A] T::append(Self[A], Self[A]) -> Unit fn[A] T::as_views(Self[A]) -> (ArrayView[A], ArrayView[A]) fn[A] T::back(Self[A]) -> A? fn[A : Compare] T::binary_search(Self[A], A) -> Result[Int, Int] fn[A] T::binary_search_by(Self[A], (A) -> Int) -> Result[Int, Int] +fn[A] T::blit_to(Self[A], Self[A], len~ : Int, src_offset~ : Int = .., dst_offset~ : Int = ..) -> Unit fn[A] T::capacity(Self[A]) -> Int fn[A] T::clear(Self[A]) -> Unit fn[A : Eq] T::contains(Self[A], A) -> Bool From af26bcc0ad8e2e9d4b9c95f636fde63dc09e2a5c Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sat, 5 Jul 2025 23:30:57 +0800 Subject: [PATCH 34/35] Format code --- deque/deque.mbt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index b74305ba7..459f8f88c 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1627,11 +1627,23 @@ pub fn[A] T::blit_to( if dst_offset + len > dst.length() { let new_dst = UninitializedArray::make(dst_offset + len) UninitializedArray::unsafe_blit(new_dst, 0, dst.buf, 0, dst.length()) - UninitializedArray::unsafe_blit(new_dst, dst_offset, self.buf, src_offset, len) + UninitializedArray::unsafe_blit( + new_dst, + dst_offset, + self.buf, + src_offset, + len, + ) dst.buf = new_dst dst.len = dst_offset + len dst.tail = dst.len - 1 } else { - UninitializedArray::unsafe_blit(dst.buf, dst_offset, self.buf, src_offset, len) + UninitializedArray::unsafe_blit( + dst.buf, + dst_offset, + self.buf, + src_offset, + len, + ) } } \ No newline at end of file From 6b75f81394a4d1ef07b3e24794f8af654c1031c6 Mon Sep 17 00:00:00 2001 From: ethereal-dream <1919172483@qq.com> Date: Sun, 6 Jul 2025 10:17:00 +0800 Subject: [PATCH 35/35] Format code --- deque/deque.mbt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/deque/deque.mbt b/deque/deque.mbt index 459f8f88c..ee0c4f934 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -1628,22 +1628,22 @@ pub fn[A] T::blit_to( let new_dst = UninitializedArray::make(dst_offset + len) UninitializedArray::unsafe_blit(new_dst, 0, dst.buf, 0, dst.length()) UninitializedArray::unsafe_blit( - new_dst, - dst_offset, - self.buf, - src_offset, - len, - ) + new_dst, + dst_offset, + self.buf, + src_offset, + len, + ) dst.buf = new_dst dst.len = dst_offset + len dst.tail = dst.len - 1 } else { - UninitializedArray::unsafe_blit( - dst.buf, - dst_offset, - self.buf, - src_offset, - len, - ) + UninitializedArray::unsafe_blit( + dst.buf, + dst_offset, + self.buf, + src_offset, + len, + ) } } \ No newline at end of file