[docs]@guppy.structclassStack(Generic[T,MAX_SIZE]):# type: ignore[misc]"""A last-in-first-out (LIFO) growable collection of values. To ensure static allocation, the maximum stack size must be specified in advance and is tracked in the type. For example, the `Stack[int, 10]` is a stack that can hold at most 10 integers. Use `empty_stack` to construct a new stack. """#: Underlying buffer holding the stack elements.#:#: INVARIANT: All array elements up to and including index `self.end - 1` are#: `option.some` variants and all further ones are `option.nothing`.buf:array[Option[T],MAX_SIZE]# type: ignore[valid-type, type-arg]#: Index of the next free index in `self.buf`.end:int
[docs]@guppy@no_type_checkdef__len__(self:Stack[T,MAX_SIZE])->int:"""Returns the number of elements currently stored in the stack."""returnself.end
[docs]@guppy@no_type_checkdef__iter__(self:Stack[T,MAX_SIZE]@owned)->Stack[T,MAX_SIZE]:"""Returns an iterator over the elements in the stack from top to bottom."""returnself
[docs]@guppy@no_type_checkdefpush(self:Stack[T,MAX_SIZE]@owned,elem:T@owned)->Stack[T,MAX_SIZE]:"""Adds an element to the top of the stack. Panics if the stack has already reached its maximum size. """ifself.end>=MAX_SIZE:panic("Stack.push: max size reached")self.buf[self.end].swap(some(elem)).unwrap_nothing()returnStack(self.buf,self.end+1)
[docs]@guppy@no_type_checkdefpop(self:Stack[T,MAX_SIZE]@owned)->tuple[T,Stack[T,MAX_SIZE]]:""" Removes the top element from the stack and returns it. Panics if the stack is empty. """ifself.end<=0:panic("Stack.pop: stack is empty")elem=self.buf[self.end-1].take().unwrap()returnelem,Stack(self.buf,self.end-1)
[docs]@guppy@no_type_checkdefpeek(self:Stack[TCopyable,MAX_SIZE]@owned,)->tuple[TCopyable,Stack[TCopyable,MAX_SIZE]]:"""Returns a copy of the top element of the stack without removing it. Panics if the stack is empty. Note that this operation is only allowed if the stack elements are copyable. """ifself.end<=0:panic("Stack.peek: stack is empty")elem=self.buf[self.end-1].unwrap()returnelem,Stack(self.buf,self.end)
[docs]@guppy@no_type_checkdefdiscard_empty(self:Stack[T,MAX_SIZE]@owned)->None:"""Discards a stack of potentially non-droppable elements assuming that the stack is empty. Panics if the stack is not empty. """ifself.end>0:panic("Stack.discard_empty: stack is not empty")foreleminself.buf:elem.unwrap_nothing()
[docs]@guppy@no_type_checkdefempty_stack()->Stack[T,MAX_SIZE]:"""Constructs a new empty stack."""buf=array(nothing[T]()for_inrange(MAX_SIZE))returnStack(buf,0)