Skip to content

Commit

Permalink
Merge branch 'main' into feature/workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
hustcer authored Mar 16, 2024
2 parents a4c9503 + 6c96c2e commit c8464b2
Show file tree
Hide file tree
Showing 17 changed files with 826 additions and 79 deletions.
96 changes: 63 additions & 33 deletions array/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
/// ```
/// [1, 2, 3, 4, 5].iter(fn(x){ print("\(x) ") }) //output: 1 2 3 4 5
/// ```
pub fn iter[T](self : Array[T], f : (T) -> Unit) {
let mut i = 0
while i < self.length() {
pub fn iter[T](self : Array[T], f : (T) -> Unit) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
f(self[i])
i = i + 1
}
}

Expand All @@ -38,9 +36,7 @@ test "iter" {
[1, 2, 3, 4, 5].iter(
fn(elem) { if elem != i + 1 { failed = true }; i = i + 1 },
)
if failed {
return Err("iter test failed")
}
@assertion.assert_false(failed)?
}

/// Iterates over the array with index.
Expand All @@ -57,11 +53,9 @@ test "iter" {
/// print("(\(index),\(elem)) ")
/// }) //output: (0,1) (1,2) (2,3) (3,4) (4,5)
/// ```
pub fn iteri[T](self : Array[T], f : (Int, T) -> Unit) {
let mut i = 0
while i < self.length() {
pub fn iteri[T](self : Array[T], f : (Int, T) -> Unit) -> Unit {
for i = 0; i < self.length(); i = i + 1 {
f(i, self[i])
i = i + 1
}
}

Expand All @@ -76,11 +70,44 @@ test "iteri" {
i = i + 1
},
)
if failed {
return Err("iteri test failed")
@assertion.assert_false(failed)?
}

pub fn iter_rev[T](self : Array[T], f : (T) -> Unit) -> Unit {
for i = self.length() - 1; i >= 0; i = i - 1 {
f(self[i])
}
}

test "iter rev" {
let mut i = 6
let mut failed = false
[1, 2, 3, 4, 5].iter_rev(
fn(elem) { if elem != i - 1 { failed = true }; i = i - 1 },
)
@assertion.assert_false(failed)?
}

pub fn iteri_rev[T](self : Array[T], f : (Int, T) -> Unit) -> Unit {
for i = self.length() - 1; i >= 0; i = i - 1 {
f(i, self[i])
}
}

test "iteri_rev" {
let mut i = 6
let mut failed = false
[1, 2, 3, 4, 5].iteri_rev(
fn(index, elem) {
if index != i - 2 || elem != i - 1 {
failed = true
}
i = i - 1
},
)
@assertion.assert_false(failed)?
}

/// Applies a function to each element of the array and returns a new array with the results.
///
/// # Example
Expand All @@ -91,45 +118,51 @@ test "iteri" {
/// debug(doubled) //output: [2, 4, 6, 8, 10]
/// ```
pub fn map[T, U](self : Array[T], f : (T) -> U) -> Array[U] {
if self.length() == 0 {
return Array::default()
}
let res = Array::make(self.length(), f(self[0]))
let mut i = 0
while i < self.length() {
for i = 1; i < self.length(); i = i + 1 {
res[i] = f(self[i])
i = i + 1
}
res
}

test "map" {
let arr = [1, 2, 3, 4, 5]
let doubled = arr.map(fn(x) { x * 2 })
let empty : Array[Unit] = Array::default().map(fn(x) { x })
@assertion.assert_eq(empty, [])?
@assertion.assert_eq(doubled, [2, 4, 6, 8, 10])?
}

pub fn map_with_index[T, U](self : Array[T], f : (T, Int) -> U) -> Array[U] {
if self.length() == 0 {
return Array::default()
}
let res = Array::make(self.length(), f(self[0], 0))
loop 1 {
i => if i < self.length() { res[i] = f(self[i], i); continue i + 1 }
for i = 1; i < self.length(); i = i + 1 {
res[i] = f(self[i], i)
}
res
}

test "map with index" {
let arr = [1, 2, 3, 4, 5]
let doubled = arr.map_with_index(fn(x, i) { x * 2 + i })
let empty : Array[Int] = Array::default().map_with_index(fn(x, i) { x + i })
@assertion.assert_eq(empty, [])?
@assertion.assert_eq(doubled, [2, 5, 8, 11, 14])?
}

pub fn op_equal[T : Eq](self : Array[T], that : Array[T]) -> Bool {
if self.length() != that.length() {
return false
}
let mut i = 0
while i < self.length() {
for i = 0; i < self.length(); i = i + 1 {
if self[i] != that[i] {
return false
}
i = i + 1
}
true
}
Expand All @@ -140,8 +173,8 @@ pub fn new[T](length : Int, value : () -> T) -> Array[T] {
Array::default()
} else {
let array = Array::make(length, value())
loop 1 {
i => if i < length { array[i] = value(); continue i + 1 }
for i = 1; i < length; i = i + 1 {
array[i] = value()
}
array
}
Expand All @@ -158,8 +191,8 @@ pub fn new_with_index[T](length : Int, value : (Int) -> T) -> Array[T] {
Array::default()
} else {
let array = Array::make(length, value(0))
loop 1 {
i => if i < length { array[i] = value(i); continue i + 1 }
for i = 1; i < length; i = i + 1 {
array[i] = value(i)
}
array
}
Expand All @@ -182,14 +215,11 @@ test "from_array" {
}

pub fn fold[T, U](self : Array[T], f : (T, U) -> U, init : U) -> U {
loop 0, init {
i, acc =>
if i < self.length() {
continue i + 1,
f(self[i], acc)
} else {
acc
}
for i = 0, acc = init; i < self.length(); {
continue i + 1,
f(self[i], acc)
} else {
acc
}
}

Expand Down
34 changes: 21 additions & 13 deletions assertion/assertion.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ test "assert_ne.eq" {
}
}

pub fn assert_false(x : Bool) -> Result[Unit, String] {
pub fn assert_false(x : Bool, ~loc : SourceLoc = _) -> Result[Unit, String] {
if x == false {
Ok(())
} else {
Err("assert_false failed")
Err("FAILED:\(loc)")
}
}

Expand All @@ -87,11 +87,11 @@ test "assert_false.true" {
assert_ne(assert_false(true), Ok(()))?
}

pub fn assert_true(x : Bool) -> Result[Unit, String] {
pub fn assert_true(x : Bool, ~loc : SourceLoc = _) -> Result[Unit, String] {
if x {
Ok(())
} else {
Err("assert_true failed")
Err("FAILED:\(loc)")
}
}

Expand All @@ -105,8 +105,8 @@ test "assert_true.false" {

/// Assert referential equality of two values.
///
/// Returns Ok if the two arguments are the same object by reference, using the
/// `===` operator; raises an Error otherwise. Certain objects may be equal by
/// Returns Ok if the two arguments are the same object by reference, using
/// `physical_equal`; raises an Error otherwise. Certain objects may be equal by
/// value, but they are different objects in the memory. This function checks
/// the latter.
///
Expand All @@ -118,13 +118,17 @@ test "assert_true.false" {
/// assert_is(a, a)? // this is okay
/// assert_is(a, b)? // yields an error
/// ```
pub fn assert_is[T : Debug](a : T, b : T) -> Result[Unit, String] {
if a === b {
pub fn assert_is[T : Debug](
a : T,
b : T,
~loc : SourceLoc = _
) -> Result[Unit, String] {
if physical_equal(a, b) {
Ok(())
} else {
let a = debug_string(a)
let b = debug_string(b)
Err("assertion failed for `\(a) === \(b)`")
Err("FAILED:\(loc) `\(a) is \(b)`")
}
}

Expand All @@ -145,7 +149,7 @@ test "assert_is.is.not" {
/// Assert referential inequality of two values.
///
/// Returns Ok if the two arguments are NOT the same object by reference, using
/// the `===` operator; raises an Error otherwise. Certain objects may be equal
/// `physical_equal`; raises an Error otherwise. Certain objects may be equal
/// by value, but they are different objects in the memory. This function
/// checks the latter.
///
Expand All @@ -157,13 +161,17 @@ test "assert_is.is.not" {
/// assert_is_not(a, b)? // this is okay
/// assert_is_not(a, a)? // yields an error
/// ```
pub fn assert_is_not[T : Debug](a : T, b : T) -> Result[Unit, String] {
if not(a === b) {
pub fn assert_is_not[T : Debug](
a : T,
b : T,
~loc : SourceLoc = _
) -> Result[Unit, String] {
if not(physical_equal(a, b)) {
Ok(())
} else {
let a = debug_string(a)
let b = debug_string(b)
Err("assertion failed for `not(\(a) === \(b))`")
Err("FAILED:\(loc) `not(\(a) is \(b))`")
}
}

Expand Down
50 changes: 50 additions & 0 deletions double/double.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,53 @@
// 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 fn Double::from_int(i : Int) -> Double {
i.to_double()
}

pub fn abs(self : Double) -> Double {
if self < 0.0 {
-self
} else {
self
}
}

/// Returns the sign of the double.
/// - If the double is positive, returns 1.0.
/// - If the double is negative, returns -1.0.
/// - Otherwise, returns the double itself (0.0, -0.0 and NaN).
pub fn signum(self : Double) -> Double {
if self < 0.0 {
-1.0
} else if self > 0.0 {
1.0
} else {
self // handles 0.0, -0.0, NaN
}
}

fn test_num[T : @num.Num + Debug + Default + Eq](
x : T,
y : T,
x_plus_y : T,
x_mul_y : T,
x_minus_y : T,
x_div_y : T,
x_signum : T
) -> Result[Unit, String] {
@assertion.assert_eq(x + y, x_plus_y)?
@assertion.assert_eq(x * y, x_mul_y)?
@assertion.assert_eq(x - y, x_minus_y)?
@assertion.assert_eq(x / y, x_div_y)?
@assertion.assert_eq(x.abs(), T::default() - x)?
@assertion.assert_eq(x.signum(), x_signum)?
Ok(())
}

test "double.num" {
let x = -500.0
let y = 792.0
test_num(x, y, x + y, x * y, x - y, x / y, -1.0)?
}
7 changes: 6 additions & 1 deletion double/moon.pkg.json
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
{}
{
"import": [
"moonbitlang/core/num",
"moonbitlang/core/assertion"
]
}
46 changes: 46 additions & 0 deletions int/int.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,49 @@
// 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 fn Int::from_int(i : Int) -> Int {
i
}

pub fn abs(self : Int) -> Int {
if self < 0 {
-self
} else {
self
}
}

pub fn signum(self : Int) -> Int {
if self < 0 {
-1
} else if self > 0 {
1
} else {
0
}
}

fn test_num[T : @num.Num + Debug + Default + Eq](
x : T,
y : T,
x_plus_y : T,
x_mul_y : T,
x_minus_y : T,
x_div_y : T,
x_signum : T
) -> Result[Unit, String] {
@assertion.assert_eq(x + y, x_plus_y)?
@assertion.assert_eq(x * y, x_mul_y)?
@assertion.assert_eq(x - y, x_minus_y)?
@assertion.assert_eq(x / y, x_div_y)?
@assertion.assert_eq(x.abs(), T::default() - x)?
@assertion.assert_eq(x.signum(), x_signum)?
Ok(())
}

test "int.num" {
let x = -5
let y = 7
test_num(x, y, x + y, x * y, x - y, x / y, -1)?
}
Loading

0 comments on commit c8464b2

Please sign in to comment.