RosettaCodeData/Task/Stack/Nim/stack.nim

74 lines
1.5 KiB
Nim

import math
type
EStackEmpty = object of E_Base
TStack* [A] = object
data: seq[A]
count: int
proc initStack*[A](initialSize = 32): TStack[A] =
assert isPowerOfTwo(initialSize)
result.count = 0
newSeq(result.data,initialSize)
proc cap*[A] (s: TStack[A]): int =
result = s.data.len
proc len*[A](stack: TStack[A]): int =
result = stack.count
proc push*[A](s: var TStack[A], item: A) =
if s.count == s.data.len:
# not enough room, make container bigger
var d: Seq[A]
newSeq(d,s.len * 2)
for i in 0 .. s.data.len - 1:
shallowCopy(d[i],s.data[i])
shallowCopy(s.data,d)
s.data[s.count] = item
inc(s.count)
proc pop*[A](s: var TStack[A]): A {.raises: [EStackEmpty].}=
if s.count == 0:
raise newException(EStackEmpty,"the stack is empty")
dec(s.count)
result = s.data[s.count]
proc top*[A](s: TStack[A]): A =
result = s.data[s.count - 1]
proc isEmpty*[A](s: var TStack[A]): bool =
return s.count == 0
#Tests
when isMainModule:
var stk: TStack[char] = initStack[char](4)
stk.push('a')
stk.push('b')
stk.push('c')
stk.push('d')
assert(stk.count == 4)
assert(stk.data.len == 4)
stk.push('e')
assert(stk.cap == 8)
assert(stk.top == 'e')
discard stk.pop
discard stk.pop
discard stk.pop
discard stk.pop
assert(stk.isEmpty == false)
discard stk.pop
assert(stk.isEmpty == true)
try:
discard stk.pop
except:
let
e = getCurrentException()
msg = getCurrentExceptionMsg()
echo "Exception: [[", repr(e), "]] msg: ", msg