diff --git a/compiler/test/stdlib/stack.test.gr b/compiler/test/stdlib/stack.test.gr
index 8f56a3ae9..0bbcd1116 100644
--- a/compiler/test/stdlib/stack.test.gr
+++ b/compiler/test/stdlib/stack.test.gr
@@ -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 }
@@ -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)
}
diff --git a/stdlib/stack.gr b/stdlib/stack.gr
index aeb8d58b3..6bc44faae 100644
--- a/stdlib/stack.gr
+++ b/stdlib/stack.gr
@@ -30,7 +30,7 @@ abstract record Stack {
*
* @param size: The initial storage size of the stack
* @returns An empty stack
- *
+ *
* @since v0.6.0
*/
provide let make = (size=16) => {
@@ -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.
*/
@@ -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), }
+ }
}
diff --git a/stdlib/stack.md b/stdlib/stack.md
index 0e5a22a65..a40034e8c 100644
--- a/stdlib/stack.md
+++ b/stdlib/stack.md
@@ -225,6 +225,144 @@ Returns:
|----|-----------|
|`Stack`|A new stack containing the elements from the input|
+### Stack.**toList**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+toList : (stack: Stack) => List
+```
+
+Creates a list containing the elements of a stack.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`stack`|`Stack`|The stack to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`List`|A list containing all stack values|
+
+Examples:
+
+```grain
+let stack = Stack.make()
+Stack.push(1, stack)
+Stack.push(2, stack)
+assert Stack.toList(stack) == [2, 1]
+```
+
+### Stack.**fromList**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+fromList : (list: List) => Stack
+```
+
+Creates a stack from a list.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`list`|`List`|The list to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`Stack`|A stack containing all list values|
+
+Examples:
+
+```grain
+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
+```
+
+### Stack.**toArray**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+toArray : (stack: Stack) => Array
+```
+
+Creates an array containing the elements of a stack.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`stack`|`Stack`|The stack to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`Array`|An array containing all stack values|
+
+Examples:
+
+```grain
+let stack = Stack.make()
+Stack.push(1, stack)
+Stack.push(2, stack)
+assert Stack.toArray(stack) == [> 2, 1]
+```
+
+### Stack.**fromArray**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+fromArray : (arr: Array) => Stack
+```
+
+Creates a stack from an array.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`arr`|`Array`|The array to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`Stack`|A stack containing all array values|
+
+Examples:
+
+```grain
+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
+```
+
## Stack.Immutable
An immutable stack implementation.
@@ -427,3 +565,147 @@ Returns:
|----|-----------|
|`Number`|The count of the items in the stack|
+#### Stack.Immutable.**toList**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+toList : (stack: ImmutableStack) => List
+```
+
+Creates a list containing the elements of a stack.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`stack`|`ImmutableStack`|The stack to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`List`|A list containing all stack values|
+
+Examples:
+
+```grain
+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]
+```
+
+#### Stack.Immutable.**fromList**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+fromList : (list: List) => ImmutableStack
+```
+
+Creates a stack from a list.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`list`|`List`|The list to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`ImmutableStack`|A stack containing all list values|
+
+Examples:
+
+```grain
+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)
+```
+
+#### Stack.Immutable.**toArray**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+toArray : (stack: ImmutableStack) => Array
+```
+
+Creates an array containing the elements of a stack.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`stack`|`ImmutableStack`|The stack to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`Array`|An array containing all stack values|
+
+Examples:
+
+```grain
+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]
+```
+
+#### Stack.Immutable.**fromArray**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+fromArray : (arr: Array) => ImmutableStack
+```
+
+Creates a stack from an array.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`arr`|`Array`|The array to convert|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`ImmutableStack`|A stack containing all array values|
+
+Examples:
+
+```grain
+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)
+```
+