Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add array manipulation functions #629

Merged
merged 7 commits into from
Dec 16, 2024
Merged
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
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)
}
Loading