Skip to content

Commit

Permalink
feat(stdlib)!: Make queue and stack mutable & provide Immutable submo…
Browse files Browse the repository at this point in the history
…dules (#1479)

* feat(stdlib): Mutable queue and stack

* moved mutable impls to root of modules

* generate submodule docs with graindoc submodule support

* updated history

* update docs with graindoc fixes

* formatting

* update names as per review

---------

Co-authored-by: Blaine Bublitz <blaine.bublitz@gmail.com>
  • Loading branch information
alex-snezhko and phated authored Feb 22, 2023
1 parent 7ab7ddc commit 979a20c
Show file tree
Hide file tree
Showing 6 changed files with 1,145 additions and 223 deletions.
122 changes: 102 additions & 20 deletions compiler/test/stdlib/queue.test.gr
Original file line number Diff line number Diff line change
@@ -1,36 +1,118 @@
module QueueTest

include "queue"
from Queue use { Immutable as ImmQ }
include "list"

// Mutable queue tests

let empty = Queue.make()
assert Queue.isEmpty(empty)
assert Queue.size(empty) == 0
assert Queue.peek(empty) == None
assert Queue.pop(empty) == None
assert Queue.size(empty) == 0

let queue = Queue.make()
Queue.push(1, queue)
Queue.push(2, queue)
Queue.push(3, queue)

assert !Queue.isEmpty(queue)
assert Queue.size(queue) == 3
assert Queue.peek(queue) == Some(1)

assert Queue.pop(queue) == Some(1)
assert Queue.peek(queue) == Some(2)
assert Queue.size(queue) == 2

Queue.push(4, queue)
assert Queue.size(queue) == 3
assert Queue.peek(queue) == Some(2)
let copy = Queue.copy(queue)
Queue.pop(copy)
assert Queue.size(copy) == 2
assert Queue.size(queue) == 3
Queue.clear(queue)
assert Queue.size(queue) == 0
assert Queue.peek(queue) == None

// test that expansion works
let queue = Queue.makeSized(3)
Queue.push(0, queue)
Queue.push(1, queue)
Queue.push(2, queue)
Queue.push(3, queue)
assert Queue.pop(queue) == Some(0)
assert Queue.pop(queue) == Some(1)
assert Queue.pop(queue) == Some(2)
assert Queue.pop(queue) == Some(3)
assert Queue.pop(queue) == None

// test that the "circular" behavior of the circular queue works as expected
let queue = Queue.makeSized(4)
let push = x => () => Queue.push(x, queue)
let pop = () => ignore(Queue.pop(queue))
let actions = [
push(1),
push(2),
push(3),
push(4),
pop,
pop,
pop,
push(5),
push(6),
pop,
pop,
push(7),
push(8),
push(9),
]
List.forEach(action => action(), actions)

assert Queue.size(queue) == 4
assert Queue.peek(queue) == Some(6)

Queue.push(10, queue)
assert Queue.size(queue) == 5
assert Queue.pop(queue) == Some(6)
assert Queue.pop(queue) == Some(7)
assert Queue.pop(queue) == Some(8)
assert Queue.pop(queue) == Some(9)
assert Queue.pop(queue) == Some(10)
assert Queue.pop(queue) == None

// Immutable queue tests

// 1 <- 2 <- 3
let sampleQueue = Queue.push(3, Queue.push(2, Queue.push(1, empty)))
let sampleQueue = ImmQ.push(3, ImmQ.push(2, ImmQ.push(1, ImmQ.empty)))

// Queue.isEmpty
// ImmQ.isEmpty

assert Queue.isEmpty(empty)
assert !Queue.isEmpty(sampleQueue)
assert ImmQ.isEmpty(ImmQ.empty)
assert !ImmQ.isEmpty(sampleQueue)

// Queue.peek
// ImmQ.peek

assert Queue.peek(empty) == None
assert Queue.peek(sampleQueue) == Some(1)
assert ImmQ.peek(ImmQ.empty) == None
assert ImmQ.peek(sampleQueue) == Some(1)

// Queue.push
// ImmQ.push

assert Queue.peek(Queue.push(1, empty)) == Some(1)
assert Queue.peek(Queue.push(4, sampleQueue)) == Some(1)
assert ImmQ.peek(ImmQ.push(1, ImmQ.empty)) == Some(1)
assert ImmQ.peek(ImmQ.push(4, sampleQueue)) == Some(1)

// Queue.pop
// ImmQ.pop

assert Queue.isEmpty(Queue.pop(empty))
assert Queue.isEmpty(Queue.pop(Queue.push(1, empty)))
assert Queue.isEmpty(Queue.pop(Queue.pop(Queue.pop(sampleQueue))))
assert Queue.peek(Queue.pop(sampleQueue)) == Some(2)
assert Queue.peek(Queue.pop(Queue.push(4, Queue.pop(sampleQueue)))) == Some(3)
assert ImmQ.isEmpty(ImmQ.pop(ImmQ.empty))
assert ImmQ.isEmpty(ImmQ.pop(ImmQ.push(1, ImmQ.empty)))
assert ImmQ.isEmpty(ImmQ.pop(ImmQ.pop(ImmQ.pop(sampleQueue))))
assert ImmQ.peek(ImmQ.pop(sampleQueue)) == Some(2)
assert ImmQ.peek(ImmQ.pop(ImmQ.push(4, ImmQ.pop(sampleQueue)))) == Some(3)

// Queue.size
// ImmQ.size

assert Queue.size(empty) == 0
assert Queue.size(sampleQueue) == 3
assert Queue.size(Queue.pop(Queue.pop(sampleQueue))) == 1
assert ImmQ.size(ImmQ.empty) == 0
assert ImmQ.size(sampleQueue) == 3
assert ImmQ.size(ImmQ.pop(ImmQ.pop(sampleQueue))) == 1
96 changes: 76 additions & 20 deletions compiler/test/stdlib/stack.test.gr
Original file line number Diff line number Diff line change
@@ -1,36 +1,92 @@
module StackTest

include "stack"
from Stack use { Immutable as ImmStack }

// Mutable stack tests

let empty = Stack.make()
assert Stack.isEmpty(empty)
assert Stack.size(empty) == 0
assert Stack.peek(empty) == None
assert Stack.pop(empty) == None
assert Stack.size(empty) == 0

let stack = Stack.make()
Stack.push(1, stack)
Stack.push(2, stack)
Stack.push(3, stack)

assert !Stack.isEmpty(stack)
assert Stack.size(stack) == 3
assert Stack.peek(stack) == Some(3)

assert Stack.pop(stack) == Some(3)
assert Stack.peek(stack) == Some(2)
assert Stack.size(stack) == 2

Stack.push(4, stack)
assert Stack.size(stack) == 3
assert Stack.peek(stack) == Some(4)
let copy = Stack.copy(stack)
Stack.pop(copy)
assert Stack.size(copy) == 2
assert Stack.size(stack) == 3
Stack.clear(stack)
assert Stack.size(stack) == 0
assert Stack.peek(stack) == None

let stack = Stack.makeSized(4)

Stack.push(1, stack)
Stack.push(2, stack)
Stack.push(3, stack)
Stack.push(4, stack)
Stack.push(5, stack)
assert Stack.size(stack) == 5
assert Stack.pop(stack) == Some(5)
assert Stack.pop(stack) == Some(4)
assert Stack.pop(stack) == Some(3)
assert Stack.pop(stack) == Some(2)
assert Stack.pop(stack) == Some(1)
assert Stack.pop(stack) == None

// Immutable Stack tests

// 1 <- 2 <- 3
let sampleStack = Stack.push(3, Stack.push(2, Stack.push(1, empty)))
let sampleStack = ImmStack.push(
3,
ImmStack.push(2, ImmStack.push(1, ImmStack.empty))
)

// Stack.isEmpty
// ImmStack.isEmpty

assert Stack.isEmpty(empty)
assert !Stack.isEmpty(sampleStack)
assert ImmStack.isEmpty(ImmStack.empty)
assert !ImmStack.isEmpty(sampleStack)

// Stack.peek
// ImmStack.peek

assert Stack.peek(empty) == None
assert Stack.peek(sampleStack) == Some(3)
assert ImmStack.peek(ImmStack.empty) == None
assert ImmStack.peek(sampleStack) == Some(3)

// Stack.push
// ImmStack.push

assert Stack.peek(Stack.push(1, empty)) == Some(1)
assert Stack.peek(Stack.push(4, sampleStack)) == Some(4)
assert ImmStack.peek(ImmStack.push(1, ImmStack.empty)) == Some(1)
assert ImmStack.peek(ImmStack.push(4, sampleStack)) == Some(4)

// Stack.pop
// ImmStack.pop

assert Stack.isEmpty(Stack.pop(empty))
assert Stack.isEmpty(Stack.pop(Stack.push(1, empty)))
assert Stack.isEmpty(Stack.pop(Stack.pop(Stack.pop(sampleStack))))
assert Stack.peek(Stack.pop(sampleStack)) == Some(2)
assert Stack.peek(Stack.pop(Stack.push(4, Stack.pop(sampleStack)))) == Some(2)
assert ImmStack.isEmpty(ImmStack.pop(ImmStack.empty))
assert ImmStack.isEmpty(ImmStack.pop(ImmStack.push(1, ImmStack.empty)))
assert ImmStack.isEmpty(ImmStack.pop(ImmStack.pop(ImmStack.pop(sampleStack))))
assert ImmStack.peek(ImmStack.pop(sampleStack)) == Some(2)
assert ImmStack.peek(
ImmStack.pop(ImmStack.push(4, ImmStack.pop(sampleStack)))
) ==
Some(2)

// Stack.size
// ImmStack.size

assert Stack.size(empty) == 0
assert Stack.size(sampleStack) == 3
assert Stack.size(Stack.pop(Stack.pop(sampleStack))) == 1
assert ImmStack.size(ImmStack.empty) == 0
assert ImmStack.size(sampleStack) == 3
assert ImmStack.size(ImmStack.pop(ImmStack.pop(sampleStack))) == 1
Loading

0 comments on commit 979a20c

Please sign in to comment.