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

feat(stdlib): Add toList, fromList, toArray, fromArray to Stack #2198

Merged
merged 4 commits into from
Jan 2, 2025
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
66 changes: 66 additions & 0 deletions compiler/test/stdlib/stack.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,44 @@ let stack2 = Stack.make(size=1)
Stack.push(0, stack2)
assert stack == stack2

// Stack.toList
let s = Stack.make()
assert Stack.toList(s) == []
Stack.push(1, s)
Stack.push(2, s)
Stack.push(3, s)
assert Stack.toList(s) == [3, 2, 1]
Stack.pop(s)
assert Stack.toList(s) == [2, 1]

// Stack.fromList
let s = Stack.fromList([3, 2, 1])
assert Stack.pop(s) == Some(3)
assert Stack.pop(s) == Some(2)
assert Stack.pop(s) == Some(1)
assert Stack.pop(s) == None
let s = Stack.fromList([])
assert Stack.pop(s) == None

// Stack.toArray
let s = Stack.make()
assert Stack.toArray(s) == [>]
Stack.push(1, s)
Stack.push(2, s)
Stack.push(3, s)
assert Stack.toArray(s) == [> 3, 2, 1]
Stack.pop(s)
assert Stack.toArray(s) == [> 2, 1]

// Stack.fromArray
let s = Stack.fromArray([> 3, 2, 1])
assert Stack.pop(s) == Some(3)
assert Stack.pop(s) == Some(2)
assert Stack.pop(s) == Some(1)
assert Stack.pop(s) == None
let s = Stack.fromArray([>])
assert Stack.pop(s) == None

module Immutable {
use Stack.{ module Immutable as Stack }

Expand Down Expand Up @@ -90,4 +128,32 @@ module Immutable {
assert Stack.size(Stack.empty) == 0
assert Stack.size(sampleStack) == 3
assert Stack.size(Stack.pop(Stack.pop(sampleStack))) == 1

// Stack.toList
let stack = Stack.empty
let stack = Stack.push(1, stack)
let stack = Stack.push(2, stack)
assert Stack.toList(stack) == [2, 1]

// Stack.fromList
let stack = Stack.fromList([2, 1])
assert Stack.peek(stack) == Some(2)
let stack = Stack.pop(stack)
assert Stack.peek(stack) == Some(1)
let stack = Stack.pop(stack)
assert Stack.isEmpty(stack)

// Stack.toArray
let stack = Stack.empty
let stack = Stack.push(1, stack)
let stack = Stack.push(2, stack)
assert Stack.toArray(stack) == [> 2, 1]

// Stack.fromArray
let stack = Stack.fromArray([> 2, 1])
assert Stack.peek(stack) == Some(2)
let stack = Stack.pop(stack)
assert Stack.peek(stack) == Some(1)
let stack = Stack.pop(stack)
assert Stack.isEmpty(stack)
}
171 changes: 170 additions & 1 deletion stdlib/stack.gr
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ abstract record Stack<a> {
*
* @param size: The initial storage size of the stack
* @returns An empty stack
*
*
* @since v0.6.0
*/
provide let make = (size=16) => {
Expand Down Expand Up @@ -134,6 +134,95 @@ provide let copy = stack => {
{ size, array: Array.copy(array) }
}

/**
* Creates a list containing the elements of a stack.
*
* @param stack: The stack to convert
* @returns A list containing all stack values
*
* @example
* let stack = Stack.make()
* Stack.push(1, stack)
* Stack.push(2, stack)
* assert Stack.toList(stack) == [2, 1]
*
* @since v0.7.0
*/
provide let toList = stack => {
let size = stack.size
List.init(size, i => match (stack.array[size - i - 1]) {
Some(v) => v,
None => fail "Impossible: None in stack bounds on toList",
})
}

/**
* Creates a stack from a list.
*
* @param list: The list to convert
* @returns A stack containing all list values
*
* @example
* let stack = Stack.fromList([3, 2, 1])
* assert Stack.pop(stack) == Some(3)
* assert Stack.pop(stack) == Some(2)
* assert Stack.pop(stack) == Some(1)
* assert Stack.pop(stack) == None
*
* @since v0.7.0
*/
provide let fromList = list => {
let stack = make(size=List.length(list))
List.forEach(v => push(v, stack), List.reverse(list))
stack
}

/**
* Creates an array containing the elements of a stack.
*
* @param stack: The stack to convert
* @returns An array containing all stack values
*
* @example
* let stack = Stack.make()
* Stack.push(1, stack)
* Stack.push(2, stack)
* assert Stack.toArray(stack) == [> 2, 1]
*
* @since v0.7.0
*/
provide let toArray = stack => {
let size = stack.size
Array.init(size, i => match (stack.array[size - i - 1]) {
Some(v) => v,
None => fail "Impossible: None in stack bounds on toList",
})
}

/**
* Creates a stack from an array.
*
* @param arr: The array to convert
* @returns A stack containing all array values
*
* @example
* let s = Stack.fromArray([> 3, 2, 1])
* assert Stack.pop(s) == Some(3)
* assert Stack.pop(s) == Some(2)
* assert Stack.pop(s) == Some(1)
* assert Stack.pop(s) == None
*
* @since v0.7.0
*/
provide let fromArray = arr => {
let arrLen = Array.length(arr)
let stack = make(size=arrLen)
for (let mut i = arrLen - 1; i >= 0; i -= 1) {
push(arr[i], stack)
}
stack
}

/**
* An immutable stack implementation.
*/
Expand Down Expand Up @@ -237,4 +326,84 @@ provide module Immutable {
{ data } => List.length(data),
}
}

/**
* Creates a list containing the elements of a stack.
*
* @param stack: The stack to convert
* @returns A list containing all stack values
*
* @example
* use Stack.{ module Immutable as Stack }
* let stack = Stack.empty
* let stack = Stack.push(1, stack)
* let stack = Stack.push(2, stack)
* assert Stack.toList(stack) == [2, 1]
*
* @since v0.7.0
*/
provide let toList = stack => {
stack.data
}

/**
* Creates a stack from a list.
*
* @param list: The list to convert
* @returns A stack containing all list values
*
* @example
* use Stack.{ module Immutable as Stack }
* let stack = Stack.fromList([2, 1])
* assert Stack.peek(stack) == Some(2)
* let stack = Stack.pop(stack)
* assert Stack.peek(stack) == Some(1)
* let stack = Stack.pop(stack)
* assert Stack.isEmpty(stack)
*
* @since v0.7.0
*/
provide let fromList = list => {
{ data: list, }
}

/**
* Creates an array containing the elements of a stack.
*
* @param stack: The stack to convert
* @returns An array containing all stack values
*
* @example
* use Stack.{ module Immutable as Stack }
* let stack = Stack.empty
* let stack = Stack.push(1, stack)
* let stack = Stack.push(2, stack)
* assert Stack.toArray(stack) == [> 2, 1]
*
* @since v0.7.0
*/
provide let toArray = stack => {
Array.fromList(stack.data)
}

/**
* Creates a stack from an array.
*
* @param arr: The array to convert
* @returns A stack containing all array values
*
* @example
* use Stack.{ module Immutable as Stack }
* let stack = Stack.fromArray([> 2, 1])
* assert Stack.peek(stack) == Some(2)
* let stack = Stack.pop(stack)
* assert Stack.peek(stack) == Some(1)
* let stack = Stack.pop(stack)
* assert Stack.isEmpty(stack)
*
* @since v0.7.0
*/
provide let fromArray = arr => {
{ data: Array.toList(arr), }
}
}
Loading
Loading