From c073535b2e866ad83655388b76bd53301f1a74f6 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sat, 25 Jan 2025 10:00:44 +0800 Subject: [PATCH 1/8] add min and max value for int16 and uint16 --- int16/int16.mbt | 6 ++++++ int16/int16.mbti | 3 +++ uint16/uint16.mbt | 6 ++++++ uint16/uint16.mbti | 3 +++ 4 files changed, 18 insertions(+) diff --git a/int16/int16.mbt b/int16/int16.mbt index c1b491685..9183c3c9b 100644 --- a/int16/int16.mbt +++ b/int16/int16.mbt @@ -12,6 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +///| +pub let max_value : Int16 = 32767 + +///| +pub let min_value : Int16 = -32768 + ///| pub fn op_add(self : Int16, that : Int16) -> Int16 { (self.to_int() + that.to_int()).to_int16() diff --git a/int16/int16.mbti b/int16/int16.mbti index 0acc3b4bc..487434153 100644 --- a/int16/int16.mbti +++ b/int16/int16.mbti @@ -1,6 +1,9 @@ package moonbitlang/core/int16 // Values +let max_value : Int16 + +let min_value : Int16 // Types and methods impl Int16 { diff --git a/uint16/uint16.mbt b/uint16/uint16.mbt index 2467f2902..ed7a080c6 100644 --- a/uint16/uint16.mbt +++ b/uint16/uint16.mbt @@ -12,6 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +///| +pub let max_value : UInt16 = 65535 + +///| +pub let min_value : UInt16 = 0 + ///| pub fn op_add(self : UInt16, that : UInt16) -> UInt16 { (self.to_int() + that.to_int()).to_uint16() diff --git a/uint16/uint16.mbti b/uint16/uint16.mbti index 09351aecc..bca523ec4 100644 --- a/uint16/uint16.mbti +++ b/uint16/uint16.mbti @@ -1,6 +1,9 @@ package moonbitlang/core/uint16 // Values +let max_value : UInt16 + +let min_value : UInt16 // Types and methods impl UInt16 { From 91f138eea956b20340c768a73929bedd90a555b1 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Sun, 26 Jan 2025 22:15:46 +0800 Subject: [PATCH 2/8] test: enhance string view test coverage for surrogate pairs --- string/view_test.mbt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/string/view_test.mbt b/string/view_test.mbt index 017e2c4a8..e3a0c040c 100644 --- a/string/view_test.mbt +++ b/string/view_test.mbt @@ -32,6 +32,36 @@ test "index_at with surrogate pairs" { inspect!(offset, content="StringIndex(6)") let offset = str.index_at(4) inspect!(offset, content="None") + inspect!( + str[1:2], + content= + #|"🤣" + , + ) + inspect!( + str[1:3], + content= + #|"🤣🤣" + , + ) + inspect!( + str[1:-1], + content= + #|"🤣" + , + ) + inspect!( + str[1:-2], + content= + #|"" + , + ) + inspect!( + str[:-1], + content= + #|"🤣🤣" + , + ) } test "stringview basic" { From 6258a4b1194e446d1520e47c682de00d562149ee Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Sun, 26 Jan 2025 22:30:48 +0800 Subject: [PATCH 3/8] test: add test for tail-recursive map implementation using DPS --- immut/list/dps_test.mbt | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 immut/list/dps_test.mbt diff --git a/immut/list/dps_test.mbt b/immut/list/dps_test.mbt new file mode 100644 index 000000000..ba5da498e --- /dev/null +++ b/immut/list/dps_test.mbt @@ -0,0 +1,59 @@ +// 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. + +///| +pub enum L { + Nil + Cons(Int, mut tail~ : L) +} derive(Eq, Show) + +///| +/// tail recursive map using dps +pub fn map(self : L, f : (Int) -> Int) -> L { + match self { + Nil => Nil + Cons(head, tail~) => { + let cell = Cons(f(head), tail=Nil) + map_dps(f, tail, cell) + cell + } + } +} + +///| +fn map_dps(f : (Int) -> Int, lst : L, dest : L) -> Unit { + loop lst, dest { + Nil, Cons(_, ..) as c => c.tail = Nil + // c.tail = lst + // this is a common error + Cons(head, tail~), Cons(_, ..) as c => { + let cell = Cons(f(head), tail=Nil) + c.tail = cell + continue tail, cell + } + _, Nil => abort("map_dps: dest is Nil") + } +} + +test "map" { + let lstL : L = Cons(1, tail=Cons(2, tail=Cons(3, tail=Cons(4, tail=Cons(5, tail=Nil))))) + let lst : L = map(lstL, fn { x => x * 2 }) + inspect!( + lst, + content= + "Cons(2, tail=Cons(4, tail=Cons(6, tail=Cons(8, tail=Cons(10, tail=Nil)))))" + , + ) + +} From 5bebf820621c2dc35550519ac66c9798fd949ca2 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Sun, 26 Jan 2025 22:38:21 +0800 Subject: [PATCH 4/8] fmt --- immut/list/dps_test.mbt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/immut/list/dps_test.mbt b/immut/list/dps_test.mbt index ba5da498e..8514f8e59 100644 --- a/immut/list/dps_test.mbt +++ b/immut/list/dps_test.mbt @@ -34,7 +34,7 @@ pub fn map(self : L, f : (Int) -> Int) -> L { ///| fn map_dps(f : (Int) -> Int, lst : L, dest : L) -> Unit { loop lst, dest { - Nil, Cons(_, ..) as c => c.tail = Nil + Nil, Cons(_, ..) as c => c.tail = Nil // c.tail = lst // this is a common error Cons(head, tail~), Cons(_, ..) as c => { @@ -47,13 +47,13 @@ fn map_dps(f : (Int) -> Int, lst : L, dest : L) -> Unit { } test "map" { - let lstL : L = Cons(1, tail=Cons(2, tail=Cons(3, tail=Cons(4, tail=Cons(5, tail=Nil))))) + let lstL : L = Cons( + 1, + tail=Cons(2, tail=Cons(3, tail=Cons(4, tail=Cons(5, tail=Nil)))), + ) let lst : L = map(lstL, fn { x => x * 2 }) inspect!( lst, - content= - "Cons(2, tail=Cons(4, tail=Cons(6, tail=Cons(8, tail=Cons(10, tail=Nil)))))" - , + content="Cons(2, tail=Cons(4, tail=Cons(6, tail=Cons(8, tail=Cons(10, tail=Nil)))))", ) - } From 8421d62553f26832b9accee74784f5354319547a Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Sun, 26 Jan 2025 15:44:44 +0800 Subject: [PATCH 5/8] migrate view --- array/array.mbti | 16 ++ array/blit.mbt | 33 +++ array/moon.pkg.json | 4 +- array/view.mbt | 247 ++++++++++++++++- array/view_test.mbt | 82 ++++++ buffer/buffer.mbt | 6 +- buffer/buffer.mbti | 4 +- buffer/moon.pkg.json | 6 +- builtin/arrayview.mbt | 254 +----------------- builtin/arrayview_test.mbt | 82 ------ builtin/builtin.mbti | 39 +-- builtin/bytes.mbt | 33 --- builtin/show.mbt | 27 -- builtin/show_test.mbt | 15 -- bytes/bytes.mbti | 24 ++ bytes/moon.pkg.json | 2 +- builtin/bytesview.mbt => bytes/view.mbt | 142 ++++++---- .../bytesview_test.mbt => bytes/view_test.mbt | 39 ++- queue/queue.mbt | 12 - queue/queue_test.mbt | 12 + quickcheck/arbitrary.mbt | 8 - quickcheck/arbitrary_test.mbt | 8 + quickcheck/moon.pkg.json | 6 +- rational/moon.pkg.json | 3 +- strconv/decimal.mbt | 2 +- string/string.mbti | 1 + string/view.mbt | 41 ++- 27 files changed, 584 insertions(+), 564 deletions(-) rename builtin/bytesview.mbt => bytes/view.mbt (82%) rename builtin/bytesview_test.mbt => bytes/view_test.mbt (90%) diff --git a/array/array.mbti b/array/array.mbti index 80a142f60..669bd1450 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -1,5 +1,6 @@ package moonbitlang/core/array +alias @moonbitlang/core/bytes as @bytes alias @moonbitlang/core/quickcheck as @quickcheck // Values @@ -8,6 +9,7 @@ alias @moonbitlang/core/quickcheck as @quickcheck impl FixedArray { all[T](Self[T], (T) -> Bool) -> Bool any[T](Self[T], (T) -> Bool) -> Bool + blit_from_bytesview(Self[Byte], Int, @bytes.BytesView) -> Unit contains[T : Eq](Self[T], T) -> Bool copy[T](Self[T]) -> Self[T] each[T](Self[T], (T) -> Unit) -> Unit @@ -68,10 +70,24 @@ impl ArrayView { contains[T : Eq](Self[T], T) -> Bool each[T](Self[T], (T) -> Unit) -> Unit eachi[T](Self[T], (Int, T) -> Unit) -> Unit + filter[T](Self[T], (T) -> Bool) -> Array[T] + fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B + foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B + iter[A](Self[A]) -> Iter[A] + map[T, U](Self[T], (T) -> U) -> Array[U] + map_inplace[T](Self[T], (T) -> T) -> Unit + mapi[T, U](Self[T], (Int, T) -> U) -> Array[U] + mapi_inplace[T](Self[T], (Int, T) -> T) -> Unit + rev_fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B + rev_foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B rev_inplace[T](Self[T]) -> Unit } +impl[T : Compare] Compare for ArrayView[T] +impl[T : Eq] Eq for ArrayView[T] +impl[X : Show] Show for ArrayView[X] // Type aliases +pub typealias View[T] = ArrayView[T] // Traits diff --git a/array/blit.mbt b/array/blit.mbt index 999b0079d..cd8488311 100644 --- a/array/blit.mbt +++ b/array/blit.mbt @@ -56,3 +56,36 @@ test "copy" { a.blit_to(a, len=2, src_offset=1) inspect!(a, content="[2, 3, 3, 4]") } + +///| +/// Copy bytes from a @bytes.View into a fixed array of bytes. +/// +/// Parameters: +/// +/// * `self` : The destination fixed array of bytes. +/// * `bytes_offset` : The starting position in the destination array where bytes will be copied. +/// * `src` : The source View to copy from. +/// +/// Throws a panic if: +/// * `bytes_offset` is negative +/// * The destination array is too small to hold all bytes from the source View +/// +/// Example: +/// +/// ```moonbit +/// let arr = FixedArray::make(4, b'\x00') +/// let view = b"\x01\x02\x03"[1:] +/// arr.blit_from_bytesview(1, view) +/// inspect!(arr, content="[b'\\x00', b'\\x02', b'\\x03', b'\\x00']") +/// ``` +pub fn FixedArray::blit_from_bytesview( + self : FixedArray[Byte], + bytes_offset : Int, + src : @bytes.View +) -> Unit { + let src_len = src.length() + guard bytes_offset >= 0 && bytes_offset + src_len - 1 < self.length() + for i = 0, j = bytes_offset; i < src_len; i = i + 1, j = j + 1 { + self[j] = src[i] + } +} diff --git a/array/moon.pkg.json b/array/moon.pkg.json index f80ac6575..91f299a1c 100644 --- a/array/moon.pkg.json +++ b/array/moon.pkg.json @@ -1,12 +1,12 @@ { "import": [ "moonbitlang/core/builtin", - + "moonbitlang/core/bytes", "moonbitlang/core/test", "moonbitlang/core/quickcheck", "moonbitlang/core/quickcheck/splitmix" ], - "test-import": ["moonbitlang/core/random"], + "test-import": ["moonbitlang/core/random", "moonbitlang/core/json"], "targets": { "array_js.mbt": ["js"], "array_nonjs.mbt": ["not", "js"], diff --git a/array/view.mbt b/array/view.mbt index 33761f4f4..3b2391fe2 100644 --- a/array/view.mbt +++ b/array/view.mbt @@ -12,6 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +///| +/// +/// A `@array.View` represents a view into a section of an array without copying the data. +/// +/// # Example +/// +/// ```moonbit +/// let arr = [1, 2, 3, 4, 5] +/// let view = arr[1:4] // Creates a view of elements at indices 1,2,3 +/// assert_eq!(view[0], 2) +/// assert_eq!(view.length(), 3) +/// ``` +pub typealias View[T] = ArrayView[T] + ///| /// Reverses the elements in the array view in place. /// @@ -28,7 +42,7 @@ /// inspect!(arr, content="[5, 4, 3, 2, 1]") /// } /// ``` -pub fn ArrayView::rev_inplace[T](self : ArrayView[T]) -> Unit { +pub fn View::rev_inplace[T](self : View[T]) -> Unit { let mid_len = self.length() / 2 for i = 0; i < mid_len; i = i + 1 { let j = self.length() - i - 1 @@ -55,7 +69,7 @@ pub fn ArrayView::rev_inplace[T](self : ArrayView[T]) -> Unit { /// inspect!(sum, content="6") /// } /// ``` -pub fn ArrayView::each[T](self : ArrayView[T], f : (T) -> Unit) -> Unit { +pub fn View::each[T](self : View[T], f : (T) -> Unit) -> Unit { for v in self { f(v) } @@ -72,7 +86,7 @@ pub fn ArrayView::each[T](self : ArrayView[T], f : (T) -> Unit) -> Unit { /// v.eachi(fn (i, x) { sum = sum + x + i }) /// assert_eq!(sum, 15) /// ``` -pub fn ArrayView::eachi[T](self : ArrayView[T], f : (Int, T) -> Unit) -> Unit { +pub fn View::eachi[T](self : View[T], f : (Int, T) -> Unit) -> Unit { for i, v in self { f(i, v) } @@ -88,7 +102,7 @@ pub fn ArrayView::eachi[T](self : ArrayView[T], f : (Int, T) -> Unit) -> Unit { /// assert_false!(v[:].all(fn(elem) { elem % 2 == 0 })) /// assert_true!(v[1:4].all(fn(elem) { elem % 2 == 0 })) /// ``` -pub fn ArrayView::all[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { +pub fn View::all[T](self : View[T], f : (T) -> Bool) -> Bool { for v in self { if not(f(v)) { return false @@ -107,7 +121,7 @@ pub fn ArrayView::all[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { /// assert_true!(v.any(fn(ele) { ele < 6 })) /// assert_false!(v.any(fn(ele) { ele < 1 })) /// ``` -pub fn ArrayView::any[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { +pub fn View::any[T](self : View[T], f : (T) -> Bool) -> Bool { for v in self { if f(v) { return true @@ -137,7 +151,7 @@ pub fn ArrayView::any[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { /// inspect!(arr.contains(6), content="false") /// } /// ``` -pub fn ArrayView::contains[T : Eq](self : ArrayView[T], value : T) -> Bool { +pub fn View::contains[T : Eq](self : View[T], value : T) -> Bool { for v in self { if v == value { break true @@ -146,3 +160,224 @@ pub fn ArrayView::contains[T : Eq](self : ArrayView[T], value : T) -> Bool { false } } + +///| +/// Returns an iterator that yields each element of the array view in sequence +/// from start to end. +/// +/// Parameters: +/// +/// * `array_view` : The array view to iterate over. +/// +/// Returns an iterator that yields elements of type `A` from the array view. +/// +/// Example: +/// +/// ```moonbit +/// test "View::iter" { +/// let arr = [1, 2, 3] +/// let view = arr[1:] +/// let mut sum = 0 +/// view.iter().each(fn(x) { sum = sum + x }) +/// inspect!(sum, content="5") +/// } +/// ``` +pub fn View::iter[A](self : View[A]) -> Iter[A] { + Iter::new(fn(yield_) { + for v in self { + guard let IterContinue = yield_(v) else { x => break x } + + } else { + IterContinue + } + }) +} + +///| +/// Fold out values from an View according to certain rules. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].fold(init=0, fn { sum, elem => sum + elem }) +/// assert_eq!(sum, 15) +/// ``` +pub fn View::fold[A, B](self : View[A], init~ : B, f : (B, A) -> B) -> B { + for i = 0, acc = init; i < self.length(); { + continue i + 1, f(acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an View according to certain rules in reversed turn. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].rev_fold(init=0, fn { sum, elem => sum + elem }) +/// assert_eq!(sum, 15) +/// ``` +pub fn View::rev_fold[A, B](self : View[A], init~ : B, f : (B, A) -> B) -> B { + for i = self.length() - 1, acc = init; i >= 0; { + continue i - 1, f(acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an View according to certain rules with index. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].foldi(init=0, fn { index, sum, _elem => sum + index }) +/// assert_eq!(sum, 10) +/// ``` +pub fn View::foldi[A, B](self : View[A], init~ : B, f : (Int, B, A) -> B) -> B { + for i = 0, acc = init; i < self.length(); { + continue i + 1, f(i, acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an View according to certain rules in reversed turn with index. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].rev_foldi(init=0, fn { index, sum, _elem => sum + index }) +/// assert_eq!(sum, 10) +/// ``` +pub fn View::rev_foldi[A, B]( + self : View[A], + init~ : B, + f : (Int, B, A) -> B +) -> B { + let len = self.length() + for i = len - 1, acc = init; i >= 0; { + continue i - 1, f(len - i - 1, acc, self[i]) + } else { + acc + } +} + +///| +/// Maps a function over the elements of the array view. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// let v2 = v[1:].map(fn (x) {x + 1}) +/// assert_eq!(v2, [5, 6]) +/// ``` +pub fn View::map[T, U](self : View[T], f : (T) -> U) -> Array[U] { + if self.length() == 0 { + return [] + } + Array::makei(self.length(), fn(i) { f(self[i]) }) +} + +///| +/// Maps a function over the elements of the array view in place. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// v[1:].map_inplace(fn (x) {x + 1}) +/// assert_eq!(v, [3, 5, 6]) +/// ``` +pub fn View::map_inplace[T](self : View[T], f : (T) -> T) -> Unit { + for i, v in self { + self[i] = f(v) + } +} + +///| +/// Maps a function over the elements of the array view with index. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// let v2 = v[1:].mapi(fn (i, x) {x + i}) +/// assert_eq!(v2, [4, 6]) +/// ``` +pub fn View::mapi[T, U](self : View[T], f : (Int, T) -> U) -> Array[U] { + if self.length() == 0 { + return [] + } + Array::makei(self.length(), fn(i) { f(i, self[i]) }) +} + +///| +/// Maps a function over the elements of the array view with index in place. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// v[1:].mapi_inplace(fn (i, x) {x + i}) +/// assert_eq!(v, [3, 4, 6]) +/// ``` +pub fn View::mapi_inplace[T](self : View[T], f : (Int, T) -> T) -> Unit { + for i, v in self { + self[i] = f(i, v) + } +} + +///| +/// Filters the array view with a predicate function. +/// +/// # Example +/// ``` +/// let arr = [1, 2, 3, 4, 5, 6] +/// let v = arr[2:].filter(fn (x) { x % 2 == 0 }) +/// assert_eq!(v, [4, 6]) +/// ``` +pub fn View::filter[T](self : View[T], f : (T) -> Bool) -> Array[T] { + let arr = [] + for v in self { + if f(v) { + arr.push(v) + } + } + arr +} + +///| +pub impl[X : Show] Show for View[X] with output(self, logger) { + logger.write_iter(self.iter()) +} + +///| +pub impl[T : Eq] Eq for View[T] with op_equal(self, other) -> Bool { + if self.length() != other.length() { + return false + } + for i in 0.. Int { + let len_self = self.length() + let len_other = other.length() + if len_self < len_other { + -1 + } else if len_self > len_other { + 1 + } else { + for i in 0.. Unit { } ///| -/// Writes a sequence of bytes from a BytesView into the buffer. +/// Writes a sequence of bytes from a @bytes.View into the buffer. /// /// Parameters: /// /// * `buffer` : The buffer to write to. -/// * `value` : The BytesView containing the bytes to write. +/// * `value` : The View containing the bytes to write. /// /// Example: /// @@ -581,7 +581,7 @@ pub fn write_bytes(self : T, value : Bytes) -> Unit { /// ) /// } /// ``` -pub fn write_bytesview(self : T, value : BytesView) -> Unit { +pub fn write_bytesview(self : T, value : @bytes.View) -> Unit { let val_len = value.length() self.grow_if_necessary(self.len + val_len) self.data.blit_from_bytesview(self.len, value) diff --git a/buffer/buffer.mbti b/buffer/buffer.mbti index 81b849506..dd669e147 100644 --- a/buffer/buffer.mbti +++ b/buffer/buffer.mbti @@ -1,5 +1,7 @@ package moonbitlang/core/buffer +alias @moonbitlang/core/bytes as @bytes + // Values fn new(size_hint~ : Int = ..) -> T @@ -16,7 +18,7 @@ impl T { to_unchecked_string(Self) -> String //deprecated write_byte(Self, Byte) -> Unit write_bytes(Self, Bytes) -> Unit - write_bytesview(Self, BytesView) -> Unit + write_bytesview(Self, @bytes.BytesView) -> Unit write_char(Self, Char) -> Unit write_double_be(Self, Double) -> Unit write_double_le(Self, Double) -> Unit diff --git a/buffer/moon.pkg.json b/buffer/moon.pkg.json index 40eb88c86..7cc72a25b 100644 --- a/buffer/moon.pkg.json +++ b/buffer/moon.pkg.json @@ -1,3 +1,7 @@ { - "import": ["moonbitlang/core/builtin", "moonbitlang/core/bytes"] + "import": [ + "moonbitlang/core/builtin", + "moonbitlang/core/bytes", + "moonbitlang/core/array" + ] } diff --git a/builtin/arrayview.mbt b/builtin/arrayview.mbt index ca9ebe9d6..0e5692d27 100644 --- a/builtin/arrayview.mbt +++ b/builtin/arrayview.mbt @@ -13,7 +13,17 @@ // limitations under the License. ///| -/// A `ArrayView` is a slice of a `Array`. +/// An `ArrayView` represents a view into a section of an array without copying the data. +/// +/// # Example +/// +/// ```moonbit +/// let arr = [1, 2, 3, 4, 5] +/// let view = arr[1:4] // Creates a view of elements at indices 1,2,3 +/// assert_eq!(view[0], 2) +/// assert_eq!(view.length(), 3) +/// ``` +/// @alert deprecated "use @array.View instead" struct ArrayView[T] { buf : UninitializedArray[T] start : Int @@ -302,245 +312,3 @@ pub fn ArrayView::op_as_view[T]( } ArrayView::{ buf: self.buf, start: self.start + start, len: end - start } } - -///| -/// Returns an iterator that yields each element of the array view in sequence -/// from start to end. -/// -/// Parameters: -/// -/// * `array_view` : The array view to iterate over. -/// -/// Returns an iterator that yields elements of type `A` from the array view. -/// -/// Example: -/// -/// ```moonbit -/// test "ArrayView::iter" { -/// let arr = [1, 2, 3] -/// let view = arr[1:] -/// let mut sum = 0 -/// view.iter().each(fn(x) { sum = sum + x }) -/// inspect!(sum, content="5") -/// } -/// ``` -pub fn ArrayView::iter[A](self : ArrayView[A]) -> Iter[A] { - Iter::new(fn(yield_) { - for v in self { - guard let IterContinue = yield_(v) else { x => break x } - - } else { - IterContinue - } - }) -} - -///| -/// Fold out values from an arrayview according to certain rules. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].fold(init=0, fn { sum, elem => sum + elem }) -/// assert_eq!(sum, 15) -/// ``` -pub fn ArrayView::fold[A, B]( - self : ArrayView[A], - init~ : B, - f : (B, A) -> B -) -> B { - for i = 0, acc = init; i < self.length(); { - continue i + 1, f(acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an arrayview according to certain rules in reversed turn. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].rev_fold(init=0, fn { sum, elem => sum + elem }) -/// assert_eq!(sum, 15) -/// ``` -pub fn ArrayView::rev_fold[A, B]( - self : ArrayView[A], - init~ : B, - f : (B, A) -> B -) -> B { - for i = self.length() - 1, acc = init; i >= 0; { - continue i - 1, f(acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an arrayview according to certain rules with index. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].foldi(init=0, fn { index, sum, _elem => sum + index }) -/// assert_eq!(sum, 10) -/// ``` -pub fn ArrayView::foldi[A, B]( - self : ArrayView[A], - init~ : B, - f : (Int, B, A) -> B -) -> B { - for i = 0, acc = init; i < self.length(); { - continue i + 1, f(i, acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an arrayview according to certain rules in reversed turn with index. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].rev_foldi(init=0, fn { index, sum, _elem => sum + index }) -/// assert_eq!(sum, 10) -/// ``` -pub fn ArrayView::rev_foldi[A, B]( - self : ArrayView[A], - init~ : B, - f : (Int, B, A) -> B -) -> B { - let len = self.length() - for i = len - 1, acc = init; i >= 0; { - continue i - 1, f(len - i - 1, acc, self[i]) - } else { - acc - } -} - -///| -/// Maps a function over the elements of the array view. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// let v2 = v[1:].map(fn (x) {x + 1}) -/// assert_eq!(v2, [5, 6]) -/// ``` -pub fn ArrayView::map[T, U](self : ArrayView[T], f : (T) -> U) -> Array[U] { - if self.length() == 0 { - return [] - } - let arr = Array::make_uninit(self.length()) - for i, v in self { - arr.unsafe_set(i, f(v)) - } - arr -} - -///| -/// Maps a function over the elements of the array view in place. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// v[1:].map_inplace(fn (x) {x + 1}) -/// assert_eq!(v, [3, 5, 6]) -/// ``` -pub fn ArrayView::map_inplace[T](self : ArrayView[T], f : (T) -> T) -> Unit { - for i, v in self { - self[i] = f(v) - } -} - -///| -/// Maps a function over the elements of the array view with index. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// let v2 = v[1:].mapi(fn (i, x) {x + i}) -/// assert_eq!(v2, [4, 6]) -/// ``` -pub fn ArrayView::mapi[T, U]( - self : ArrayView[T], - f : (Int, T) -> U -) -> Array[U] { - if self.length() == 0 { - return [] - } - let arr = Array::make_uninit(self.length()) - for i, v in self { - arr.unsafe_set(i, f(i, v)) - } - arr -} - -///| -/// Maps a function over the elements of the array view with index in place. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// v[1:].mapi_inplace(fn (i, x) {x + i}) -/// assert_eq!(v, [3, 4, 6]) -/// ``` -pub fn ArrayView::mapi_inplace[T]( - self : ArrayView[T], - f : (Int, T) -> T -) -> Unit { - for i, v in self { - self[i] = f(i, v) - } -} - -///| -/// Filters the array view with a predicate function. -/// -/// # Example -/// ``` -/// let arr = [1, 2, 3, 4, 5, 6] -/// let v = arr[2:].filter(fn (x) { x % 2 == 0 }) -/// assert_eq!(v, [4, 6]) -/// ``` -pub fn ArrayView::filter[T](self : ArrayView[T], f : (T) -> Bool) -> Array[T] { - let arr = [] - for v in self { - if f(v) { - arr.push(v) - } - } - arr -} - -///| -pub impl[T : Eq] Eq for ArrayView[T] with op_equal(self, other) -> Bool { - if self.length() != other.length() { - return false - } - for i in 0.. Int { - let len_self = self.length() - let len_other = other.length() - if len_self < len_other { - -1 - } else if len_self > len_other { - 1 - } else { - for i in 0.. Bool) -> Array[T] - fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B - foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B - iter[A](Self[A]) -> Iter[A] length[T](Self[T]) -> Int - map[T, U](Self[T], (T) -> U) -> Array[U] - map_inplace[T](Self[T], (T) -> T) -> Unit - mapi[T, U](Self[T], (Int, T) -> U) -> Array[U] - mapi_inplace[T](Self[T], (Int, T) -> T) -> Unit op_as_view[T](Self[T], start~ : Int = .., end? : Int) -> Self[T] op_get[T](Self[T], Int) -> T op_set[T](Self[T], Int, T) -> Unit - rev_fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B - rev_foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B swap[T](Self[T], Int, Int) -> Unit to_json[X : ToJson](Self[X]) -> Json unsafe_get[T](Self[T], Int) -> T } -impl[T : Compare] Compare for ArrayView[T] -impl[T : Eq] Eq for ArrayView[T] -impl[X : Show] Show for ArrayView[X] type BigInt impl BigInt { @@ -188,28 +175,6 @@ impl BigInt { } impl Show for BigInt -type BytesView -impl BytesView { - iter(Self) -> Iter[Byte] - length(Self) -> Int - op_as_view(Self, start~ : Int = .., end? : Int) -> Self - op_get(Self, Int) -> Byte - to_double_be(Self) -> Double - to_double_le(Self) -> Double - to_float_be(Self) -> Float - to_float_le(Self) -> Float - to_int64_be(Self) -> Int64 - to_int64_le(Self) -> Int64 - to_int_be(Self) -> Int - to_int_le(Self) -> Int - to_uint64_be(Self) -> UInt64 - to_uint64_le(Self) -> UInt64 - to_uint_be(Self) -> UInt - to_uint_le(Self) -> UInt - unsafe_get(Self, Int) -> Byte -} -impl Show for BytesView - pub(all) type! Failure String impl Show for Failure @@ -694,7 +659,6 @@ impl Result { impl FixedArray { blit_from_bytes(Self[Byte], Int, Bytes, Int, Int) -> Unit - blit_from_bytesview(Self[Byte], Int, BytesView) -> Unit blit_from_string(Self[Byte], Int, String, Int, Int) -> Unit blit_to[A](Self[A], Self[A], len~ : Int, src_offset~ : Int = .., dst_offset~ : Int = ..) -> Unit compare[T : Compare](Self[T], Self[T]) -> Int @@ -726,7 +690,6 @@ impl Bytes { makei(Int, (Int) -> Byte) -> Bytes new(Int) -> Bytes of_string(String) -> Bytes - op_as_view(Bytes, start~ : Int = .., end? : Int) -> BytesView op_equal(Bytes, Bytes) -> Bool op_get(Bytes, Int) -> Byte op_set(Bytes, Int, Byte) -> Unit //deprecated diff --git a/builtin/bytes.mbt b/builtin/bytes.mbt index aeefd9fee..a8149574d 100644 --- a/builtin/bytes.mbt +++ b/builtin/bytes.mbt @@ -221,39 +221,6 @@ pub fn FixedArray::blit_from_bytes( } } -///| -/// Copy bytes from a BytesView into a fixed array of bytes. -/// -/// Parameters: -/// -/// * `self` : The destination fixed array of bytes. -/// * `bytes_offset` : The starting position in the destination array where bytes will be copied. -/// * `src` : The source BytesView to copy from. -/// -/// Throws a panic if: -/// * `bytes_offset` is negative -/// * The destination array is too small to hold all bytes from the source BytesView -/// -/// Example: -/// -/// ```moonbit -/// let arr = FixedArray::make(4, b'\x00') -/// let view = b"\x01\x02\x03"[1:] -/// arr.blit_from_bytesview(1, view) -/// inspect!(arr, content="[b'\\x00', b'\\x02', b'\\x03', b'\\x00']") -/// ``` -pub fn FixedArray::blit_from_bytesview( - self : FixedArray[Byte], - bytes_offset : Int, - src : BytesView -) -> Unit { - let src_len = src.length() - guard bytes_offset >= 0 && bytes_offset + src_len - 1 < self.length() - for i = 0, j = bytes_offset; i < src_len; i = i + 1, j = j + 1 { - self[j] = src[i] - } -} - ///| /// Creates a new byte sequence by copying all bytes from the input sequence. /// diff --git a/builtin/show.mbt b/builtin/show.mbt index 2dacf848f..2846ace84 100644 --- a/builtin/show.mbt +++ b/builtin/show.mbt @@ -77,28 +77,6 @@ pub impl Show for Bytes with output(self, logger) { logger.write_string("\"") } -///| -pub impl Show for BytesView with output(self, logger) { - fn to_hex_digit(i : Int) -> Char { - if i < 10 { - Char::from_int('0'.to_int() + i) - } else { - Char::from_int('a'.to_int() + (i - 10)) - } - } - - logger.write_string("b\"") - for i in 0.. ignore - } - logger.write_string("\"") -} - ///| pub impl Show for String with output(self, logger) { logger.write_char('"') @@ -208,11 +186,6 @@ pub impl[X : Show] Show for Array[X] with output(self, logger) { logger.write_iter(self.iter()) } -///| -pub impl[X : Show] Show for ArrayView[X] with output(self, logger) { - logger.write_iter(self.iter()) -} - ///| /// Convert Char to String /// @intrinsic %char.to_string diff --git a/builtin/show_test.mbt b/builtin/show_test.mbt index 3bd9cf1e3..83e34c381 100644 --- a/builtin/show_test.mbt +++ b/builtin/show_test.mbt @@ -71,21 +71,6 @@ test "Show for Bytes" { ) } -test "Show for BytesView" { - inspect!( - b"abcdefg"[1:5].to_string(), - content= - #|b"\x62\x63\x64\x65" - , - ) - inspect!( - b"\x00\xff\x63"[:].to_string(), - content= - #|b"\x00\xff\x63" - , - ) -} - test "Show for String" { fn to_string_using_output(str) { let buf = StringBuilder::new() diff --git a/bytes/bytes.mbti b/bytes/bytes.mbti index e0d873f1a..76f7928ac 100644 --- a/bytes/bytes.mbti +++ b/bytes/bytes.mbti @@ -12,6 +12,28 @@ fn from_iter(Iter[Byte]) -> Bytes fn of(FixedArray[Byte]) -> Bytes // Types and methods +type BytesView //deprecated +impl BytesView { + iter(Self) -> Iter[Byte] + length(Self) -> Int + op_as_view(Self, start~ : Int = .., end? : Int) -> Self + op_get(Self, Int) -> Byte + to_double_be(Self) -> Double + to_double_le(Self) -> Double + to_float_be(Self) -> Float + to_float_le(Self) -> Float + to_int64_be(Self) -> Int64 + to_int64_le(Self) -> Int64 + to_int_be(Self) -> Int + to_int_le(Self) -> Int + to_uint64_be(Self) -> UInt64 + to_uint64_le(Self) -> UInt64 + to_uint_be(Self) -> UInt + to_uint_le(Self) -> UInt + unsafe_get(Self, Int) -> Byte +} +impl Show for BytesView + impl Bytes { default() -> Bytes from_array(Array[Byte]) -> Bytes @@ -19,12 +41,14 @@ impl Bytes { from_iter(Iter[Byte]) -> Bytes iter(Bytes) -> Iter[Byte] of(FixedArray[Byte]) -> Bytes + op_as_view(Bytes, start~ : Int = .., end? : Int) -> BytesView to_array(Bytes) -> Array[Byte] to_fixedarray(Bytes, len? : Int) -> FixedArray[Byte] } impl Hash for Bytes // Type aliases +pub typealias View = BytesView // Traits diff --git a/bytes/moon.pkg.json b/bytes/moon.pkg.json index e4b88edc7..993c140c3 100644 --- a/bytes/moon.pkg.json +++ b/bytes/moon.pkg.json @@ -1,4 +1,4 @@ { "import": ["moonbitlang/core/builtin"], - "test-import": ["moonbitlang/core/array"] + "test-import": ["moonbitlang/core/array", "moonbitlang/core/double"] } diff --git a/builtin/bytesview.mbt b/bytes/view.mbt similarity index 82% rename from builtin/bytesview.mbt rename to bytes/view.mbt index c49b546f5..9af85a881 100644 --- a/builtin/bytesview.mbt +++ b/bytes/view.mbt @@ -25,12 +25,28 @@ /// assert_eq!(bv[1], b'\x02') /// assert_eq!(bv[2], b'\x03') /// ``` +/// @alert deprecated "use @bytes.View instead" struct BytesView { bytes : Bytes start : Int len : Int } +///| +/// A `@bytes.View` represents a view into a section of a `Bytes` without copying the data. +/// +/// # Example +/// +/// ``` +/// let bs = b"\x00\x01\x02\x03\x04\x05" +/// let bv = bs[1:4] +/// assert_eq!(bv.length(), 3) +/// assert_eq!(bv[0], b'\x01') +/// assert_eq!(bv[1], b'\x02') +/// assert_eq!(bv[2], b'\x03') +/// ``` +pub typealias View = BytesView + ///| /// Returns the number of bytes in the view. /// @@ -43,13 +59,13 @@ struct BytesView { /// Example: /// /// ```moonbit -/// test "BytesView::length" { +/// test "View::length" { /// let bytes = b"\x00\x01\x02\x03\x04" /// let view = bytes[2:4] /// inspect!(view.length(), content="2") /// } /// ``` -pub fn BytesView::length(self : BytesView) -> Int { +pub fn View::length(self : View) -> Int { self.len } @@ -69,18 +85,18 @@ pub fn BytesView::length(self : BytesView) -> Int { /// Example: /// /// ```moonbit -/// test "BytesView::op_get" { +/// test "View::op_get" { /// let bytes = b"\x01\x02\x03\x04\x05" /// let view = bytes[1:4] // view contains [0x02, 0x03, 0x04] /// inspect!(view[1], content="b'\\x03'") /// } /// -/// test "panic BytesView::op_get/out_of_bounds" { +/// test "panic View::op_get/out_of_bounds" { /// let view = b"\x01\x02\x03"[:] /// ignore(view[3]) // Index out of bounds /// } /// ``` -pub fn BytesView::op_get(self : BytesView, index : Int) -> Byte { +pub fn View::op_get(self : View, index : Int) -> Byte { guard index >= 0 && index < self.len else { abort( "index out of bounds: the len is from 0 to \{self.len} but the index is \{index}", @@ -107,25 +123,25 @@ pub fn BytesView::op_get(self : BytesView, index : Int) -> Byte { /// Example: /// /// ```moonbit -/// test "BytesView::unsafe_get" { +/// test "View::unsafe_get" { /// let bytes = b"\x01\x02\x03\x04\x05" /// let view = bytes[2:4] // view contains [0x03, 0x04] /// inspect!(view.unsafe_get(0), content="b'\\x03'") /// } /// -/// test "panic BytesView::unsafe_get/out_of_bounds" { +/// test "panic View::unsafe_get/out_of_bounds" { /// let view = b"\x01\x02\x03"[:] /// ignore(view.unsafe_get(3)) // Panic: index out of bounds /// } /// ``` /// /// @alert unsafe "Panic if index is out of bounds" -pub fn BytesView::unsafe_get(self : BytesView, index : Int) -> Byte { +pub fn View::unsafe_get(self : View, index : Int) -> Byte { self.bytes[self.start + index] } ///| -/// Creates a new `BytesView` from the given `Bytes`. +/// Creates a new `View` from the given `Bytes`. /// /// # Example /// @@ -137,11 +153,7 @@ pub fn BytesView::unsafe_get(self : BytesView, index : Int) -> Byte { /// assert_eq!(bv[1], b'\x02') /// assert_eq!(bv[2], b'\x03') /// ``` -pub fn Bytes::op_as_view( - self : Bytes, - start~ : Int = 0, - end? : Int -) -> BytesView { +pub fn Bytes::op_as_view(self : Bytes, start~ : Int = 0, end? : Int) -> View { let len = self.length() let end = match end { None => len @@ -149,13 +161,13 @@ pub fn Bytes::op_as_view( } let start = if start < 0 { len + start } else { start } guard start >= 0 && start <= end && end <= len else { - abort("Invalid index for BytesView") + abort("Invalid index for View") } - BytesView::{ bytes: self, start, len: end - start } + View::{ bytes: self, start, len: end - start } } ///| -/// Creates a new `BytesView` from the given `BytesView`. +/// Creates a new `View` from the given `View`. /// /// # Example /// @@ -165,11 +177,7 @@ pub fn Bytes::op_as_view( /// assert_eq!(bv2.length(), 3) /// assert_eq!(bv2[1], b'\x02') /// ``` -pub fn BytesView::op_as_view( - self : BytesView, - start~ : Int = 0, - end? : Int -) -> BytesView { +pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { let len = self.length() let end = match end { None => len @@ -177,13 +185,13 @@ pub fn BytesView::op_as_view( } let start = if start < 0 { len + start } else { start } guard start >= 0 && start <= end && end <= len else { - abort("Invalid index for BytesView") + abort("Invalid index for View") } - BytesView::{ bytes: self.bytes, start: self.start + start, len: end - start } + View::{ bytes: self.bytes, start: self.start + start, len: end - start } } ///| -/// Returns an iterator over the `BytesView`. +/// Returns an iterator over the `View`. /// /// # Example /// @@ -193,7 +201,7 @@ pub fn BytesView::op_as_view( /// bv.iter().each(fn(x) { sum = sum + x.to_int() }) /// assert_eq!(sum, 15) /// ``` -pub fn BytesView::iter(self : BytesView) -> Iter[Byte] { +pub fn View::iter(self : View) -> Iter[Byte] { Iter::new(fn(yield_) { for i in 0.. break x } @@ -218,17 +226,17 @@ pub fn BytesView::iter(self : BytesView) -> Iter[Byte] { /// Example: /// /// ```moonbit -/// test "BytesView::to_uint_be" { +/// test "View::to_uint_be" { /// let bytes = b"\x12\x34\x56\x78"[:] /// inspect!(bytes.to_uint_be(), content="305419896") // 0x12345678 /// } /// -/// test "panic BytesView::to_uint_be/out_of_bounds" { +/// test "panic View::to_uint_be/out_of_bounds" { /// let bytes = b"\x12\x34\x56"[:] // Less than 4 bytes /// ignore(bytes.to_uint_be()) // Panics with index out of bounds /// } /// ``` -pub fn BytesView::to_uint_be(self : BytesView) -> UInt { +pub fn View::to_uint_be(self : View) -> UInt { (self[0].to_uint() << 24) + (self[1].to_uint() << 16) + (self[2].to_uint() << 8) + @@ -242,7 +250,7 @@ pub fn BytesView::to_uint_be(self : BytesView) -> UInt { /// /// Parameters: /// -/// * `view` : A `BytesView` containing exactly 4 bytes to be interpreted as a +/// * `view` : A `View` containing exactly 4 bytes to be interpreted as a /// little-endian unsigned integer. /// /// Returns an unsigned 32-bit integer (`UInt`) formed by interpreting the bytes @@ -253,13 +261,13 @@ pub fn BytesView::to_uint_be(self : BytesView) -> UInt { /// Example: /// /// ```moonbit -/// test "BytesView::to_uint_le" { +/// test "View::to_uint_le" { /// let bytes = b"\x01\x02\x03\x04" /// let view = bytes[:] /// inspect!(view.to_uint_le(), content="67305985") // 0x04030201 /// } /// ``` -pub fn BytesView::to_uint_le(self : BytesView) -> UInt { +pub fn View::to_uint_le(self : View) -> UInt { self[0].to_uint() + (self[1].to_uint() << 8) + (self[2].to_uint() << 16) + @@ -286,17 +294,17 @@ pub fn BytesView::to_uint_le(self : BytesView) -> UInt { /// Example: /// /// ```moonbit -/// test "BytesView::to_uint64_be" { +/// test "View::to_uint64_be" { /// let bytes = b"\x01\x23\x45\x67\x89\xAB\xCD\xEF"[:] /// inspect!(bytes.to_uint64_be(), content="81985529216486895") /// } /// -/// test "panic BytesView::to_uint64_be/short_input" { +/// test "panic View::to_uint64_be/short_input" { /// let bytes = b"\x01\x02\x03"[:] /// ignore(bytes.to_uint64_be()) // Throws error: index out of bounds /// } /// ``` -pub fn BytesView::to_uint64_be(self : BytesView) -> UInt64 { +pub fn View::to_uint64_be(self : View) -> UInt64 { (self[0].to_uint().to_uint64() << 56) + (self[1].to_uint().to_uint64() << 48) + (self[2].to_uint().to_uint64() << 40) + @@ -322,23 +330,23 @@ pub fn BytesView::to_uint64_be(self : BytesView) -> UInt64 { /// Returns an unsigned 64-bit integer assembled from the bytes in little-endian /// order. /// -/// Throws a panic if the BytesView is less than 8 bytes long or if trying to +/// Throws a panic if the View is less than 8 bytes long or if trying to /// access a byte beyond the view's bounds. /// /// Example: /// /// ```moonbit -/// test "BytesView::to_uint64_le" { +/// test "View::to_uint64_le" { /// let bytes = b"\x01\x02\x03\x04\x05\x06\x07\x08"[:] /// inspect!(bytes.to_uint64_le(), content="578437695752307201") /// } /// -/// test "panic BytesView::to_uint64_le/short_view" { +/// test "panic View::to_uint64_le/short_view" { /// let bytes = b"\x01\x02\x03"[:] /// ignore(bytes.to_uint64_le()) // Panics: view is too short /// } /// ``` -pub fn BytesView::to_uint64_le(self : BytesView) -> UInt64 { +pub fn View::to_uint64_le(self : View) -> UInt64 { self[0].to_uint().to_uint64() + (self[1].to_uint().to_uint64() << 8) + (self[2].to_uint().to_uint64() << 16) + @@ -357,7 +365,7 @@ pub fn BytesView::to_uint64_le(self : BytesView) -> UInt64 { /// /// Parameters: /// -/// * `bytesView` : A view into a byte sequence that must be exactly 4 bytes +/// * `View` : A view into a byte sequence that must be exactly 4 bytes /// long. The bytes are interpreted in big-endian order, where the first byte is /// the most significant byte and the last byte is the least significant byte. /// @@ -367,12 +375,12 @@ pub fn BytesView::to_uint64_le(self : BytesView) -> UInt64 { /// Example: /// /// ```moonbit -/// test "BytesView::to_int_be" { +/// test "View::to_int_be" { /// let bytes = b"\x80\x00\x00\x00"[:] // Represents -2147483648 in two's complement /// inspect!(bytes.to_int_be(), content="-2147483648") /// } /// ``` -pub fn BytesView::to_int_be(self : BytesView) -> Int { +pub fn View::to_int_be(self : View) -> Int { self.to_uint_be().reinterpret_as_int() } @@ -394,13 +402,13 @@ pub fn BytesView::to_int_be(self : BytesView) -> Int { /// Example: /// /// ```moonbit -/// test "BytesView::to_int_le" { +/// test "View::to_int_le" { /// let bytes = b"\x78\x56\x34\x12" /// let view = bytes[:] /// inspect!(view.to_int_le(), content="305419896") // 0x12345678 in decimal /// } /// ``` -pub fn BytesView::to_int_le(self : BytesView) -> Int { +pub fn View::to_int_le(self : View) -> Int { self.to_uint_le().reinterpret_as_int() } @@ -419,12 +427,12 @@ pub fn BytesView::to_int_le(self : BytesView) -> Int { /// Example: /// /// ```moonbit -/// test "BytesView::to_int64_be" { +/// test "View::to_int64_be" { /// let bytes = b"\x80\x00\x00\x00\x00\x00\x00\x00"[:] // Most negative 64-bit integer /// inspect!(bytes.to_int64_be(), content="-9223372036854775808") /// } /// ``` -pub fn BytesView::to_int64_be(self : BytesView) -> Int64 { +pub fn View::to_int64_be(self : View) -> Int64 { self.to_uint64_be().reinterpret_as_int64() } @@ -444,13 +452,13 @@ pub fn BytesView::to_int64_be(self : BytesView) -> Int64 { /// Example: /// /// ```moonbit -/// test "BytesView::to_int64_le" { +/// test "View::to_int64_le" { /// let bytes = b"\x01\x02\x03\x04\x05\x06\x07\x08" /// let view = bytes[:] /// inspect!(view.to_int64_le(), content="578437695752307201") /// } /// ``` -pub fn BytesView::to_int64_le(self : BytesView) -> Int64 { +pub fn View::to_int64_le(self : View) -> Int64 { self.to_uint64_le().reinterpret_as_int64() } @@ -470,7 +478,7 @@ pub fn BytesView::to_int64_le(self : BytesView) -> Int64 { /// Example: /// /// ```moonbit -/// test "BytesView::to_float_be" { +/// test "View::to_float_be" { /// let bytes = b"\x40\x48\xF5\xC3" // Represents 3.14 in IEEE 754 format /// let view = bytes[:] /// let float = view.to_float_be() @@ -478,7 +486,7 @@ pub fn BytesView::to_int64_le(self : BytesView) -> Int64 { /// inspect!(float.to_double(), content="3.140000104904175") /// } /// ``` -pub fn BytesView::to_float_be(self : BytesView) -> Float { +pub fn View::to_float_be(self : View) -> Float { self.to_uint_be().reinterpret_as_float() } @@ -496,13 +504,13 @@ pub fn BytesView::to_float_be(self : BytesView) -> Float { /// Example: /// /// ```moonbit -/// test "BytesView::to_float_le" { +/// test "View::to_float_le" { /// let bytes = b"\x00\x00\x80\x3F" // Represents 1.0 in little-endian IEEE-754 /// let f = bytes[:].to_float_le() /// inspect!(f.to_double(), content="1") /// } /// ``` -pub fn BytesView::to_float_le(self : BytesView) -> Float { +pub fn View::to_float_le(self : View) -> Float { self.to_uint_le().reinterpret_as_float() } @@ -522,14 +530,14 @@ pub fn BytesView::to_float_le(self : BytesView) -> Float { /// Example: /// /// ```moonbit -/// test "BytesView::to_double_be" { +/// test "View::to_double_be" { /// // Bytes representing 1.0 in IEEE 754 double-precision format (big-endian) /// let bytes = b"\x3F\xF0\x00\x00\x00\x00\x00\x00" /// let view = bytes[:] /// inspect!(view.to_double_be(), content="1") /// } /// ``` -pub fn BytesView::to_double_be(self : BytesView) -> Double { +pub fn View::to_double_be(self : View) -> Double { self.to_uint64_be().reinterpret_as_double() } @@ -548,12 +556,34 @@ pub fn BytesView::to_double_be(self : BytesView) -> Double { /// Example: /// /// ```moonbit -/// test "BytesView::to_double_le" { +/// test "View::to_double_le" { /// let bytes = b"\x00\x00\x00\x00\x00\x00\xF0\x3F" // represents 1.0 in little-endian /// let view = bytes[:] /// inspect!(view.to_double_le(), content="1") /// } /// ``` -pub fn BytesView::to_double_le(self : BytesView) -> Double { +pub fn View::to_double_le(self : View) -> Double { self.to_uint64_le().reinterpret_as_double() } + +///| +pub impl Show for View with output(self, logger) { + fn to_hex_digit(i : Int) -> Char { + if i < 10 { + Char::from_int('0'.to_int() + i) + } else { + Char::from_int('a'.to_int() + (i - 10)) + } + } + + logger.write_string("b\"") + for i in 0.. ignore + } + logger.write_string("\"") +} diff --git a/builtin/bytesview_test.mbt b/bytes/view_test.mbt similarity index 90% rename from builtin/bytesview_test.mbt rename to bytes/view_test.mbt index 0c8401861..afa99ca68 100644 --- a/builtin/bytesview_test.mbt +++ b/bytes/view_test.mbt @@ -291,7 +291,7 @@ test "panic negative index2" { } -test "BytesView::unsafe_get additional test" { +test "View::unsafe_get additional test" { let bytes = b"\x01\x02\x03\x04\x05" let view = bytes[1:4] // view contains [0x02, 0x03, 0x04] let result = view.unsafe_get(1) // gets byte at index 1 (the second byte) of the view @@ -303,26 +303,26 @@ test "to_uint_be with b'\\xFF\\xFF\\xFF\\xFF'" { inspect!(bytes.to_uint_be(), content="4294967295") } -test "BytesView::to_uint_le with non-zero bytes" { +test "View::to_uint_le with non-zero bytes" { let bytes = b"\x01\x02\x03\x04" let view = bytes[:] inspect!(view.to_uint_le(), content="67305985") // 67305985 = 0x04030201 } -test "panic BytesView::to_uint_le/out_of_bounds" { +test "panic View::to_uint_le/out_of_bounds" { let bytes = b"\x01\x02\x03" // Only 3 bytes let view = bytes[:] ignore(view.to_uint_le()) // Should panic: index out of bounds } -test "BytesView::to_uint64_be/first_byte_operation" { +test "View::to_uint64_be/first_byte_operation" { let bytes = b"\xFF\x00\x00\x00\x00\x00\x00\x00"[:] // First byte is all 1s let result = bytes.to_uint64_be() // First byte shifted left by 56 bits should give us: 0xFF00000000000000 inspect!(result, content="18374686479671623680") } -test "test BytesView::to_uint64_le with binary pattern" { +test "test View::to_uint64_le with binary pattern" { let bytes = b"\x01\x00\x00\x00\x00\x00\x00\x00"[:] inspect!(bytes.to_uint64_le(), content="1") let bytes2 = b"\x00\x01\x00\x00\x00\x00\x00\x00"[:] @@ -333,12 +333,12 @@ test "test BytesView::to_uint64_le with binary pattern" { inspect!(bytes3.to_uint64_le(), content="578437695752307201") } -test "test BytesView::to_int_le with a non-zero 32-bit number" { +test "test View::to_int_le with a non-zero 32-bit number" { let bytes = b"\x78\x56\x34\x12"[:] inspect!(bytes.to_int_le(), content="305419896") } -test "BytesView::to_int64_be test cases" { +test "View::to_int64_be test cases" { // Test positive number let bytes = b"\x00\x00\x00\x00\x00\x00\x00\x01" inspect!(bytes[:].to_int64_be(), content="1") @@ -352,7 +352,7 @@ test "BytesView::to_int64_be test cases" { inspect!(bytes3[:].to_int64_be(), content="9223372036854775807") } -test "BytesView::to_int64_le with mixed bytes" { +test "View::to_int64_le with mixed bytes" { // Test with bytes containing both negative and positive values let bytes = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" let view = bytes[:] @@ -363,10 +363,10 @@ test "panic to_float_be/short_input" { // Test that trying to read from a view that's too short causes a panic let bytes = b"\x40\x49" let view = bytes[:] - ignore(@builtin.BytesView::to_float_be(view)) // Should panic due to insufficient bytes + ignore(View::to_float_be(view)) // Should panic due to insufficient bytes } -test "BytesView::to_float_le with different values" { +test "View::to_float_le with different values" { // Test with value 0.0 let bytes = b"\x00\x00\x00\x00" let f = bytes[:].to_float_le() @@ -378,7 +378,7 @@ test "BytesView::to_float_le with different values" { inspect!(f2.to_double(), content="-1") } -test "BytesView::to_double_be/zero" { +test "View::to_double_be/zero" { let bytes = b"\x00\x00\x00\x00\x00\x00\x00\x00" let view = bytes[:] inspect!(view.to_double_be(), content="0") @@ -406,7 +406,22 @@ test "iter break early" { inspect!(total, content="3") // \x01 + \x02 = 3 } -test "BytesView::to_int_be with positive value" { +test "View::to_int_be with positive value" { let bytes = b"\x00\x00\x00\x01"[:] // Represents 1 in big-endian inspect!(bytes.to_int_be(), content="1") } + +test "Show for View" { + inspect!( + b"abcdefg"[1:5].to_string(), + content= + #|b"\x62\x63\x64\x65" + , + ) + inspect!( + b"\x00\xff\x63"[:].to_string(), + content= + #|b"\x00\xff\x63" + , + ) +} diff --git a/queue/queue.mbt b/queue/queue.mbt index 234d5ccae..a2d826c74 100644 --- a/queue/queue.mbt +++ b/queue/queue.mbt @@ -461,15 +461,3 @@ pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[X] with arbitrar ) { @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter } - -test "queue arbitrary" { - let samples : Array[T[Int]] = @quickcheck.samples(20) - inspect!( - samples[1:5], - content="[@queue.of([]), @queue.of([0]), @queue.of([0]), @queue.of([0])]", - ) - inspect!( - samples[15], - content="@queue.of([0, 0, 0, 0, 0, -1, -3, -3, -1, -4, 5, -1])", - ) -} diff --git a/queue/queue_test.mbt b/queue/queue_test.mbt index 2d35d92c9..6dbd095a5 100644 --- a/queue/queue_test.mbt +++ b/queue/queue_test.mbt @@ -183,3 +183,15 @@ test "to_string" { let queue : @queue.T[Int] = @queue.from_array([9, 8, 7, 5]) assert_eq!(queue.to_string(), "@queue.of([9, 8, 7, 5])") } + +test "queue arbitrary" { + let samples : Array[T[Int]] = @quickcheck.samples(20) + inspect!( + samples[1:5], + content="[@queue.of([]), @queue.of([0]), @queue.of([0]), @queue.of([0])]", + ) + inspect!( + samples[15], + content="@queue.of([0, 0, 0, 0, 0, -1, -3, -3, -1, -4, 5, -1])", + ) +} diff --git a/quickcheck/arbitrary.mbt b/quickcheck/arbitrary.mbt index f086fd53d..1201aff4d 100644 --- a/quickcheck/arbitrary.mbt +++ b/quickcheck/arbitrary.mbt @@ -121,14 +121,6 @@ pub impl[X : Arbitrary] Arbitrary for Iter[X] with arbitrary(size, rs) { }) } -test "iter arbitrary" { - let samples : Array[Iter[Int]] = samples(20) - inspect!("[0, 0, 0, 1, 2, -2]", content="[0, 0, 0, 1, 2, -2]") - inspect!(samples[1:5], content="[[], [0], [0], [0]]") - // inspect!(samples[9], content="[0, 0, 0, 1, 2, -2]") (Cause infinite loop?) - inspect!(samples[10], content="[0, 0, 0]") -} - ///| pub fn gen[T : Arbitrary](size? : Int, state? : @splitmix.RandomState) -> T { let size = match size { diff --git a/quickcheck/arbitrary_test.mbt b/quickcheck/arbitrary_test.mbt index c99c9a3e5..36cd16a50 100644 --- a/quickcheck/arbitrary_test.mbt +++ b/quickcheck/arbitrary_test.mbt @@ -45,3 +45,11 @@ test "gen with default parameters" { let x : Bool = @quickcheck.gen() inspect!(x, content="true") } + +test "iter arbitrary" { + let samples : Array[Iter[Int]] = samples(20) + inspect!("[0, 0, 0, 1, 2, -2]", content="[0, 0, 0, 1, 2, -2]") + inspect!(samples[1:5], content="[[], [0], [0], [0]]") + // inspect!(samples[9], content="[0, 0, 0, 1, 2, -2]") (Cause infinite loop?) + inspect!(samples[10], content="[0, 0, 0]") +} diff --git a/quickcheck/moon.pkg.json b/quickcheck/moon.pkg.json index 53eeb0cf5..6af6c865f 100644 --- a/quickcheck/moon.pkg.json +++ b/quickcheck/moon.pkg.json @@ -1,3 +1,7 @@ { - "import": ["moonbitlang/core/quickcheck/splitmix", "moonbitlang/core/builtin"] + "import": [ + "moonbitlang/core/quickcheck/splitmix", + "moonbitlang/core/builtin" + ], + "test-import": ["moonbitlang/core/array"] } diff --git a/rational/moon.pkg.json b/rational/moon.pkg.json index cc55d2281..d7c190055 100644 --- a/rational/moon.pkg.json +++ b/rational/moon.pkg.json @@ -5,5 +5,6 @@ "moonbitlang/core/double", "moonbitlang/core/int64", "moonbitlang/core/quickcheck" - ] + ], + "test-import": ["moonbitlang/core/array"] } diff --git a/strconv/decimal.mbt b/strconv/decimal.mbt index 3b1f11e4d..c3da3a54c 100644 --- a/strconv/decimal.mbt +++ b/strconv/decimal.mbt @@ -64,7 +64,7 @@ pub fn parse_decimal(str : String) -> Decimal!StrConvError { } ///| -fn parse_decimal_from_view(str : @string.StringView) -> Decimal!StrConvError { +fn parse_decimal_from_view(str : @string.View) -> Decimal!StrConvError { let d = Decimal::new() let mut has_dp = false let mut has_digits = false diff --git a/string/string.mbti b/string/string.mbti index d789dabb9..7a4590b64 100644 --- a/string/string.mbti +++ b/string/string.mbti @@ -71,6 +71,7 @@ impl String { } // Type aliases +pub typealias View = StringView // Traits diff --git a/string/view.mbt b/string/view.mbt index 986865686..a8365f152 100644 --- a/string/view.mbt +++ b/string/view.mbt @@ -16,6 +16,7 @@ /// A `StringView` represents a view of a String that maintains proper Unicode /// character boundaries. It allows safe access to a substring while handling /// multi-byte characters correctly. +/// alert deprecated "use @string.View instead" struct StringView { // # Fields // @@ -30,6 +31,12 @@ struct StringView { end : Int } +///| +/// A `@string.View` represents a view of a String that maintains proper Unicode +/// character boundaries. It allows safe access to a substring while handling +/// multi-byte characters correctly. +pub typealias View = StringView + ///| /// A `StringIndex` represents an unicode-aware position within a string. /// @@ -151,7 +158,7 @@ pub fn index_at_rev( /// /// Note this has O(n) complexity where n is the length of the code points in /// the view. -pub fn StringView::length(self : StringView) -> Int { +pub fn View::length(self : View) -> Int { let mut len = 0 for index = self.start; index < self.end; index = index + 1 { let c1 = self.str.unsafe_charcode_at(index) @@ -173,7 +180,7 @@ pub fn StringView::length(self : StringView) -> Int { /// Test if the length of the view is equal to the given length. /// /// This has O(n) complexity where n is the length in the parameter. -pub fn length_eq(self : StringView, len : Int) -> Bool { +pub fn length_eq(self : View, len : Int) -> Bool { for index = self.start, self_len = 0 index < self.end && self_len < len index = index + 1, self_len = self_len + 1 { @@ -195,7 +202,7 @@ pub fn length_eq(self : StringView, len : Int) -> Bool { /// Test if the length of the view is greater than or equal to the given length. /// /// This has O(n) complexity where n is the length in the parameter. -pub fn length_ge(self : StringView, len : Int) -> Bool { +pub fn length_ge(self : View, len : Int) -> Bool { for index = self.start, self_len = 0 index < self.end && self_len < len index = index + 1, self_len = self_len + 1 { @@ -214,7 +221,7 @@ pub fn length_ge(self : StringView, len : Int) -> Bool { } ///| -/// Creates a `StringView` into a `String`. +/// Creates a `View` into a `String`. /// /// # Example /// @@ -225,11 +232,7 @@ pub fn length_ge(self : StringView, len : Int) -> Bool { /// #|"ello🤣" ///) /// ``` -pub fn String::op_as_view( - self : String, - start~ : Int = 0, - end? : Int -) -> StringView { +pub fn String::op_as_view(self : String, start~ : Int = 0, end? : Int) -> View { let str_len = self.charcode_length() let start = if start >= 0 { guard let Some(start_offset) = index_at(self, start, start=0) else { @@ -258,13 +261,13 @@ pub fn String::op_as_view( None => str_len } guard start >= 0 && start <= end && end <= str_len else { - abort("Invalid index for StringView") + abort("Invalid index for View") } { str: self, start, end } } ///| -/// Creates a new `StringView` from an existing `StringView`. +/// Creates a new `View` from an existing `View`. /// /// # Example /// @@ -276,11 +279,7 @@ pub fn String::op_as_view( /// #|"llo🤣" /// ) /// ``` -pub fn StringView::op_as_view( - self : StringView, - start~ : Int = 0, - end? : Int -) -> StringView { +pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { let start = if start >= 0 { guard let Some(start_offset) = index_at(self.str, start, start=self.start) else { _ => abort("Invalid start index") @@ -312,7 +311,7 @@ pub fn StringView::op_as_view( end >= self.start && end <= self.end && start <= end else { - abort("Invalid index for StringView") + abort("Invalid index for View") } { str: self.str, start, end } } @@ -331,7 +330,7 @@ pub fn StringView::op_as_view( /// inspect!(view[0], content="'e'") /// inspect!(view[4], content="'🤣'") /// ``` -pub fn StringView::op_get(self : StringView, index : Int) -> Char { +pub fn View::op_get(self : View, index : Int) -> Char { guard index >= 0 else { abort("Index out of bounds: cannot access negative index") } @@ -383,7 +382,7 @@ pub fn StringView::op_get(self : StringView, index : Int) -> Char { /// inspect!(view.rev_get(0), content="'🤣'") /// inspect!(view.rev_get(4), content="'e'") /// ``` -pub fn rev_get(self : StringView, index : Int) -> Char { +pub fn rev_get(self : View, index : Int) -> Char { guard index >= 0 else { abort("Index out of bounds: cannot access negative index") } @@ -421,14 +420,14 @@ pub fn rev_get(self : StringView, index : Int) -> Char { } ///| -pub impl Show for StringView with output(self, logger) { +pub impl Show for View with output(self, logger) { let substr = self.str.substring(start=self.start, end=self.end) String::output(substr, logger) } ///| /// Returns an iterator over the Unicode characters in the string view. -pub fn StringView::iter(self : StringView) -> Iter[Char] { +pub fn View::iter(self : View) -> Iter[Char] { Iter::new(fn(yield_) { for index = self.start; index < self.end; index = index + 1 { let c1 = self.str.unsafe_charcode_at(index) From 0dd9b2df20c034b2b9a2fb90ec2af67d20f4c4c7 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Mon, 27 Jan 2025 10:55:46 +0800 Subject: [PATCH 6/8] Revert "migrate view" This reverts commit 8421d62553f26832b9accee74784f5354319547a. --- array/array.mbti | 16 -- array/blit.mbt | 33 --- array/moon.pkg.json | 4 +- array/view.mbt | 247 +---------------- array/view_test.mbt | 82 ------ buffer/buffer.mbt | 6 +- buffer/buffer.mbti | 4 +- buffer/moon.pkg.json | 6 +- builtin/arrayview.mbt | 254 +++++++++++++++++- builtin/arrayview_test.mbt | 82 ++++++ builtin/builtin.mbti | 39 ++- builtin/bytes.mbt | 33 +++ bytes/view.mbt => builtin/bytesview.mbt | 142 ++++------ .../bytesview_test.mbt | 39 +-- builtin/show.mbt | 27 ++ builtin/show_test.mbt | 15 ++ bytes/bytes.mbti | 24 -- bytes/moon.pkg.json | 2 +- queue/queue.mbt | 12 + queue/queue_test.mbt | 12 - quickcheck/arbitrary.mbt | 8 + quickcheck/arbitrary_test.mbt | 8 - quickcheck/moon.pkg.json | 6 +- rational/moon.pkg.json | 3 +- strconv/decimal.mbt | 2 +- string/string.mbti | 1 - string/view.mbt | 41 +-- 27 files changed, 564 insertions(+), 584 deletions(-) rename bytes/view.mbt => builtin/bytesview.mbt (82%) rename bytes/view_test.mbt => builtin/bytesview_test.mbt (90%) diff --git a/array/array.mbti b/array/array.mbti index 669bd1450..80a142f60 100644 --- a/array/array.mbti +++ b/array/array.mbti @@ -1,6 +1,5 @@ package moonbitlang/core/array -alias @moonbitlang/core/bytes as @bytes alias @moonbitlang/core/quickcheck as @quickcheck // Values @@ -9,7 +8,6 @@ alias @moonbitlang/core/quickcheck as @quickcheck impl FixedArray { all[T](Self[T], (T) -> Bool) -> Bool any[T](Self[T], (T) -> Bool) -> Bool - blit_from_bytesview(Self[Byte], Int, @bytes.BytesView) -> Unit contains[T : Eq](Self[T], T) -> Bool copy[T](Self[T]) -> Self[T] each[T](Self[T], (T) -> Unit) -> Unit @@ -70,24 +68,10 @@ impl ArrayView { contains[T : Eq](Self[T], T) -> Bool each[T](Self[T], (T) -> Unit) -> Unit eachi[T](Self[T], (Int, T) -> Unit) -> Unit - filter[T](Self[T], (T) -> Bool) -> Array[T] - fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B - foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B - iter[A](Self[A]) -> Iter[A] - map[T, U](Self[T], (T) -> U) -> Array[U] - map_inplace[T](Self[T], (T) -> T) -> Unit - mapi[T, U](Self[T], (Int, T) -> U) -> Array[U] - mapi_inplace[T](Self[T], (Int, T) -> T) -> Unit - rev_fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B - rev_foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B rev_inplace[T](Self[T]) -> Unit } -impl[T : Compare] Compare for ArrayView[T] -impl[T : Eq] Eq for ArrayView[T] -impl[X : Show] Show for ArrayView[X] // Type aliases -pub typealias View[T] = ArrayView[T] // Traits diff --git a/array/blit.mbt b/array/blit.mbt index cd8488311..999b0079d 100644 --- a/array/blit.mbt +++ b/array/blit.mbt @@ -56,36 +56,3 @@ test "copy" { a.blit_to(a, len=2, src_offset=1) inspect!(a, content="[2, 3, 3, 4]") } - -///| -/// Copy bytes from a @bytes.View into a fixed array of bytes. -/// -/// Parameters: -/// -/// * `self` : The destination fixed array of bytes. -/// * `bytes_offset` : The starting position in the destination array where bytes will be copied. -/// * `src` : The source View to copy from. -/// -/// Throws a panic if: -/// * `bytes_offset` is negative -/// * The destination array is too small to hold all bytes from the source View -/// -/// Example: -/// -/// ```moonbit -/// let arr = FixedArray::make(4, b'\x00') -/// let view = b"\x01\x02\x03"[1:] -/// arr.blit_from_bytesview(1, view) -/// inspect!(arr, content="[b'\\x00', b'\\x02', b'\\x03', b'\\x00']") -/// ``` -pub fn FixedArray::blit_from_bytesview( - self : FixedArray[Byte], - bytes_offset : Int, - src : @bytes.View -) -> Unit { - let src_len = src.length() - guard bytes_offset >= 0 && bytes_offset + src_len - 1 < self.length() - for i = 0, j = bytes_offset; i < src_len; i = i + 1, j = j + 1 { - self[j] = src[i] - } -} diff --git a/array/moon.pkg.json b/array/moon.pkg.json index 91f299a1c..f80ac6575 100644 --- a/array/moon.pkg.json +++ b/array/moon.pkg.json @@ -1,12 +1,12 @@ { "import": [ "moonbitlang/core/builtin", - "moonbitlang/core/bytes", + "moonbitlang/core/test", "moonbitlang/core/quickcheck", "moonbitlang/core/quickcheck/splitmix" ], - "test-import": ["moonbitlang/core/random", "moonbitlang/core/json"], + "test-import": ["moonbitlang/core/random"], "targets": { "array_js.mbt": ["js"], "array_nonjs.mbt": ["not", "js"], diff --git a/array/view.mbt b/array/view.mbt index 3b2391fe2..33761f4f4 100644 --- a/array/view.mbt +++ b/array/view.mbt @@ -12,20 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -///| -/// -/// A `@array.View` represents a view into a section of an array without copying the data. -/// -/// # Example -/// -/// ```moonbit -/// let arr = [1, 2, 3, 4, 5] -/// let view = arr[1:4] // Creates a view of elements at indices 1,2,3 -/// assert_eq!(view[0], 2) -/// assert_eq!(view.length(), 3) -/// ``` -pub typealias View[T] = ArrayView[T] - ///| /// Reverses the elements in the array view in place. /// @@ -42,7 +28,7 @@ pub typealias View[T] = ArrayView[T] /// inspect!(arr, content="[5, 4, 3, 2, 1]") /// } /// ``` -pub fn View::rev_inplace[T](self : View[T]) -> Unit { +pub fn ArrayView::rev_inplace[T](self : ArrayView[T]) -> Unit { let mid_len = self.length() / 2 for i = 0; i < mid_len; i = i + 1 { let j = self.length() - i - 1 @@ -69,7 +55,7 @@ pub fn View::rev_inplace[T](self : View[T]) -> Unit { /// inspect!(sum, content="6") /// } /// ``` -pub fn View::each[T](self : View[T], f : (T) -> Unit) -> Unit { +pub fn ArrayView::each[T](self : ArrayView[T], f : (T) -> Unit) -> Unit { for v in self { f(v) } @@ -86,7 +72,7 @@ pub fn View::each[T](self : View[T], f : (T) -> Unit) -> Unit { /// v.eachi(fn (i, x) { sum = sum + x + i }) /// assert_eq!(sum, 15) /// ``` -pub fn View::eachi[T](self : View[T], f : (Int, T) -> Unit) -> Unit { +pub fn ArrayView::eachi[T](self : ArrayView[T], f : (Int, T) -> Unit) -> Unit { for i, v in self { f(i, v) } @@ -102,7 +88,7 @@ pub fn View::eachi[T](self : View[T], f : (Int, T) -> Unit) -> Unit { /// assert_false!(v[:].all(fn(elem) { elem % 2 == 0 })) /// assert_true!(v[1:4].all(fn(elem) { elem % 2 == 0 })) /// ``` -pub fn View::all[T](self : View[T], f : (T) -> Bool) -> Bool { +pub fn ArrayView::all[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { for v in self { if not(f(v)) { return false @@ -121,7 +107,7 @@ pub fn View::all[T](self : View[T], f : (T) -> Bool) -> Bool { /// assert_true!(v.any(fn(ele) { ele < 6 })) /// assert_false!(v.any(fn(ele) { ele < 1 })) /// ``` -pub fn View::any[T](self : View[T], f : (T) -> Bool) -> Bool { +pub fn ArrayView::any[T](self : ArrayView[T], f : (T) -> Bool) -> Bool { for v in self { if f(v) { return true @@ -151,7 +137,7 @@ pub fn View::any[T](self : View[T], f : (T) -> Bool) -> Bool { /// inspect!(arr.contains(6), content="false") /// } /// ``` -pub fn View::contains[T : Eq](self : View[T], value : T) -> Bool { +pub fn ArrayView::contains[T : Eq](self : ArrayView[T], value : T) -> Bool { for v in self { if v == value { break true @@ -160,224 +146,3 @@ pub fn View::contains[T : Eq](self : View[T], value : T) -> Bool { false } } - -///| -/// Returns an iterator that yields each element of the array view in sequence -/// from start to end. -/// -/// Parameters: -/// -/// * `array_view` : The array view to iterate over. -/// -/// Returns an iterator that yields elements of type `A` from the array view. -/// -/// Example: -/// -/// ```moonbit -/// test "View::iter" { -/// let arr = [1, 2, 3] -/// let view = arr[1:] -/// let mut sum = 0 -/// view.iter().each(fn(x) { sum = sum + x }) -/// inspect!(sum, content="5") -/// } -/// ``` -pub fn View::iter[A](self : View[A]) -> Iter[A] { - Iter::new(fn(yield_) { - for v in self { - guard let IterContinue = yield_(v) else { x => break x } - - } else { - IterContinue - } - }) -} - -///| -/// Fold out values from an View according to certain rules. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].fold(init=0, fn { sum, elem => sum + elem }) -/// assert_eq!(sum, 15) -/// ``` -pub fn View::fold[A, B](self : View[A], init~ : B, f : (B, A) -> B) -> B { - for i = 0, acc = init; i < self.length(); { - continue i + 1, f(acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an View according to certain rules in reversed turn. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].rev_fold(init=0, fn { sum, elem => sum + elem }) -/// assert_eq!(sum, 15) -/// ``` -pub fn View::rev_fold[A, B](self : View[A], init~ : B, f : (B, A) -> B) -> B { - for i = self.length() - 1, acc = init; i >= 0; { - continue i - 1, f(acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an View according to certain rules with index. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].foldi(init=0, fn { index, sum, _elem => sum + index }) -/// assert_eq!(sum, 10) -/// ``` -pub fn View::foldi[A, B](self : View[A], init~ : B, f : (Int, B, A) -> B) -> B { - for i = 0, acc = init; i < self.length(); { - continue i + 1, f(i, acc, self[i]) - } else { - acc - } -} - -///| -/// Fold out values from an View according to certain rules in reversed turn with index. -/// -/// # Example -/// ``` -/// let sum = [1, 2, 3, 4, 5][:].rev_foldi(init=0, fn { index, sum, _elem => sum + index }) -/// assert_eq!(sum, 10) -/// ``` -pub fn View::rev_foldi[A, B]( - self : View[A], - init~ : B, - f : (Int, B, A) -> B -) -> B { - let len = self.length() - for i = len - 1, acc = init; i >= 0; { - continue i - 1, f(len - i - 1, acc, self[i]) - } else { - acc - } -} - -///| -/// Maps a function over the elements of the array view. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// let v2 = v[1:].map(fn (x) {x + 1}) -/// assert_eq!(v2, [5, 6]) -/// ``` -pub fn View::map[T, U](self : View[T], f : (T) -> U) -> Array[U] { - if self.length() == 0 { - return [] - } - Array::makei(self.length(), fn(i) { f(self[i]) }) -} - -///| -/// Maps a function over the elements of the array view in place. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// v[1:].map_inplace(fn (x) {x + 1}) -/// assert_eq!(v, [3, 5, 6]) -/// ``` -pub fn View::map_inplace[T](self : View[T], f : (T) -> T) -> Unit { - for i, v in self { - self[i] = f(v) - } -} - -///| -/// Maps a function over the elements of the array view with index. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// let v2 = v[1:].mapi(fn (i, x) {x + i}) -/// assert_eq!(v2, [4, 6]) -/// ``` -pub fn View::mapi[T, U](self : View[T], f : (Int, T) -> U) -> Array[U] { - if self.length() == 0 { - return [] - } - Array::makei(self.length(), fn(i) { f(i, self[i]) }) -} - -///| -/// Maps a function over the elements of the array view with index in place. -/// -/// # Example -/// ``` -/// let v = [3, 4, 5] -/// v[1:].mapi_inplace(fn (i, x) {x + i}) -/// assert_eq!(v, [3, 4, 6]) -/// ``` -pub fn View::mapi_inplace[T](self : View[T], f : (Int, T) -> T) -> Unit { - for i, v in self { - self[i] = f(i, v) - } -} - -///| -/// Filters the array view with a predicate function. -/// -/// # Example -/// ``` -/// let arr = [1, 2, 3, 4, 5, 6] -/// let v = arr[2:].filter(fn (x) { x % 2 == 0 }) -/// assert_eq!(v, [4, 6]) -/// ``` -pub fn View::filter[T](self : View[T], f : (T) -> Bool) -> Array[T] { - let arr = [] - for v in self { - if f(v) { - arr.push(v) - } - } - arr -} - -///| -pub impl[X : Show] Show for View[X] with output(self, logger) { - logger.write_iter(self.iter()) -} - -///| -pub impl[T : Eq] Eq for View[T] with op_equal(self, other) -> Bool { - if self.length() != other.length() { - return false - } - for i in 0.. Int { - let len_self = self.length() - let len_other = other.length() - if len_self < len_other { - -1 - } else if len_self > len_other { - 1 - } else { - for i in 0.. Unit { } ///| -/// Writes a sequence of bytes from a @bytes.View into the buffer. +/// Writes a sequence of bytes from a BytesView into the buffer. /// /// Parameters: /// /// * `buffer` : The buffer to write to. -/// * `value` : The View containing the bytes to write. +/// * `value` : The BytesView containing the bytes to write. /// /// Example: /// @@ -581,7 +581,7 @@ pub fn write_bytes(self : T, value : Bytes) -> Unit { /// ) /// } /// ``` -pub fn write_bytesview(self : T, value : @bytes.View) -> Unit { +pub fn write_bytesview(self : T, value : BytesView) -> Unit { let val_len = value.length() self.grow_if_necessary(self.len + val_len) self.data.blit_from_bytesview(self.len, value) diff --git a/buffer/buffer.mbti b/buffer/buffer.mbti index dd669e147..81b849506 100644 --- a/buffer/buffer.mbti +++ b/buffer/buffer.mbti @@ -1,7 +1,5 @@ package moonbitlang/core/buffer -alias @moonbitlang/core/bytes as @bytes - // Values fn new(size_hint~ : Int = ..) -> T @@ -18,7 +16,7 @@ impl T { to_unchecked_string(Self) -> String //deprecated write_byte(Self, Byte) -> Unit write_bytes(Self, Bytes) -> Unit - write_bytesview(Self, @bytes.BytesView) -> Unit + write_bytesview(Self, BytesView) -> Unit write_char(Self, Char) -> Unit write_double_be(Self, Double) -> Unit write_double_le(Self, Double) -> Unit diff --git a/buffer/moon.pkg.json b/buffer/moon.pkg.json index 7cc72a25b..40eb88c86 100644 --- a/buffer/moon.pkg.json +++ b/buffer/moon.pkg.json @@ -1,7 +1,3 @@ { - "import": [ - "moonbitlang/core/builtin", - "moonbitlang/core/bytes", - "moonbitlang/core/array" - ] + "import": ["moonbitlang/core/builtin", "moonbitlang/core/bytes"] } diff --git a/builtin/arrayview.mbt b/builtin/arrayview.mbt index 0e5692d27..ca9ebe9d6 100644 --- a/builtin/arrayview.mbt +++ b/builtin/arrayview.mbt @@ -13,17 +13,7 @@ // limitations under the License. ///| -/// An `ArrayView` represents a view into a section of an array without copying the data. -/// -/// # Example -/// -/// ```moonbit -/// let arr = [1, 2, 3, 4, 5] -/// let view = arr[1:4] // Creates a view of elements at indices 1,2,3 -/// assert_eq!(view[0], 2) -/// assert_eq!(view.length(), 3) -/// ``` -/// @alert deprecated "use @array.View instead" +/// A `ArrayView` is a slice of a `Array`. struct ArrayView[T] { buf : UninitializedArray[T] start : Int @@ -312,3 +302,245 @@ pub fn ArrayView::op_as_view[T]( } ArrayView::{ buf: self.buf, start: self.start + start, len: end - start } } + +///| +/// Returns an iterator that yields each element of the array view in sequence +/// from start to end. +/// +/// Parameters: +/// +/// * `array_view` : The array view to iterate over. +/// +/// Returns an iterator that yields elements of type `A` from the array view. +/// +/// Example: +/// +/// ```moonbit +/// test "ArrayView::iter" { +/// let arr = [1, 2, 3] +/// let view = arr[1:] +/// let mut sum = 0 +/// view.iter().each(fn(x) { sum = sum + x }) +/// inspect!(sum, content="5") +/// } +/// ``` +pub fn ArrayView::iter[A](self : ArrayView[A]) -> Iter[A] { + Iter::new(fn(yield_) { + for v in self { + guard let IterContinue = yield_(v) else { x => break x } + + } else { + IterContinue + } + }) +} + +///| +/// Fold out values from an arrayview according to certain rules. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].fold(init=0, fn { sum, elem => sum + elem }) +/// assert_eq!(sum, 15) +/// ``` +pub fn ArrayView::fold[A, B]( + self : ArrayView[A], + init~ : B, + f : (B, A) -> B +) -> B { + for i = 0, acc = init; i < self.length(); { + continue i + 1, f(acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an arrayview according to certain rules in reversed turn. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].rev_fold(init=0, fn { sum, elem => sum + elem }) +/// assert_eq!(sum, 15) +/// ``` +pub fn ArrayView::rev_fold[A, B]( + self : ArrayView[A], + init~ : B, + f : (B, A) -> B +) -> B { + for i = self.length() - 1, acc = init; i >= 0; { + continue i - 1, f(acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an arrayview according to certain rules with index. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].foldi(init=0, fn { index, sum, _elem => sum + index }) +/// assert_eq!(sum, 10) +/// ``` +pub fn ArrayView::foldi[A, B]( + self : ArrayView[A], + init~ : B, + f : (Int, B, A) -> B +) -> B { + for i = 0, acc = init; i < self.length(); { + continue i + 1, f(i, acc, self[i]) + } else { + acc + } +} + +///| +/// Fold out values from an arrayview according to certain rules in reversed turn with index. +/// +/// # Example +/// ``` +/// let sum = [1, 2, 3, 4, 5][:].rev_foldi(init=0, fn { index, sum, _elem => sum + index }) +/// assert_eq!(sum, 10) +/// ``` +pub fn ArrayView::rev_foldi[A, B]( + self : ArrayView[A], + init~ : B, + f : (Int, B, A) -> B +) -> B { + let len = self.length() + for i = len - 1, acc = init; i >= 0; { + continue i - 1, f(len - i - 1, acc, self[i]) + } else { + acc + } +} + +///| +/// Maps a function over the elements of the array view. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// let v2 = v[1:].map(fn (x) {x + 1}) +/// assert_eq!(v2, [5, 6]) +/// ``` +pub fn ArrayView::map[T, U](self : ArrayView[T], f : (T) -> U) -> Array[U] { + if self.length() == 0 { + return [] + } + let arr = Array::make_uninit(self.length()) + for i, v in self { + arr.unsafe_set(i, f(v)) + } + arr +} + +///| +/// Maps a function over the elements of the array view in place. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// v[1:].map_inplace(fn (x) {x + 1}) +/// assert_eq!(v, [3, 5, 6]) +/// ``` +pub fn ArrayView::map_inplace[T](self : ArrayView[T], f : (T) -> T) -> Unit { + for i, v in self { + self[i] = f(v) + } +} + +///| +/// Maps a function over the elements of the array view with index. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// let v2 = v[1:].mapi(fn (i, x) {x + i}) +/// assert_eq!(v2, [4, 6]) +/// ``` +pub fn ArrayView::mapi[T, U]( + self : ArrayView[T], + f : (Int, T) -> U +) -> Array[U] { + if self.length() == 0 { + return [] + } + let arr = Array::make_uninit(self.length()) + for i, v in self { + arr.unsafe_set(i, f(i, v)) + } + arr +} + +///| +/// Maps a function over the elements of the array view with index in place. +/// +/// # Example +/// ``` +/// let v = [3, 4, 5] +/// v[1:].mapi_inplace(fn (i, x) {x + i}) +/// assert_eq!(v, [3, 4, 6]) +/// ``` +pub fn ArrayView::mapi_inplace[T]( + self : ArrayView[T], + f : (Int, T) -> T +) -> Unit { + for i, v in self { + self[i] = f(i, v) + } +} + +///| +/// Filters the array view with a predicate function. +/// +/// # Example +/// ``` +/// let arr = [1, 2, 3, 4, 5, 6] +/// let v = arr[2:].filter(fn (x) { x % 2 == 0 }) +/// assert_eq!(v, [4, 6]) +/// ``` +pub fn ArrayView::filter[T](self : ArrayView[T], f : (T) -> Bool) -> Array[T] { + let arr = [] + for v in self { + if f(v) { + arr.push(v) + } + } + arr +} + +///| +pub impl[T : Eq] Eq for ArrayView[T] with op_equal(self, other) -> Bool { + if self.length() != other.length() { + return false + } + for i in 0.. Int { + let len_self = self.length() + let len_other = other.length() + if len_self < len_other { + -1 + } else if len_self > len_other { + 1 + } else { + for i in 0.. Bool) -> Array[T] + fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B + foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B + iter[A](Self[A]) -> Iter[A] length[T](Self[T]) -> Int + map[T, U](Self[T], (T) -> U) -> Array[U] + map_inplace[T](Self[T], (T) -> T) -> Unit + mapi[T, U](Self[T], (Int, T) -> U) -> Array[U] + mapi_inplace[T](Self[T], (Int, T) -> T) -> Unit op_as_view[T](Self[T], start~ : Int = .., end? : Int) -> Self[T] op_get[T](Self[T], Int) -> T op_set[T](Self[T], Int, T) -> Unit + rev_fold[A, B](Self[A], init~ : B, (B, A) -> B) -> B + rev_foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B swap[T](Self[T], Int, Int) -> Unit to_json[X : ToJson](Self[X]) -> Json unsafe_get[T](Self[T], Int) -> T } +impl[T : Compare] Compare for ArrayView[T] +impl[T : Eq] Eq for ArrayView[T] +impl[X : Show] Show for ArrayView[X] type BigInt impl BigInt { @@ -175,6 +188,28 @@ impl BigInt { } impl Show for BigInt +type BytesView +impl BytesView { + iter(Self) -> Iter[Byte] + length(Self) -> Int + op_as_view(Self, start~ : Int = .., end? : Int) -> Self + op_get(Self, Int) -> Byte + to_double_be(Self) -> Double + to_double_le(Self) -> Double + to_float_be(Self) -> Float + to_float_le(Self) -> Float + to_int64_be(Self) -> Int64 + to_int64_le(Self) -> Int64 + to_int_be(Self) -> Int + to_int_le(Self) -> Int + to_uint64_be(Self) -> UInt64 + to_uint64_le(Self) -> UInt64 + to_uint_be(Self) -> UInt + to_uint_le(Self) -> UInt + unsafe_get(Self, Int) -> Byte +} +impl Show for BytesView + pub(all) type! Failure String impl Show for Failure @@ -659,6 +694,7 @@ impl Result { impl FixedArray { blit_from_bytes(Self[Byte], Int, Bytes, Int, Int) -> Unit + blit_from_bytesview(Self[Byte], Int, BytesView) -> Unit blit_from_string(Self[Byte], Int, String, Int, Int) -> Unit blit_to[A](Self[A], Self[A], len~ : Int, src_offset~ : Int = .., dst_offset~ : Int = ..) -> Unit compare[T : Compare](Self[T], Self[T]) -> Int @@ -690,6 +726,7 @@ impl Bytes { makei(Int, (Int) -> Byte) -> Bytes new(Int) -> Bytes of_string(String) -> Bytes + op_as_view(Bytes, start~ : Int = .., end? : Int) -> BytesView op_equal(Bytes, Bytes) -> Bool op_get(Bytes, Int) -> Byte op_set(Bytes, Int, Byte) -> Unit //deprecated diff --git a/builtin/bytes.mbt b/builtin/bytes.mbt index a8149574d..aeefd9fee 100644 --- a/builtin/bytes.mbt +++ b/builtin/bytes.mbt @@ -221,6 +221,39 @@ pub fn FixedArray::blit_from_bytes( } } +///| +/// Copy bytes from a BytesView into a fixed array of bytes. +/// +/// Parameters: +/// +/// * `self` : The destination fixed array of bytes. +/// * `bytes_offset` : The starting position in the destination array where bytes will be copied. +/// * `src` : The source BytesView to copy from. +/// +/// Throws a panic if: +/// * `bytes_offset` is negative +/// * The destination array is too small to hold all bytes from the source BytesView +/// +/// Example: +/// +/// ```moonbit +/// let arr = FixedArray::make(4, b'\x00') +/// let view = b"\x01\x02\x03"[1:] +/// arr.blit_from_bytesview(1, view) +/// inspect!(arr, content="[b'\\x00', b'\\x02', b'\\x03', b'\\x00']") +/// ``` +pub fn FixedArray::blit_from_bytesview( + self : FixedArray[Byte], + bytes_offset : Int, + src : BytesView +) -> Unit { + let src_len = src.length() + guard bytes_offset >= 0 && bytes_offset + src_len - 1 < self.length() + for i = 0, j = bytes_offset; i < src_len; i = i + 1, j = j + 1 { + self[j] = src[i] + } +} + ///| /// Creates a new byte sequence by copying all bytes from the input sequence. /// diff --git a/bytes/view.mbt b/builtin/bytesview.mbt similarity index 82% rename from bytes/view.mbt rename to builtin/bytesview.mbt index 9af85a881..c49b546f5 100644 --- a/bytes/view.mbt +++ b/builtin/bytesview.mbt @@ -25,28 +25,12 @@ /// assert_eq!(bv[1], b'\x02') /// assert_eq!(bv[2], b'\x03') /// ``` -/// @alert deprecated "use @bytes.View instead" struct BytesView { bytes : Bytes start : Int len : Int } -///| -/// A `@bytes.View` represents a view into a section of a `Bytes` without copying the data. -/// -/// # Example -/// -/// ``` -/// let bs = b"\x00\x01\x02\x03\x04\x05" -/// let bv = bs[1:4] -/// assert_eq!(bv.length(), 3) -/// assert_eq!(bv[0], b'\x01') -/// assert_eq!(bv[1], b'\x02') -/// assert_eq!(bv[2], b'\x03') -/// ``` -pub typealias View = BytesView - ///| /// Returns the number of bytes in the view. /// @@ -59,13 +43,13 @@ pub typealias View = BytesView /// Example: /// /// ```moonbit -/// test "View::length" { +/// test "BytesView::length" { /// let bytes = b"\x00\x01\x02\x03\x04" /// let view = bytes[2:4] /// inspect!(view.length(), content="2") /// } /// ``` -pub fn View::length(self : View) -> Int { +pub fn BytesView::length(self : BytesView) -> Int { self.len } @@ -85,18 +69,18 @@ pub fn View::length(self : View) -> Int { /// Example: /// /// ```moonbit -/// test "View::op_get" { +/// test "BytesView::op_get" { /// let bytes = b"\x01\x02\x03\x04\x05" /// let view = bytes[1:4] // view contains [0x02, 0x03, 0x04] /// inspect!(view[1], content="b'\\x03'") /// } /// -/// test "panic View::op_get/out_of_bounds" { +/// test "panic BytesView::op_get/out_of_bounds" { /// let view = b"\x01\x02\x03"[:] /// ignore(view[3]) // Index out of bounds /// } /// ``` -pub fn View::op_get(self : View, index : Int) -> Byte { +pub fn BytesView::op_get(self : BytesView, index : Int) -> Byte { guard index >= 0 && index < self.len else { abort( "index out of bounds: the len is from 0 to \{self.len} but the index is \{index}", @@ -123,25 +107,25 @@ pub fn View::op_get(self : View, index : Int) -> Byte { /// Example: /// /// ```moonbit -/// test "View::unsafe_get" { +/// test "BytesView::unsafe_get" { /// let bytes = b"\x01\x02\x03\x04\x05" /// let view = bytes[2:4] // view contains [0x03, 0x04] /// inspect!(view.unsafe_get(0), content="b'\\x03'") /// } /// -/// test "panic View::unsafe_get/out_of_bounds" { +/// test "panic BytesView::unsafe_get/out_of_bounds" { /// let view = b"\x01\x02\x03"[:] /// ignore(view.unsafe_get(3)) // Panic: index out of bounds /// } /// ``` /// /// @alert unsafe "Panic if index is out of bounds" -pub fn View::unsafe_get(self : View, index : Int) -> Byte { +pub fn BytesView::unsafe_get(self : BytesView, index : Int) -> Byte { self.bytes[self.start + index] } ///| -/// Creates a new `View` from the given `Bytes`. +/// Creates a new `BytesView` from the given `Bytes`. /// /// # Example /// @@ -153,7 +137,11 @@ pub fn View::unsafe_get(self : View, index : Int) -> Byte { /// assert_eq!(bv[1], b'\x02') /// assert_eq!(bv[2], b'\x03') /// ``` -pub fn Bytes::op_as_view(self : Bytes, start~ : Int = 0, end? : Int) -> View { +pub fn Bytes::op_as_view( + self : Bytes, + start~ : Int = 0, + end? : Int +) -> BytesView { let len = self.length() let end = match end { None => len @@ -161,13 +149,13 @@ pub fn Bytes::op_as_view(self : Bytes, start~ : Int = 0, end? : Int) -> View { } let start = if start < 0 { len + start } else { start } guard start >= 0 && start <= end && end <= len else { - abort("Invalid index for View") + abort("Invalid index for BytesView") } - View::{ bytes: self, start, len: end - start } + BytesView::{ bytes: self, start, len: end - start } } ///| -/// Creates a new `View` from the given `View`. +/// Creates a new `BytesView` from the given `BytesView`. /// /// # Example /// @@ -177,7 +165,11 @@ pub fn Bytes::op_as_view(self : Bytes, start~ : Int = 0, end? : Int) -> View { /// assert_eq!(bv2.length(), 3) /// assert_eq!(bv2[1], b'\x02') /// ``` -pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { +pub fn BytesView::op_as_view( + self : BytesView, + start~ : Int = 0, + end? : Int +) -> BytesView { let len = self.length() let end = match end { None => len @@ -185,13 +177,13 @@ pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { } let start = if start < 0 { len + start } else { start } guard start >= 0 && start <= end && end <= len else { - abort("Invalid index for View") + abort("Invalid index for BytesView") } - View::{ bytes: self.bytes, start: self.start + start, len: end - start } + BytesView::{ bytes: self.bytes, start: self.start + start, len: end - start } } ///| -/// Returns an iterator over the `View`. +/// Returns an iterator over the `BytesView`. /// /// # Example /// @@ -201,7 +193,7 @@ pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { /// bv.iter().each(fn(x) { sum = sum + x.to_int() }) /// assert_eq!(sum, 15) /// ``` -pub fn View::iter(self : View) -> Iter[Byte] { +pub fn BytesView::iter(self : BytesView) -> Iter[Byte] { Iter::new(fn(yield_) { for i in 0.. break x } @@ -226,17 +218,17 @@ pub fn View::iter(self : View) -> Iter[Byte] { /// Example: /// /// ```moonbit -/// test "View::to_uint_be" { +/// test "BytesView::to_uint_be" { /// let bytes = b"\x12\x34\x56\x78"[:] /// inspect!(bytes.to_uint_be(), content="305419896") // 0x12345678 /// } /// -/// test "panic View::to_uint_be/out_of_bounds" { +/// test "panic BytesView::to_uint_be/out_of_bounds" { /// let bytes = b"\x12\x34\x56"[:] // Less than 4 bytes /// ignore(bytes.to_uint_be()) // Panics with index out of bounds /// } /// ``` -pub fn View::to_uint_be(self : View) -> UInt { +pub fn BytesView::to_uint_be(self : BytesView) -> UInt { (self[0].to_uint() << 24) + (self[1].to_uint() << 16) + (self[2].to_uint() << 8) + @@ -250,7 +242,7 @@ pub fn View::to_uint_be(self : View) -> UInt { /// /// Parameters: /// -/// * `view` : A `View` containing exactly 4 bytes to be interpreted as a +/// * `view` : A `BytesView` containing exactly 4 bytes to be interpreted as a /// little-endian unsigned integer. /// /// Returns an unsigned 32-bit integer (`UInt`) formed by interpreting the bytes @@ -261,13 +253,13 @@ pub fn View::to_uint_be(self : View) -> UInt { /// Example: /// /// ```moonbit -/// test "View::to_uint_le" { +/// test "BytesView::to_uint_le" { /// let bytes = b"\x01\x02\x03\x04" /// let view = bytes[:] /// inspect!(view.to_uint_le(), content="67305985") // 0x04030201 /// } /// ``` -pub fn View::to_uint_le(self : View) -> UInt { +pub fn BytesView::to_uint_le(self : BytesView) -> UInt { self[0].to_uint() + (self[1].to_uint() << 8) + (self[2].to_uint() << 16) + @@ -294,17 +286,17 @@ pub fn View::to_uint_le(self : View) -> UInt { /// Example: /// /// ```moonbit -/// test "View::to_uint64_be" { +/// test "BytesView::to_uint64_be" { /// let bytes = b"\x01\x23\x45\x67\x89\xAB\xCD\xEF"[:] /// inspect!(bytes.to_uint64_be(), content="81985529216486895") /// } /// -/// test "panic View::to_uint64_be/short_input" { +/// test "panic BytesView::to_uint64_be/short_input" { /// let bytes = b"\x01\x02\x03"[:] /// ignore(bytes.to_uint64_be()) // Throws error: index out of bounds /// } /// ``` -pub fn View::to_uint64_be(self : View) -> UInt64 { +pub fn BytesView::to_uint64_be(self : BytesView) -> UInt64 { (self[0].to_uint().to_uint64() << 56) + (self[1].to_uint().to_uint64() << 48) + (self[2].to_uint().to_uint64() << 40) + @@ -330,23 +322,23 @@ pub fn View::to_uint64_be(self : View) -> UInt64 { /// Returns an unsigned 64-bit integer assembled from the bytes in little-endian /// order. /// -/// Throws a panic if the View is less than 8 bytes long or if trying to +/// Throws a panic if the BytesView is less than 8 bytes long or if trying to /// access a byte beyond the view's bounds. /// /// Example: /// /// ```moonbit -/// test "View::to_uint64_le" { +/// test "BytesView::to_uint64_le" { /// let bytes = b"\x01\x02\x03\x04\x05\x06\x07\x08"[:] /// inspect!(bytes.to_uint64_le(), content="578437695752307201") /// } /// -/// test "panic View::to_uint64_le/short_view" { +/// test "panic BytesView::to_uint64_le/short_view" { /// let bytes = b"\x01\x02\x03"[:] /// ignore(bytes.to_uint64_le()) // Panics: view is too short /// } /// ``` -pub fn View::to_uint64_le(self : View) -> UInt64 { +pub fn BytesView::to_uint64_le(self : BytesView) -> UInt64 { self[0].to_uint().to_uint64() + (self[1].to_uint().to_uint64() << 8) + (self[2].to_uint().to_uint64() << 16) + @@ -365,7 +357,7 @@ pub fn View::to_uint64_le(self : View) -> UInt64 { /// /// Parameters: /// -/// * `View` : A view into a byte sequence that must be exactly 4 bytes +/// * `bytesView` : A view into a byte sequence that must be exactly 4 bytes /// long. The bytes are interpreted in big-endian order, where the first byte is /// the most significant byte and the last byte is the least significant byte. /// @@ -375,12 +367,12 @@ pub fn View::to_uint64_le(self : View) -> UInt64 { /// Example: /// /// ```moonbit -/// test "View::to_int_be" { +/// test "BytesView::to_int_be" { /// let bytes = b"\x80\x00\x00\x00"[:] // Represents -2147483648 in two's complement /// inspect!(bytes.to_int_be(), content="-2147483648") /// } /// ``` -pub fn View::to_int_be(self : View) -> Int { +pub fn BytesView::to_int_be(self : BytesView) -> Int { self.to_uint_be().reinterpret_as_int() } @@ -402,13 +394,13 @@ pub fn View::to_int_be(self : View) -> Int { /// Example: /// /// ```moonbit -/// test "View::to_int_le" { +/// test "BytesView::to_int_le" { /// let bytes = b"\x78\x56\x34\x12" /// let view = bytes[:] /// inspect!(view.to_int_le(), content="305419896") // 0x12345678 in decimal /// } /// ``` -pub fn View::to_int_le(self : View) -> Int { +pub fn BytesView::to_int_le(self : BytesView) -> Int { self.to_uint_le().reinterpret_as_int() } @@ -427,12 +419,12 @@ pub fn View::to_int_le(self : View) -> Int { /// Example: /// /// ```moonbit -/// test "View::to_int64_be" { +/// test "BytesView::to_int64_be" { /// let bytes = b"\x80\x00\x00\x00\x00\x00\x00\x00"[:] // Most negative 64-bit integer /// inspect!(bytes.to_int64_be(), content="-9223372036854775808") /// } /// ``` -pub fn View::to_int64_be(self : View) -> Int64 { +pub fn BytesView::to_int64_be(self : BytesView) -> Int64 { self.to_uint64_be().reinterpret_as_int64() } @@ -452,13 +444,13 @@ pub fn View::to_int64_be(self : View) -> Int64 { /// Example: /// /// ```moonbit -/// test "View::to_int64_le" { +/// test "BytesView::to_int64_le" { /// let bytes = b"\x01\x02\x03\x04\x05\x06\x07\x08" /// let view = bytes[:] /// inspect!(view.to_int64_le(), content="578437695752307201") /// } /// ``` -pub fn View::to_int64_le(self : View) -> Int64 { +pub fn BytesView::to_int64_le(self : BytesView) -> Int64 { self.to_uint64_le().reinterpret_as_int64() } @@ -478,7 +470,7 @@ pub fn View::to_int64_le(self : View) -> Int64 { /// Example: /// /// ```moonbit -/// test "View::to_float_be" { +/// test "BytesView::to_float_be" { /// let bytes = b"\x40\x48\xF5\xC3" // Represents 3.14 in IEEE 754 format /// let view = bytes[:] /// let float = view.to_float_be() @@ -486,7 +478,7 @@ pub fn View::to_int64_le(self : View) -> Int64 { /// inspect!(float.to_double(), content="3.140000104904175") /// } /// ``` -pub fn View::to_float_be(self : View) -> Float { +pub fn BytesView::to_float_be(self : BytesView) -> Float { self.to_uint_be().reinterpret_as_float() } @@ -504,13 +496,13 @@ pub fn View::to_float_be(self : View) -> Float { /// Example: /// /// ```moonbit -/// test "View::to_float_le" { +/// test "BytesView::to_float_le" { /// let bytes = b"\x00\x00\x80\x3F" // Represents 1.0 in little-endian IEEE-754 /// let f = bytes[:].to_float_le() /// inspect!(f.to_double(), content="1") /// } /// ``` -pub fn View::to_float_le(self : View) -> Float { +pub fn BytesView::to_float_le(self : BytesView) -> Float { self.to_uint_le().reinterpret_as_float() } @@ -530,14 +522,14 @@ pub fn View::to_float_le(self : View) -> Float { /// Example: /// /// ```moonbit -/// test "View::to_double_be" { +/// test "BytesView::to_double_be" { /// // Bytes representing 1.0 in IEEE 754 double-precision format (big-endian) /// let bytes = b"\x3F\xF0\x00\x00\x00\x00\x00\x00" /// let view = bytes[:] /// inspect!(view.to_double_be(), content="1") /// } /// ``` -pub fn View::to_double_be(self : View) -> Double { +pub fn BytesView::to_double_be(self : BytesView) -> Double { self.to_uint64_be().reinterpret_as_double() } @@ -556,34 +548,12 @@ pub fn View::to_double_be(self : View) -> Double { /// Example: /// /// ```moonbit -/// test "View::to_double_le" { +/// test "BytesView::to_double_le" { /// let bytes = b"\x00\x00\x00\x00\x00\x00\xF0\x3F" // represents 1.0 in little-endian /// let view = bytes[:] /// inspect!(view.to_double_le(), content="1") /// } /// ``` -pub fn View::to_double_le(self : View) -> Double { +pub fn BytesView::to_double_le(self : BytesView) -> Double { self.to_uint64_le().reinterpret_as_double() } - -///| -pub impl Show for View with output(self, logger) { - fn to_hex_digit(i : Int) -> Char { - if i < 10 { - Char::from_int('0'.to_int() + i) - } else { - Char::from_int('a'.to_int() + (i - 10)) - } - } - - logger.write_string("b\"") - for i in 0.. ignore - } - logger.write_string("\"") -} diff --git a/bytes/view_test.mbt b/builtin/bytesview_test.mbt similarity index 90% rename from bytes/view_test.mbt rename to builtin/bytesview_test.mbt index afa99ca68..0c8401861 100644 --- a/bytes/view_test.mbt +++ b/builtin/bytesview_test.mbt @@ -291,7 +291,7 @@ test "panic negative index2" { } -test "View::unsafe_get additional test" { +test "BytesView::unsafe_get additional test" { let bytes = b"\x01\x02\x03\x04\x05" let view = bytes[1:4] // view contains [0x02, 0x03, 0x04] let result = view.unsafe_get(1) // gets byte at index 1 (the second byte) of the view @@ -303,26 +303,26 @@ test "to_uint_be with b'\\xFF\\xFF\\xFF\\xFF'" { inspect!(bytes.to_uint_be(), content="4294967295") } -test "View::to_uint_le with non-zero bytes" { +test "BytesView::to_uint_le with non-zero bytes" { let bytes = b"\x01\x02\x03\x04" let view = bytes[:] inspect!(view.to_uint_le(), content="67305985") // 67305985 = 0x04030201 } -test "panic View::to_uint_le/out_of_bounds" { +test "panic BytesView::to_uint_le/out_of_bounds" { let bytes = b"\x01\x02\x03" // Only 3 bytes let view = bytes[:] ignore(view.to_uint_le()) // Should panic: index out of bounds } -test "View::to_uint64_be/first_byte_operation" { +test "BytesView::to_uint64_be/first_byte_operation" { let bytes = b"\xFF\x00\x00\x00\x00\x00\x00\x00"[:] // First byte is all 1s let result = bytes.to_uint64_be() // First byte shifted left by 56 bits should give us: 0xFF00000000000000 inspect!(result, content="18374686479671623680") } -test "test View::to_uint64_le with binary pattern" { +test "test BytesView::to_uint64_le with binary pattern" { let bytes = b"\x01\x00\x00\x00\x00\x00\x00\x00"[:] inspect!(bytes.to_uint64_le(), content="1") let bytes2 = b"\x00\x01\x00\x00\x00\x00\x00\x00"[:] @@ -333,12 +333,12 @@ test "test View::to_uint64_le with binary pattern" { inspect!(bytes3.to_uint64_le(), content="578437695752307201") } -test "test View::to_int_le with a non-zero 32-bit number" { +test "test BytesView::to_int_le with a non-zero 32-bit number" { let bytes = b"\x78\x56\x34\x12"[:] inspect!(bytes.to_int_le(), content="305419896") } -test "View::to_int64_be test cases" { +test "BytesView::to_int64_be test cases" { // Test positive number let bytes = b"\x00\x00\x00\x00\x00\x00\x00\x01" inspect!(bytes[:].to_int64_be(), content="1") @@ -352,7 +352,7 @@ test "View::to_int64_be test cases" { inspect!(bytes3[:].to_int64_be(), content="9223372036854775807") } -test "View::to_int64_le with mixed bytes" { +test "BytesView::to_int64_le with mixed bytes" { // Test with bytes containing both negative and positive values let bytes = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" let view = bytes[:] @@ -363,10 +363,10 @@ test "panic to_float_be/short_input" { // Test that trying to read from a view that's too short causes a panic let bytes = b"\x40\x49" let view = bytes[:] - ignore(View::to_float_be(view)) // Should panic due to insufficient bytes + ignore(@builtin.BytesView::to_float_be(view)) // Should panic due to insufficient bytes } -test "View::to_float_le with different values" { +test "BytesView::to_float_le with different values" { // Test with value 0.0 let bytes = b"\x00\x00\x00\x00" let f = bytes[:].to_float_le() @@ -378,7 +378,7 @@ test "View::to_float_le with different values" { inspect!(f2.to_double(), content="-1") } -test "View::to_double_be/zero" { +test "BytesView::to_double_be/zero" { let bytes = b"\x00\x00\x00\x00\x00\x00\x00\x00" let view = bytes[:] inspect!(view.to_double_be(), content="0") @@ -406,22 +406,7 @@ test "iter break early" { inspect!(total, content="3") // \x01 + \x02 = 3 } -test "View::to_int_be with positive value" { +test "BytesView::to_int_be with positive value" { let bytes = b"\x00\x00\x00\x01"[:] // Represents 1 in big-endian inspect!(bytes.to_int_be(), content="1") } - -test "Show for View" { - inspect!( - b"abcdefg"[1:5].to_string(), - content= - #|b"\x62\x63\x64\x65" - , - ) - inspect!( - b"\x00\xff\x63"[:].to_string(), - content= - #|b"\x00\xff\x63" - , - ) -} diff --git a/builtin/show.mbt b/builtin/show.mbt index 2846ace84..2dacf848f 100644 --- a/builtin/show.mbt +++ b/builtin/show.mbt @@ -77,6 +77,28 @@ pub impl Show for Bytes with output(self, logger) { logger.write_string("\"") } +///| +pub impl Show for BytesView with output(self, logger) { + fn to_hex_digit(i : Int) -> Char { + if i < 10 { + Char::from_int('0'.to_int() + i) + } else { + Char::from_int('a'.to_int() + (i - 10)) + } + } + + logger.write_string("b\"") + for i in 0.. ignore + } + logger.write_string("\"") +} + ///| pub impl Show for String with output(self, logger) { logger.write_char('"') @@ -186,6 +208,11 @@ pub impl[X : Show] Show for Array[X] with output(self, logger) { logger.write_iter(self.iter()) } +///| +pub impl[X : Show] Show for ArrayView[X] with output(self, logger) { + logger.write_iter(self.iter()) +} + ///| /// Convert Char to String /// @intrinsic %char.to_string diff --git a/builtin/show_test.mbt b/builtin/show_test.mbt index 83e34c381..3bd9cf1e3 100644 --- a/builtin/show_test.mbt +++ b/builtin/show_test.mbt @@ -71,6 +71,21 @@ test "Show for Bytes" { ) } +test "Show for BytesView" { + inspect!( + b"abcdefg"[1:5].to_string(), + content= + #|b"\x62\x63\x64\x65" + , + ) + inspect!( + b"\x00\xff\x63"[:].to_string(), + content= + #|b"\x00\xff\x63" + , + ) +} + test "Show for String" { fn to_string_using_output(str) { let buf = StringBuilder::new() diff --git a/bytes/bytes.mbti b/bytes/bytes.mbti index 76f7928ac..e0d873f1a 100644 --- a/bytes/bytes.mbti +++ b/bytes/bytes.mbti @@ -12,28 +12,6 @@ fn from_iter(Iter[Byte]) -> Bytes fn of(FixedArray[Byte]) -> Bytes // Types and methods -type BytesView //deprecated -impl BytesView { - iter(Self) -> Iter[Byte] - length(Self) -> Int - op_as_view(Self, start~ : Int = .., end? : Int) -> Self - op_get(Self, Int) -> Byte - to_double_be(Self) -> Double - to_double_le(Self) -> Double - to_float_be(Self) -> Float - to_float_le(Self) -> Float - to_int64_be(Self) -> Int64 - to_int64_le(Self) -> Int64 - to_int_be(Self) -> Int - to_int_le(Self) -> Int - to_uint64_be(Self) -> UInt64 - to_uint64_le(Self) -> UInt64 - to_uint_be(Self) -> UInt - to_uint_le(Self) -> UInt - unsafe_get(Self, Int) -> Byte -} -impl Show for BytesView - impl Bytes { default() -> Bytes from_array(Array[Byte]) -> Bytes @@ -41,14 +19,12 @@ impl Bytes { from_iter(Iter[Byte]) -> Bytes iter(Bytes) -> Iter[Byte] of(FixedArray[Byte]) -> Bytes - op_as_view(Bytes, start~ : Int = .., end? : Int) -> BytesView to_array(Bytes) -> Array[Byte] to_fixedarray(Bytes, len? : Int) -> FixedArray[Byte] } impl Hash for Bytes // Type aliases -pub typealias View = BytesView // Traits diff --git a/bytes/moon.pkg.json b/bytes/moon.pkg.json index 993c140c3..e4b88edc7 100644 --- a/bytes/moon.pkg.json +++ b/bytes/moon.pkg.json @@ -1,4 +1,4 @@ { "import": ["moonbitlang/core/builtin"], - "test-import": ["moonbitlang/core/array", "moonbitlang/core/double"] + "test-import": ["moonbitlang/core/array"] } diff --git a/queue/queue.mbt b/queue/queue.mbt index a2d826c74..234d5ccae 100644 --- a/queue/queue.mbt +++ b/queue/queue.mbt @@ -461,3 +461,15 @@ pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[X] with arbitrar ) { @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter } + +test "queue arbitrary" { + let samples : Array[T[Int]] = @quickcheck.samples(20) + inspect!( + samples[1:5], + content="[@queue.of([]), @queue.of([0]), @queue.of([0]), @queue.of([0])]", + ) + inspect!( + samples[15], + content="@queue.of([0, 0, 0, 0, 0, -1, -3, -3, -1, -4, 5, -1])", + ) +} diff --git a/queue/queue_test.mbt b/queue/queue_test.mbt index 6dbd095a5..2d35d92c9 100644 --- a/queue/queue_test.mbt +++ b/queue/queue_test.mbt @@ -183,15 +183,3 @@ test "to_string" { let queue : @queue.T[Int] = @queue.from_array([9, 8, 7, 5]) assert_eq!(queue.to_string(), "@queue.of([9, 8, 7, 5])") } - -test "queue arbitrary" { - let samples : Array[T[Int]] = @quickcheck.samples(20) - inspect!( - samples[1:5], - content="[@queue.of([]), @queue.of([0]), @queue.of([0]), @queue.of([0])]", - ) - inspect!( - samples[15], - content="@queue.of([0, 0, 0, 0, 0, -1, -3, -3, -1, -4, 5, -1])", - ) -} diff --git a/quickcheck/arbitrary.mbt b/quickcheck/arbitrary.mbt index 1201aff4d..f086fd53d 100644 --- a/quickcheck/arbitrary.mbt +++ b/quickcheck/arbitrary.mbt @@ -121,6 +121,14 @@ pub impl[X : Arbitrary] Arbitrary for Iter[X] with arbitrary(size, rs) { }) } +test "iter arbitrary" { + let samples : Array[Iter[Int]] = samples(20) + inspect!("[0, 0, 0, 1, 2, -2]", content="[0, 0, 0, 1, 2, -2]") + inspect!(samples[1:5], content="[[], [0], [0], [0]]") + // inspect!(samples[9], content="[0, 0, 0, 1, 2, -2]") (Cause infinite loop?) + inspect!(samples[10], content="[0, 0, 0]") +} + ///| pub fn gen[T : Arbitrary](size? : Int, state? : @splitmix.RandomState) -> T { let size = match size { diff --git a/quickcheck/arbitrary_test.mbt b/quickcheck/arbitrary_test.mbt index 36cd16a50..c99c9a3e5 100644 --- a/quickcheck/arbitrary_test.mbt +++ b/quickcheck/arbitrary_test.mbt @@ -45,11 +45,3 @@ test "gen with default parameters" { let x : Bool = @quickcheck.gen() inspect!(x, content="true") } - -test "iter arbitrary" { - let samples : Array[Iter[Int]] = samples(20) - inspect!("[0, 0, 0, 1, 2, -2]", content="[0, 0, 0, 1, 2, -2]") - inspect!(samples[1:5], content="[[], [0], [0], [0]]") - // inspect!(samples[9], content="[0, 0, 0, 1, 2, -2]") (Cause infinite loop?) - inspect!(samples[10], content="[0, 0, 0]") -} diff --git a/quickcheck/moon.pkg.json b/quickcheck/moon.pkg.json index 6af6c865f..53eeb0cf5 100644 --- a/quickcheck/moon.pkg.json +++ b/quickcheck/moon.pkg.json @@ -1,7 +1,3 @@ { - "import": [ - "moonbitlang/core/quickcheck/splitmix", - "moonbitlang/core/builtin" - ], - "test-import": ["moonbitlang/core/array"] + "import": ["moonbitlang/core/quickcheck/splitmix", "moonbitlang/core/builtin"] } diff --git a/rational/moon.pkg.json b/rational/moon.pkg.json index d7c190055..cc55d2281 100644 --- a/rational/moon.pkg.json +++ b/rational/moon.pkg.json @@ -5,6 +5,5 @@ "moonbitlang/core/double", "moonbitlang/core/int64", "moonbitlang/core/quickcheck" - ], - "test-import": ["moonbitlang/core/array"] + ] } diff --git a/strconv/decimal.mbt b/strconv/decimal.mbt index c3da3a54c..3b1f11e4d 100644 --- a/strconv/decimal.mbt +++ b/strconv/decimal.mbt @@ -64,7 +64,7 @@ pub fn parse_decimal(str : String) -> Decimal!StrConvError { } ///| -fn parse_decimal_from_view(str : @string.View) -> Decimal!StrConvError { +fn parse_decimal_from_view(str : @string.StringView) -> Decimal!StrConvError { let d = Decimal::new() let mut has_dp = false let mut has_digits = false diff --git a/string/string.mbti b/string/string.mbti index 7a4590b64..d789dabb9 100644 --- a/string/string.mbti +++ b/string/string.mbti @@ -71,7 +71,6 @@ impl String { } // Type aliases -pub typealias View = StringView // Traits diff --git a/string/view.mbt b/string/view.mbt index a8365f152..986865686 100644 --- a/string/view.mbt +++ b/string/view.mbt @@ -16,7 +16,6 @@ /// A `StringView` represents a view of a String that maintains proper Unicode /// character boundaries. It allows safe access to a substring while handling /// multi-byte characters correctly. -/// alert deprecated "use @string.View instead" struct StringView { // # Fields // @@ -31,12 +30,6 @@ struct StringView { end : Int } -///| -/// A `@string.View` represents a view of a String that maintains proper Unicode -/// character boundaries. It allows safe access to a substring while handling -/// multi-byte characters correctly. -pub typealias View = StringView - ///| /// A `StringIndex` represents an unicode-aware position within a string. /// @@ -158,7 +151,7 @@ pub fn index_at_rev( /// /// Note this has O(n) complexity where n is the length of the code points in /// the view. -pub fn View::length(self : View) -> Int { +pub fn StringView::length(self : StringView) -> Int { let mut len = 0 for index = self.start; index < self.end; index = index + 1 { let c1 = self.str.unsafe_charcode_at(index) @@ -180,7 +173,7 @@ pub fn View::length(self : View) -> Int { /// Test if the length of the view is equal to the given length. /// /// This has O(n) complexity where n is the length in the parameter. -pub fn length_eq(self : View, len : Int) -> Bool { +pub fn length_eq(self : StringView, len : Int) -> Bool { for index = self.start, self_len = 0 index < self.end && self_len < len index = index + 1, self_len = self_len + 1 { @@ -202,7 +195,7 @@ pub fn length_eq(self : View, len : Int) -> Bool { /// Test if the length of the view is greater than or equal to the given length. /// /// This has O(n) complexity where n is the length in the parameter. -pub fn length_ge(self : View, len : Int) -> Bool { +pub fn length_ge(self : StringView, len : Int) -> Bool { for index = self.start, self_len = 0 index < self.end && self_len < len index = index + 1, self_len = self_len + 1 { @@ -221,7 +214,7 @@ pub fn length_ge(self : View, len : Int) -> Bool { } ///| -/// Creates a `View` into a `String`. +/// Creates a `StringView` into a `String`. /// /// # Example /// @@ -232,7 +225,11 @@ pub fn length_ge(self : View, len : Int) -> Bool { /// #|"ello🤣" ///) /// ``` -pub fn String::op_as_view(self : String, start~ : Int = 0, end? : Int) -> View { +pub fn String::op_as_view( + self : String, + start~ : Int = 0, + end? : Int +) -> StringView { let str_len = self.charcode_length() let start = if start >= 0 { guard let Some(start_offset) = index_at(self, start, start=0) else { @@ -261,13 +258,13 @@ pub fn String::op_as_view(self : String, start~ : Int = 0, end? : Int) -> View { None => str_len } guard start >= 0 && start <= end && end <= str_len else { - abort("Invalid index for View") + abort("Invalid index for StringView") } { str: self, start, end } } ///| -/// Creates a new `View` from an existing `View`. +/// Creates a new `StringView` from an existing `StringView`. /// /// # Example /// @@ -279,7 +276,11 @@ pub fn String::op_as_view(self : String, start~ : Int = 0, end? : Int) -> View { /// #|"llo🤣" /// ) /// ``` -pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { +pub fn StringView::op_as_view( + self : StringView, + start~ : Int = 0, + end? : Int +) -> StringView { let start = if start >= 0 { guard let Some(start_offset) = index_at(self.str, start, start=self.start) else { _ => abort("Invalid start index") @@ -311,7 +312,7 @@ pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { end >= self.start && end <= self.end && start <= end else { - abort("Invalid index for View") + abort("Invalid index for StringView") } { str: self.str, start, end } } @@ -330,7 +331,7 @@ pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View { /// inspect!(view[0], content="'e'") /// inspect!(view[4], content="'🤣'") /// ``` -pub fn View::op_get(self : View, index : Int) -> Char { +pub fn StringView::op_get(self : StringView, index : Int) -> Char { guard index >= 0 else { abort("Index out of bounds: cannot access negative index") } @@ -382,7 +383,7 @@ pub fn View::op_get(self : View, index : Int) -> Char { /// inspect!(view.rev_get(0), content="'🤣'") /// inspect!(view.rev_get(4), content="'e'") /// ``` -pub fn rev_get(self : View, index : Int) -> Char { +pub fn rev_get(self : StringView, index : Int) -> Char { guard index >= 0 else { abort("Index out of bounds: cannot access negative index") } @@ -420,14 +421,14 @@ pub fn rev_get(self : View, index : Int) -> Char { } ///| -pub impl Show for View with output(self, logger) { +pub impl Show for StringView with output(self, logger) { let substr = self.str.substring(start=self.start, end=self.end) String::output(substr, logger) } ///| /// Returns an iterator over the Unicode characters in the string view. -pub fn View::iter(self : View) -> Iter[Char] { +pub fn StringView::iter(self : StringView) -> Iter[Char] { Iter::new(fn(yield_) { for index = self.start; index < self.end; index = index + 1 { let c1 = self.str.unsafe_charcode_at(index) From 719f09847238bbd23e6bc8d2ad2945b642b9bad8 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Mon, 27 Jan 2025 10:59:31 +0800 Subject: [PATCH 7/8] add view pattern test --- bytes/view_pattern_test.mbt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 bytes/view_pattern_test.mbt diff --git a/bytes/view_pattern_test.mbt b/bytes/view_pattern_test.mbt new file mode 100644 index 000000000..fe5c67bd2 --- /dev/null +++ b/bytes/view_pattern_test.mbt @@ -0,0 +1,24 @@ +// 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. + + +test "View::pattern" { + let view = b"\x01\x02\x03"[:] + match view { + [0x01, 0x02, ..rest] => { + inspect!(rest, content="b\"\\x03\"") + } + _ => abort("should not happen") + } +} From 4a6e310110a51e060e968a44e81baa8b259d1239 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Mon, 27 Jan 2025 11:01:54 +0800 Subject: [PATCH 8/8] refactor: update view pattern test syntax --- bytes/view_pattern_test.mbt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bytes/view_pattern_test.mbt b/bytes/view_pattern_test.mbt index fe5c67bd2..7941e0737 100644 --- a/bytes/view_pattern_test.mbt +++ b/bytes/view_pattern_test.mbt @@ -12,13 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. - test "View::pattern" { let view = b"\x01\x02\x03"[:] match view { - [0x01, 0x02, ..rest] => { - inspect!(rest, content="b\"\\x03\"") - } + [0x01, 0x02, .. rest] => inspect!(rest, content="b\"\\x03\"") _ => abort("should not happen") } }