"""
Node with self-reference and __repr__
"""


class LListNode:
    """Node to be used in linked list"""
    
    def __init__(self: 'LListNode', value: object =None, 
                 nxt: 'LListNode' =None) -> None:
        """Create a new LListNode"""
        
        self.value, self.nxt = value, nxt
        
    def __repr__(self: 'LListNode') -> str:
        """String representation of this LListNode"""
        
        return 'LListNode(' + str(self.value) + ', ' + str(self.nxt) + ')'
    

"""Stack ADT.

Operations:
	pop: remove and return top item
        push(item): store item on top of stack
        is_empty: return whether stack is empty.
"""

class Stack:

    """A last-in, first-out (LIFO) stack of items"""

    def __init__(self: 'Stack') -> None:
        """A new empty Stack."""
        self.top = None
        
    def pop(self: 'Stack') -> object:
        """Remove and return the top item"""
        self.top, value = self.top.nxt, self.top.value
        return value

    def is_empty(self: 'Stack') -> bool:
        """Return whether the stack is empty."""
        return not self.top
        
    
    def push(self: 'Stack' , o: object) -> None:
        """Place o on top of the stack"""
        self.top = LListNode(o, self.top)