Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions builtin/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -798,9 +798,7 @@ pub fn[T] Array::rev(self : Array[T]) -> Array[T] {
pub fn[T] Array::split_at(self : Array[T], index : Int) -> (Array[T], Array[T]) {
if index < 0 || index > self.length() {
let len = self.length()
abort(
"index out of bounds: the len is from 0 to \{len} but the index is \{index}",
)
abort(out_of_index(len, index))
}
let v1 = Array::make_uninit(index)
let v2 = Array::make_uninit(self.length() - index)
Expand Down Expand Up @@ -1125,10 +1123,7 @@ pub fn[T] Array::binary_search_by(
/// ```
pub fn[T] Array::swap(self : Array[T], i : Int, j : Int) -> Unit {
if i >= self.length() || j >= self.length() || i < 0 || j < 0 {
let len = self.length()
abort(
"index out of bounds: the len is from 0 to \{len} but the index is (\{i}, \{j})",
)
abort(out_of_index(self.length(), i, index2=j))
}
let temp = self.unsafe_get(i)
self.unsafe_set(i, self.unsafe_get(j))
Expand Down
12 changes: 3 additions & 9 deletions builtin/arraycore_js.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,7 @@ pub fn[T] Array::unsafe_pop(self : Array[T]) -> T {
/// ```
pub fn[T] Array::remove(self : Array[T], index : Int) -> T {
guard index >= 0 && index < self.length() else {
abort(
"index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}",
)
abort(out_of_index(self.length(), index))
}
let value = self.buffer()[index]
let _ = JSArray::ofAnyArray(self).splice(index, 1)
Expand All @@ -275,9 +273,7 @@ pub fn[T] Array::remove(self : Array[T], index : Int) -> T {
/// ```
pub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] {
guard begin >= 0 && end <= self.length() && begin <= end else {
abort(
"index out of bounds: the len is \{self.length()} but the index is (\{begin}, \{end})",
)
abort(out_of_index(self.length(), begin, index2=end))
}
JSArray::ofAnyArray(self).splice(begin, end - begin).toAnyArray()
}
Expand All @@ -295,9 +291,7 @@ pub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] {
/// ```
pub fn[T] Array::insert(self : Array[T], index : Int, value : T) -> Unit {
guard index >= 0 && index <= self.length() else {
abort(
"index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}",
)
abort(out_of_index(self.length(), index))
}
let _ = JSArray::ofAnyArray(self).splice1(index, 0, JSValue::ofAny(value))
}
Expand Down
8 changes: 2 additions & 6 deletions builtin/arraycore_nonjs.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,7 @@ pub fn[T] Array::unsafe_pop(self : Array[T]) -> T {
/// ```
pub fn[T] Array::remove(self : Array[T], index : Int) -> T {
guard index >= 0 && index < self.length() else {
abort(
"index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}",
)
abort(out_of_index(self.length(), index))
}
let value = self.unsafe_get(index)
UninitializedArray::unsafe_blit(
Expand Down Expand Up @@ -388,9 +386,7 @@ pub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] {
/// ```
pub fn[T] Array::insert(self : Array[T], index : Int, value : T) -> Unit {
guard index >= 0 && index <= self.length() else {
abort(
"index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}",
)
abort(out_of_index(self.length(), index))
}
if self.length() == self.buffer().0.length() {
self.realloc()
Expand Down
4 changes: 1 addition & 3 deletions builtin/arrayview.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ pub fn[T] ArrayView::start_offset(self : Self[T]) -> Int {
#alias("_[_]")
pub fn[T] ArrayView::at(self : ArrayView[T], index : Int) -> T {
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}",
)
abort(out_of_index(self.len(), index))
}
self.buf()[self.start() + index]
}
Expand Down
4 changes: 1 addition & 3 deletions builtin/bytesview.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ pub fn BytesView::is_empty(self : BytesView) -> Bool {
#alias("_[_]")
pub fn BytesView::at(self : BytesView, index : Int) -> Byte {
guard index >= 0 && index < self.length() else {
abort(
"index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}",
)
abort(out_of_index(self.length(), index))
}
self.bytes()[self.start() + index]
}
Expand Down
37 changes: 30 additions & 7 deletions builtin/intrinsics.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,37 @@ pub fn[T] physical_equal(a : T, b : T) -> Bool = "%refeq"
/// This function never returns.
/// Function `abort`.
#callsite(autofill(loc))
pub fn[T] abort(string : String, loc~ : SourceLoc) -> T {
@abort.abort(
(
$|\{string}
$| at \{loc}
$|
),
#cfg(not(target="js"))
pub fn[T] abort(msg : String, loc~ : SourceLoc) -> T {
let loc = loc.repr()
let concat = "\n at "
let concat_length = 6
let buffer : FixedArray[UInt16] = FixedArray::make(
msg.length() + concat_length + loc.length() + 1,
0,
)
// TODO : intrinsic
let mut offset = 0
for i in 0..<msg.length() {
buffer[i] = msg[i]
}
offset += msg.length()
for i in 0..<concat_length {
buffer[offset + i] = concat[i]
}
offset += concat_length
for i in 0..<loc.length() {
buffer[offset + i] = loc[i]
}
buffer[msg.length() + concat_length + loc.length()] = 10 // '\n'
@abort.abort(unsafe_fixedarray_uint16_to_string(buffer))
Comment thread
peter-jerry-ye marked this conversation as resolved.
}

///|
#callsite(autofill(loc))
#cfg(target="js")
pub fn[T] abort(msg : String, loc~ : SourceLoc) -> T {
@abort.abort(msg + "\n at " + loc.repr() + "\n")
}

///|
Expand Down
8 changes: 2 additions & 6 deletions builtin/mutarrayview.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@ pub fn[T] MutArrayView::start_offset(self : MutArrayView[T]) -> Int {
#alias("_[_]")
pub fn[T] MutArrayView::at(self : MutArrayView[T], index : Int) -> T {
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}",
)
abort(out_of_index(self.len(), index))
}
self.buf()[self.start() + index]
}
Expand Down Expand Up @@ -179,9 +177,7 @@ pub fn[T] MutArrayView::set(
value : T,
) -> Unit {
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}",
)
abort(out_of_index(self.len(), index))
}
self.buf()[self.start() + index] = value
}
Expand Down
126 changes: 126 additions & 0 deletions builtin/utils.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2026 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.

///|
#cfg(not(target="js"))
fn out_of_index(len : Int, index : Int, index2? : Int) -> String {
let pre = "index out of bounds: the length is "
let pre_length = 35
let mid = " but the index is "
let mid_length = 18
let len = len.to_string()
let index = index.to_string()
let and_ = " and "
let and_length = 5
let index2_str = if index2 is Some(i) { i.to_string() } else { "" }

let data : FixedArray[UInt16] = if index2 is Some(_) {
FixedArray::make(
pre_length +
len.length() +
mid_length +
index.length() +
and_length +
index2_str.length(),
0,
)
} else {
FixedArray::make(pre_length + len.length() + mid_length + index.length(), 0)
}

// TODO : add blit intrinsic to copy string to fixed array
let mut offset = 0
for i in 0..<pre_length {
data[i] = pre[i]
}
offset += pre_length
for i in 0..<len.length() {
data[offset + i] = len[i]
}
offset += len.length()
for i in 0..<mid_length {
data[offset + i] = mid[i]
}
offset += mid_length
for i in 0..<index.length() {
data[offset + i] = index[i]
}
if index2 is Some(_) {
offset += index.length()
for i in 0..<and_length {
data[offset + i] = and_[i]
}
for i in 0..<index2_str.length() {
data[offset + and_length + i] = index2_str[i]
}
}
unsafe_fixedarray_uint16_to_string(data)
}

///|
#cfg(target="js")
fn out_of_index(len : Int, index : Int, index2? : Int) -> String {
if index2 is Some(i) {
"index out of bounds: the length is " +
len.to_string() +
" but the index is " +
index.to_string() +
" and " +
i.to_string()
} else {
"index out of bounds: the length is " +
len.to_string() +
" but the index is " +
index.to_string()
}
}

///|
test "out of index msg" {
let pre = "index out of bounds: the length is "
inspect(
pre.length(),
content=(
#|35
),
)
let mid = " but the index is "
inspect(
mid.length(),
content=(
#|18
),
)
let msg = out_of_index(10, 20)
inspect(
msg,
content=(
#|index out of bounds: the length is 10 but the index is 20
),
)
let msg2 = out_of_index(100, -10)
inspect(
msg2,
content=(
#|index out of bounds: the length is 100 but the index is -10
),
)
let msg3 = out_of_index(50, 60, index2=70)
inspect(
msg3,
content=(
#|index out of bounds: the length is 50 but the index is 60 and 70
),
)
}