Skip to content

Commit b815bcd

Browse files
feat(stdlib): Add toList, fromList, toArray, fromArray to Stack (#2198)
Co-authored-by: Oscar Spencer <oscar.spen@gmail.com>
1 parent 1179c91 commit b815bcd

File tree

3 files changed

+518
-1
lines changed

3 files changed

+518
-1
lines changed

compiler/test/stdlib/stack.test.gr

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,44 @@ let stack2 = Stack.make(size=1)
5656
Stack.push(0, stack2)
5757
assert stack == stack2
5858

59+
// Stack.toList
60+
let s = Stack.make()
61+
assert Stack.toList(s) == []
62+
Stack.push(1, s)
63+
Stack.push(2, s)
64+
Stack.push(3, s)
65+
assert Stack.toList(s) == [3, 2, 1]
66+
Stack.pop(s)
67+
assert Stack.toList(s) == [2, 1]
68+
69+
// Stack.fromList
70+
let s = Stack.fromList([3, 2, 1])
71+
assert Stack.pop(s) == Some(3)
72+
assert Stack.pop(s) == Some(2)
73+
assert Stack.pop(s) == Some(1)
74+
assert Stack.pop(s) == None
75+
let s = Stack.fromList([])
76+
assert Stack.pop(s) == None
77+
78+
// Stack.toArray
79+
let s = Stack.make()
80+
assert Stack.toArray(s) == [>]
81+
Stack.push(1, s)
82+
Stack.push(2, s)
83+
Stack.push(3, s)
84+
assert Stack.toArray(s) == [> 3, 2, 1]
85+
Stack.pop(s)
86+
assert Stack.toArray(s) == [> 2, 1]
87+
88+
// Stack.fromArray
89+
let s = Stack.fromArray([> 3, 2, 1])
90+
assert Stack.pop(s) == Some(3)
91+
assert Stack.pop(s) == Some(2)
92+
assert Stack.pop(s) == Some(1)
93+
assert Stack.pop(s) == None
94+
let s = Stack.fromArray([>])
95+
assert Stack.pop(s) == None
96+
5997
module Immutable {
6098
use Stack.{ module Immutable as Stack }
6199

@@ -90,4 +128,32 @@ module Immutable {
90128
assert Stack.size(Stack.empty) == 0
91129
assert Stack.size(sampleStack) == 3
92130
assert Stack.size(Stack.pop(Stack.pop(sampleStack))) == 1
131+
132+
// Stack.toList
133+
let stack = Stack.empty
134+
let stack = Stack.push(1, stack)
135+
let stack = Stack.push(2, stack)
136+
assert Stack.toList(stack) == [2, 1]
137+
138+
// Stack.fromList
139+
let stack = Stack.fromList([2, 1])
140+
assert Stack.peek(stack) == Some(2)
141+
let stack = Stack.pop(stack)
142+
assert Stack.peek(stack) == Some(1)
143+
let stack = Stack.pop(stack)
144+
assert Stack.isEmpty(stack)
145+
146+
// Stack.toArray
147+
let stack = Stack.empty
148+
let stack = Stack.push(1, stack)
149+
let stack = Stack.push(2, stack)
150+
assert Stack.toArray(stack) == [> 2, 1]
151+
152+
// Stack.fromArray
153+
let stack = Stack.fromArray([> 2, 1])
154+
assert Stack.peek(stack) == Some(2)
155+
let stack = Stack.pop(stack)
156+
assert Stack.peek(stack) == Some(1)
157+
let stack = Stack.pop(stack)
158+
assert Stack.isEmpty(stack)
93159
}

stdlib/stack.gr

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ abstract record Stack<a> {
3030
*
3131
* @param size: The initial storage size of the stack
3232
* @returns An empty stack
33-
*
33+
*
3434
* @since v0.6.0
3535
*/
3636
provide let make = (size=16) => {
@@ -134,6 +134,95 @@ provide let copy = stack => {
134134
{ size, array: Array.copy(array) }
135135
}
136136

137+
/**
138+
* Creates a list containing the elements of a stack.
139+
*
140+
* @param stack: The stack to convert
141+
* @returns A list containing all stack values
142+
*
143+
* @example
144+
* let stack = Stack.make()
145+
* Stack.push(1, stack)
146+
* Stack.push(2, stack)
147+
* assert Stack.toList(stack) == [2, 1]
148+
*
149+
* @since v0.7.0
150+
*/
151+
provide let toList = stack => {
152+
let size = stack.size
153+
List.init(size, i => match (stack.array[size - i - 1]) {
154+
Some(v) => v,
155+
None => fail "Impossible: None in stack bounds on toList",
156+
})
157+
}
158+
159+
/**
160+
* Creates a stack from a list.
161+
*
162+
* @param list: The list to convert
163+
* @returns A stack containing all list values
164+
*
165+
* @example
166+
* let stack = Stack.fromList([3, 2, 1])
167+
* assert Stack.pop(stack) == Some(3)
168+
* assert Stack.pop(stack) == Some(2)
169+
* assert Stack.pop(stack) == Some(1)
170+
* assert Stack.pop(stack) == None
171+
*
172+
* @since v0.7.0
173+
*/
174+
provide let fromList = list => {
175+
let stack = make(size=List.length(list))
176+
List.forEach(v => push(v, stack), List.reverse(list))
177+
stack
178+
}
179+
180+
/**
181+
* Creates an array containing the elements of a stack.
182+
*
183+
* @param stack: The stack to convert
184+
* @returns An array containing all stack values
185+
*
186+
* @example
187+
* let stack = Stack.make()
188+
* Stack.push(1, stack)
189+
* Stack.push(2, stack)
190+
* assert Stack.toArray(stack) == [> 2, 1]
191+
*
192+
* @since v0.7.0
193+
*/
194+
provide let toArray = stack => {
195+
let size = stack.size
196+
Array.init(size, i => match (stack.array[size - i - 1]) {
197+
Some(v) => v,
198+
None => fail "Impossible: None in stack bounds on toList",
199+
})
200+
}
201+
202+
/**
203+
* Creates a stack from an array.
204+
*
205+
* @param arr: The array to convert
206+
* @returns A stack containing all array values
207+
*
208+
* @example
209+
* let s = Stack.fromArray([> 3, 2, 1])
210+
* assert Stack.pop(s) == Some(3)
211+
* assert Stack.pop(s) == Some(2)
212+
* assert Stack.pop(s) == Some(1)
213+
* assert Stack.pop(s) == None
214+
*
215+
* @since v0.7.0
216+
*/
217+
provide let fromArray = arr => {
218+
let arrLen = Array.length(arr)
219+
let stack = make(size=arrLen)
220+
for (let mut i = arrLen - 1; i >= 0; i -= 1) {
221+
push(arr[i], stack)
222+
}
223+
stack
224+
}
225+
137226
/**
138227
* An immutable stack implementation.
139228
*/
@@ -237,4 +326,84 @@ provide module Immutable {
237326
{ data } => List.length(data),
238327
}
239328
}
329+
330+
/**
331+
* Creates a list containing the elements of a stack.
332+
*
333+
* @param stack: The stack to convert
334+
* @returns A list containing all stack values
335+
*
336+
* @example
337+
* use Stack.{ module Immutable as Stack }
338+
* let stack = Stack.empty
339+
* let stack = Stack.push(1, stack)
340+
* let stack = Stack.push(2, stack)
341+
* assert Stack.toList(stack) == [2, 1]
342+
*
343+
* @since v0.7.0
344+
*/
345+
provide let toList = stack => {
346+
stack.data
347+
}
348+
349+
/**
350+
* Creates a stack from a list.
351+
*
352+
* @param list: The list to convert
353+
* @returns A stack containing all list values
354+
*
355+
* @example
356+
* use Stack.{ module Immutable as Stack }
357+
* let stack = Stack.fromList([2, 1])
358+
* assert Stack.peek(stack) == Some(2)
359+
* let stack = Stack.pop(stack)
360+
* assert Stack.peek(stack) == Some(1)
361+
* let stack = Stack.pop(stack)
362+
* assert Stack.isEmpty(stack)
363+
*
364+
* @since v0.7.0
365+
*/
366+
provide let fromList = list => {
367+
{ data: list, }
368+
}
369+
370+
/**
371+
* Creates an array containing the elements of a stack.
372+
*
373+
* @param stack: The stack to convert
374+
* @returns An array containing all stack values
375+
*
376+
* @example
377+
* use Stack.{ module Immutable as Stack }
378+
* let stack = Stack.empty
379+
* let stack = Stack.push(1, stack)
380+
* let stack = Stack.push(2, stack)
381+
* assert Stack.toArray(stack) == [> 2, 1]
382+
*
383+
* @since v0.7.0
384+
*/
385+
provide let toArray = stack => {
386+
Array.fromList(stack.data)
387+
}
388+
389+
/**
390+
* Creates a stack from an array.
391+
*
392+
* @param arr: The array to convert
393+
* @returns A stack containing all array values
394+
*
395+
* @example
396+
* use Stack.{ module Immutable as Stack }
397+
* let stack = Stack.fromArray([> 2, 1])
398+
* assert Stack.peek(stack) == Some(2)
399+
* let stack = Stack.pop(stack)
400+
* assert Stack.peek(stack) == Some(1)
401+
* let stack = Stack.pop(stack)
402+
* assert Stack.isEmpty(stack)
403+
*
404+
* @since v0.7.0
405+
*/
406+
provide let fromArray = arr => {
407+
{ data: Array.toList(arr), }
408+
}
240409
}

0 commit comments

Comments
 (0)