o
    Xi`)                     @  sr   d Z ddlmZ ddlmZmZmZ ddlmZm	Z	m
Z
 e	dZG dd dee ZG dd	 d	ee ee Zd
S )z@Mutable list for nodes in a graph with safe mutation properties.    )annotations)IterableIteratorSequence)GenericTypeVaroverloadTc                   @  s@   e Zd ZdZdZdd	d
ZedddZdddZdddZ	dS )_LinkBoxa  A link in a doubly linked list that has a reference to the actual object in the link.

    The :class:`_LinkBox` is a container for the actual object in the list. It is used to
    maintain the links between the elements in the linked list. The actual object is stored in the
    :attr:`value` attribute.

    By using a separate container for the actual object, we can safely remove the object from the
    list without losing the links. This allows us to remove the object from the list during
    iteration and place the object into a different list without breaking any chains.

    This is an internal class and should only be initialized by the :class:`DoublyLinkedSet`.

    Attributes:
        prev: The previous box in the list.
        next: The next box in the list.
        erased: A flag to indicate if the box has been removed from the list.
        owning_list: The :class:`DoublyLinkedSet` to which the box belongs.
        value: The actual object in the list.
    )nextowning_listprevvalueownerDoublyLinkedSet[T]r   T | NonereturnNonec                 C  s   | | _ | | _|| _|| _dS )aJ  Create a new link box.

        Args:
            owner: The linked list to which this box belongs.
            value: The value to be stored in the link box. When the value is None,
                the link box is considered erased (default). The root box of the list
                should be created with a None value.
        N)r   r   r   r   )selfr   r    r   H/home/ubuntu/.local/lib/python3.10/site-packages/onnx_ir/_linked_list.py__init__$   s   	
z_LinkBox.__init__boolc                 C  s
   | j d u S N)r   r   r   r   r   erased2   s   
z_LinkBox.erasedc                 C  s8   | j du r	td| j| j}}|||_|_d| _ dS )z@Remove the link from the list and detach the value from the box.Nz_LinkBox is already erased)r   
ValueErrorr   r   )r   r   next_r   r   r   erase6   s
   

z_LinkBox.erasestrc              	   C  s*   d| j d| j d| jj d| jj d	S )Nz	_LinkBox(z	, erased=z, prev=z, next=))r   r   r   r   r   r   r   r   __repr__@   s   *z_LinkBox.__repr__N)r   r   r   r   r   r   )r   r   )r   r   r   r   )
__name__
__module____qualname____doc__	__slots__r   propertyr   r   r!   r   r   r   r   r
      s    


r
   c                   @  s   e Zd ZdZdZd1d2dd	Zd3ddZd3ddZd4ddZe	d5ddZ
e	d6ddZ
dd Z
d7ddZd8d!d"Zd9d$d%Zd9d&d'Zd:d(d)Zd;d*d+Zd;d,d-Zd<d/d0ZdS )=DoublyLinkedSeta`  A doubly linked ordered set of nodes.

    The container can be viewed as a set as it does not allow duplicate values. The order of the
    elements is maintained. One can typically treat it as a doubly linked list with list-like
    methods implemented.

    Adding and removing elements from the set during iteration is safe. Moving elements
    from one set to another is also safe.

    During the iteration:
    - If new elements are inserted after the current node, the iterator will
        iterate over them as well.
    - If new elements are inserted before the current node, they will
        not be iterated over in this iteration.
    - If the current node is lifted and inserted in a different location,
        iteration will start from the "next" node at the _original_ location.

    Time complexity:
        Inserting and removing nodes from the set is O(1). Accessing nodes by index is O(n),
        although accessing nodes at either end of the set is O(1). I.e.
        ``linked_set[0]`` and ``linked_set[-1]`` are O(1).

    Values need to be hashable. ``None`` is not a valid value in the set.
    )_length_root_value_ids_to_boxesNvaluesIterable[T] | Noner   r   c                 C  s6   t | d }|| _d| _i | _|d ur| | d S d S )Nr   )r
   r+   r*   r,   extend)r   r-   root_r   r   r   r   `   s   
zDoublyLinkedSet.__init__Iterator[T]c                 c  sb    | j j}|| j ur/|j| urtd|d|js%|jdus!J |jV  |j}|| j us
dS dS )a  Iterate over the elements in the list.

        - If new elements are inserted after the current node, the iterator will
            iterate over them as well.
        - If new elements are inserted before the current node, they will
            not be iterated over in this iteration.
        - If the current node is lifted and inserted in a different location,
            iteration will start from the "next" node at the _original_ location.
        zElement  is not in the listN)r+   r   r   RuntimeErrorr   r   r   boxr   r   r   __iter__j   s   


zDoublyLinkedSet.__iter__c                 c  sH    | j j}|| j ur"|js|jdusJ |jV  |j}|| j us
dS dS )z7Iterate over the elements in the list in reverse order.N)r+   r   r   r   r4   r   r   r   __reversed__}   s   
zDoublyLinkedSet.__reversed__intc                 C  s   | j t| jksJ d| j S )Nz*Bug in the implementation: length mismatch)r*   lenr,   r   r   r   r   __len__   s   zDoublyLinkedSet.__len__indexr	   c                 C     d S r   r   r   r;   r   r   r   __getitem__      zDoublyLinkedSet.__getitem__sliceSequence[T]c                 C  r<   r   r   r=   r   r   r   r>      r?   c                 C  s   t |trt| | S || jks|| j k r&td| d| j d| j d|dk rBt| }t|}t| d D ]}t|}q9|S t| }t|}t|D ]}t|}qN|S )zFGet the node at the given index.

        Complexity is O(n).
        zIndex out of range: z not in range [-z, r    r      )	
isinstancer@   tupler*   
IndexErrorreversedr   rangeiter)r   r;   iteratoritem_r   r   r   r>      s"   


r5   _LinkBox[T]	new_valuec                 C  s   |du rt | jj d|j|u r|S |j| ur"td|jdt| }| jv r0| | t	| |}|j
}||_
||_||_
||_|  jd7  _|| j|< |S )a  Insert a new value after the given box.

        All insertion methods should call this method to ensure that the list is updated correctly.

        Example::
            Before: A  <->  B  <->  C
                    ^v0     ^v1     ^v2
            Call: _insert_one_after(B, v3)
            After:  A  <->  B  <->  new_box  <->  C
                    ^v0     ^v1       ^v3         ^v2

        Args:
            box: The box which the new value is to be inserted.
            new_value: The new value to be inserted.
        Nz does not support None valuesValue r2   rB   )	TypeError	__class__r#   r   r   r   idr,   remover
   r   r   r*   )r   r5   rM   new_value_idnew_boxoriginal_nextr   r   r   _insert_one_after   s"   




z!DoublyLinkedSet._insert_one_after
new_valuesIterable[T]c                 C  s   |}|D ]}|  ||}qdS )z/Insert multiple new values after the given box.N)rV   )r   r5   rW   insertion_pointrM   r   r   r   _insert_many_after   s   z"DoublyLinkedSet._insert_many_afterr   c                 C  sN   t | }| jvrtd|d| j| }|  |  jd8  _| j|= dS )zRemove a node from the list.rN   r2   rB   N)rQ   r,   r   r   r*   )r   r   value_idr5   r   r   r   rR      s   
zDoublyLinkedSet.removec                 C  s   |  | jj|}dS )zAppend a node to the list.N)rV   r+   r   )r   r   rK   r   r   r   append   s   zDoublyLinkedSet.appendc                 C  s   |D ]}|  | qd S r   )r\   )r   r-   r   r   r   r   r/      s   zDoublyLinkedSet.extendc                 C  s8   t | }| jvrtd|d| j| }| ||S )zInsert new nodes after the given node.

        Args:
            value: The value after which the new values are to be inserted.
            new_values: The new values to be inserted.
        rN   r2   )rQ   r,   r   rZ   r   r   rW   r[   rY   r   r   r   insert_after   s   
zDoublyLinkedSet.insert_afterc                 C  s:   t | }| jvrtd|d| j| j}| ||S )zInsert new nodes before the given node.

        Args:
            value: The value before which the new values are to be inserted.
            new_values: The new values to be inserted.
        rN   r2   )rQ   r,   r   r   rZ   r]   r   r   r   insert_before  s   zDoublyLinkedSet.insert_beforer   c                 C  s   dt |  dS )NzDoublyLinkedSet(r    )listr   r   r   r   r!     s   zDoublyLinkedSet.__repr__r   )r-   r.   r   r   )r   r1   )r   r8   )r;   r8   r   r	   )r;   r@   r   rA   )r5   rL   rM   r	   r   rL   )r5   rL   rW   rX   )r   r	   r   r   )r-   rX   r   r   )r   r	   rW   rX   r   r   r"   )r#   r$   r%   r&   r'   r   r6   r7   r:   r   r>   rV   rZ   rR   r\   r/   r^   r_   r!   r   r   r   r   r)   D   s(    



	

1





r)   N)r&   
__future__r   collections.abcr   r   r   typingr   r   r   r	   r
   r)   r   r   r   r   <module>   s   7