Skip to content

Commit

Permalink
Add array manipulation functions (#629)
Browse files Browse the repository at this point in the history
Co-authored-by: Maksym Hazevych <[email protected]>
  • Loading branch information
hdwalters and mks-h authored Dec 16, 2024
1 parent 19c3e35 commit 79fa51c
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 9 deletions.
52 changes: 52 additions & 0 deletions src/std/array.ab
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,55 @@ pub fun includes(array, value) {
let result = array_first_index(array, value)
return result >= 0
}

/// Returns the first element in the array; if the array is empty, the return
/// value is undefined.
pub fun first(array) {
return array[0]
}

/// Returns the last element in the array; if the array is empty, the return
/// value is undefined.
pub fun last(array) {
let index = len(array) - 1
return array[index]
}

/// Removes an element at the index from the array; if the index is negative
/// or beyond the end, the return value is undefined, but the array will be
/// unchanged.
pub fun remove_at(ref array: [], index: Num): Null {
let offset = index + 1
let length = len(array)
array = array[0..index] + array[offset..length]
}

/// Removes an element at the index from the array, and returns it; if the
/// index is negative or beyond the end, the return value is undefined, but
/// the array will be unchanged.
pub fun extract_at(ref array, index) {
let element = array[index]
let offset = index + 1
let length = len(array)
array = array[0..index] + array[offset..length]
return element
}

/// Removes the last element from the array, and returns it; if the array
/// is empty, the return value is undefined, but the array will be unchanged.
pub fun pop(ref array) {
let length = len(array)
let index = length - 1
let element = array[index]
array = array[0..index]
return element
}

/// Removes the first element from the array, and returns it; if the array
/// is empty, the return value is undefined, but the array will be unchanged.
pub fun shift(ref array) {
let length = len(array)
let element = array[0]
array = array[1..length]
return element
}
25 changes: 25 additions & 0 deletions src/tests/stdlib/array_extract_at.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { extract_at } from "std/array"

// Output
// Value at -5: "" (4) [zero one two three]
// Value at -4: "zero" (4) [zero one two three]
// Value at -3: "one" (4) [zero one two three]
// Value at -2: "two" (4) [zero one two three]
// Value at -1: "three" (4) [zero one two three]
// Value at 0: "zero" (3) [one two three]
// Value at 1: "one" (3) [zero two three]
// Value at 2: "two" (3) [zero one three]
// Value at 3: "three" (3) [zero one two]
// Value at 4: "" (4) [zero one two three]

fun test_extract(data: [Text], index: Num): Null {
let value = extract_at(data, index)
echo "Value at {index}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
for index in -5..=4 {
test_extract(numbers, index)
}
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_first.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { first } from "std/array"

// Output
// First of numbers: "zero" (4) [zero one two three]
// First of empty: "" (0) []

fun test_first(label: Text, data: [Text]): Null {
let value = first(data)
echo "First of {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_first("numbers", numbers)
test_first("empty", empty)
}
22 changes: 18 additions & 4 deletions src/tests/stdlib/array_first_index.ab
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import * from "std/array"
import { array_first_index } from "std/array"

// Output
// 2
// Index of "zero": 0
// Index of "one": 1
// Index of "two": 2
// Index of "three": 3
// Index of "four": -1

fun test_index(data: [Text], value: Text): Null {
let index = array_first_index(data, value)
echo "Index of \"{value}\": {index}"
}

main {
echo array_first_index([1, 2, 3, 4], 3)
}
let numbers = ["zero", "one", "two", "three", "two", "one", "zero"]
test_index(numbers, "zero")
test_index(numbers, "one")
test_index(numbers, "two")
test_index(numbers, "three")
test_index(numbers, "four")
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_last.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { last } from "std/array"

// Output
// Last of numbers: "three" (4) [zero one two three]
// Last of empty: "" (0) []

fun test_last(label: Text, data: [Text]): Null {
let value = last(data)
echo "Last of {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_last("numbers", numbers)
test_last("empty", empty)
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_pop.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { pop } from "std/array"

// Output
// Popped from numbers: "three" (3) [zero one two]
// Popped from empty: "" (0) []

fun test_pop(label: Text, data: [Text]): Null {
let value = pop(data)
echo "Popped from {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_pop("numbers", numbers)
test_pop("empty", empty)
}
25 changes: 25 additions & 0 deletions src/tests/stdlib/array_remove_at.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { remove_at } from "std/array"

// Output
// Array after -5: (4) [zero one two three]
// Array after -4: (4) [zero one two three]
// Array after -3: (4) [zero one two three]
// Array after -2: (4) [zero one two three]
// Array after -1: (4) [zero one two three]
// Array after 0: (3) [one two three]
// Array after 1: (3) [zero two three]
// Array after 2: (3) [zero one three]
// Array after 3: (3) [zero one two]
// Array after 4: (4) [zero one two three]

fun test_remove(data: [Text], index: Num): Null {
remove_at(data, index)
echo "Array after {index}: ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
for index in -5..=4 {
test_remove(numbers, index)
}
}
21 changes: 21 additions & 0 deletions src/tests/stdlib/array_remove_each.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { remove_at } from "std/array"

// Output
// Array before 1: (4) [zero one two three]
// Array after 1: (3) [zero two three]
// Array after 2: (2) [zero three]
// Array after 3: (1) [zero]
// Array after 4: (1) [zero]

main {
let numbers = ["zero", "one", "two", "three"]
echo "Array before 1: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 1: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 2: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 3: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 4: ({len(numbers)}) [{numbers}]"
}
23 changes: 18 additions & 5 deletions src/tests/stdlib/array_search.ab
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import * from "std/array"
import { array_search } from "std/array"

// Output
// 6
// Indices of "zero": [0 6]
// Indices of "one": [1 5]
// Indices of "two": [2 4]
// Indices of "three": [3]
// Indices of "four": []

fun test_search(data: [Text], value: Text): Null {
let indices = array_search(data, value)
echo "Indices of \"{value}\": [{indices}]"
}

main {
let result = array_search([1, 2, 3, 4, 3], 3)
echo result[0]+result[1]
}
let numbers = ["zero", "one", "two", "three", "two", "one", "zero"]
test_search(numbers, "zero")
test_search(numbers, "one")
test_search(numbers, "two")
test_search(numbers, "three")
test_search(numbers, "four")
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_shift.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { shift } from "std/array"

// Output
// Shifted from numbers: "zero" (3) [one two three]
// Shifted from empty: "" (0) []

fun test_shift(label: Text, data: [Text]): Null {
let value = shift(data)
echo "Shifted from {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_shift("numbers", numbers)
test_shift("empty", empty)
}

0 comments on commit 79fa51c

Please sign in to comment.