From 3270e6b6dabe949dda3c42f82771e7acede20797 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Mon, 11 Mar 2024 18:58:59 +0800 Subject: [PATCH 1/2] basic setup for vector --- vec/moon.pkg.json | 5 +++ vec/vec.mbt | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 vec/moon.pkg.json create mode 100644 vec/vec.mbt diff --git a/vec/moon.pkg.json b/vec/moon.pkg.json new file mode 100644 index 000000000..8fe706ebd --- /dev/null +++ b/vec/moon.pkg.json @@ -0,0 +1,5 @@ +{ + "import": [ + { "path": "moonbitlang/core/assertion", "alias": "assertion" } + ] +} \ No newline at end of file diff --git a/vec/vec.mbt b/vec/vec.mbt new file mode 100644 index 000000000..09461bfdc --- /dev/null +++ b/vec/vec.mbt @@ -0,0 +1,81 @@ +// Copyright 2024 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. + +priv type UninitializedArray[T] Array[UnsafeMaybeUninit[T]] + +fn UninitializedArray::make[T](size : Int) -> UninitializedArray[T] = "%make_array_maybe_uninit" + +fn op_get[T](self : UninitializedArray[T], index : Int) -> T = "%array_get" + +fn op_set[T](self : UninitializedArray[T], index : Int, value : T) = "%array_set" + +fn length[T](self : UninitializedArray[T]) -> Int { + self.0.length() +} + +/// A `Vec` is a generic vector (dynamic array) that can grow in size. +struct Vec[T] { + mut buf : UninitializedArray[T] + mut len : Int +} + +/// Creates a new, empty vector. +pub fn Vec::new[T]() -> Vec[T] { + Vec::{ buf: UninitializedArray::make(0), len: 0 } +} + +/// Creates a new, empty vector with a specified initial capacity. +pub fn Vec::with_capacity[T](cap : Int) -> Vec[T] { + Vec::{ buf: UninitializedArray::make(cap), len: 0 } +} + +/// Adds an element to the end of the vector. +pub fn push[T](self : Vec[T], value : T) { + if self.len == self.buf.length() { + let old_cap = self.len + let new_cap = if old_cap == 0 { 8 } else { old_cap * 2 } + let new_buf = UninitializedArray::make(new_cap) + for i = 0; i < old_cap; i = i + 1 { + new_buf[i] = self.buf[i] + } + new_buf[old_cap] = value + self.buf = new_buf + self.len = old_cap + 1 + } else { + self.buf[self.len] = value + self.len += 1 + } +} + +/// Retrieves the element at the specified index from the vector. +pub fn op_get[T](self : Vec[T], index : Int) -> T { + self.buf[index] +} + +/// Sets the value of the element at the specified index. +pub fn op_set[T](self : Vec[T], index : Int, value : T) { + self.buf[index] = value +} + +test "push" { + let v = Vec::new() + v.push(3) + v.push(4) + v.push(5) + @assertion.assert_eq(v[0], 3)? + @assertion.assert_eq(v[1], 4)? + @assertion.assert_eq(v[2], 5)? + v[0] = 6 + @assertion.assert_eq(v[0], 6)? +} From f7827502c57fd249c66c7a5a57d25719d78efa2b Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Tue, 12 Mar 2024 10:10:02 +0800 Subject: [PATCH 2/2] bounds check --- vec/vec.mbt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vec/vec.mbt b/vec/vec.mbt index 09461bfdc..72735e4ea 100644 --- a/vec/vec.mbt +++ b/vec/vec.mbt @@ -59,12 +59,24 @@ pub fn push[T](self : Vec[T], value : T) { } /// Retrieves the element at the specified index from the vector. +/// +/// If you try to access an index which isn’t in the Vec, it will panic. pub fn op_get[T](self : Vec[T], index : Int) -> T { + if index >= self.len { + let len = self.len + abort("index out of bounds: the len is \(len) but the index is \(index)") + } self.buf[index] } /// Sets the value of the element at the specified index. +/// +/// If you try to access an index which isn’t in the Vec, it will panic. pub fn op_set[T](self : Vec[T], index : Int, value : T) { + if index >= self.len { + let len = self.len + abort("index out of bounds: the len is \(len) but the index is \(index)") + } self.buf[index] = value }