o
    Xi*                     @  s   d Z ddlmZ g dZddlZddlZddlmZ ddlZ	e
eZG dd deZG dd	 d	eZG d
d de	jjZdddZdS )zAName fix pass for ensuring unique names for all values and nodes.    )annotations)NameFixPassNameGeneratorSimpleNameGeneratorN)Protocolc                   @  s    e Zd ZdddZdd	d
ZdS )r   nodeir.Nodereturnstrc                 C     dS )%Generate a preferred name for a node.N selfr   r   r   P/home/ubuntu/.local/lib/python3.10/site-packages/onnx_ir/passes/common/naming.pygenerate_node_name      z NameGenerator.generate_node_namevalueir.Valuec                 C  r   )&Generate a preferred name for a value.Nr   r   r   r   r   r   generate_value_name   r   z!NameGenerator.generate_value_nameNr   r   r	   r
   r   r   r	   r
   )__name__
__module____qualname__r   r   r   r   r   r   r      s    
r   c                   @  s$   e Zd ZdZdddZdd
dZdS )r   z)Base class for name generation functions.r   r   r	   r
   c                 C  
   |j pdS )r   r   namer   r   r   r   r   #      
z&SimpleNameGenerator.generate_node_namer   r   c                 C  r   )r   vr   r   r   r   r   r   '   r    z'SimpleNameGenerator.generate_value_nameNr   r   )r   r   r   __doc__r   r   r   r   r   r   r       s    
r   c                      sl   e Zd ZdZ	d)d* fddZd+ddZd,ddZd-ddZd.dd Zd/d#d$Z	d.d%d&Z
d/d'd(Z  ZS )0r   a  Pass for fixing names to ensure all values and nodes have unique names.

    This pass ensures that:
    1. Graph inputs and outputs have unique names (take precedence)
    2. All intermediate values have unique names (assign names to unnamed values)
    3. All values in subgraphs have unique names within their graph and parent graphs
    4. All nodes have unique names within their graph

    The pass maintains global uniqueness across the entire model.

    You can customize the name generation functions for nodes and values by passing
    a subclass of :class:`NameGenerator`.

    For example, you can use a custom naming scheme like this::

        class CustomNameGenerator:
            def custom_node_name(node: ir.Node) -> str:
                return f"custom_node_{node.op_type}"

            def custom_value_name(value: ir.Value) -> str:
                return f"custom_value_{value.type}"

        name_fix_pass = NameFixPass(name_generator=CustomNameGenerator())

    .. versionadded:: 0.1.6
    Nname_generatorNameGenerator | Noner	   Nonec                   s   t    |p	t | _dS )a  Initialize the NameFixPass with custom name generation functions.

        Args:
            name_generator (NameGenerator, optional): An instance of a subclass of
                :class:`NameGenerator` to customize name generation for nodes and values.
                If not provided, defaults to a basic implementation that uses
                the node's or value's existing name or a generic name like "node" or "v".
        N)super__init__r   _name_generator)r   r#   	__class__r   r   r'   H   s   
zNameFixPass.__init__modelir.Modelir.passes.PassResultc                 C  s:   |  |j}|j D ]	}|  |p|}qtjj||dS )N)modified)_fix_graph_namesgraph	functionsvaluesirpasses
PassResult)r   r+   r.   functionr   r   r   callW   s   zNameFixPass.call
graph_likeir.Graph | ir.Functionboolc                   s   d t  t  gt  gt t }d fdd}dfdd}tjj|||dD ]D}|jsC|d	 |rBd
 n|d	 |rNd
 |j	D ]}|durc
|d	 rcd
 qQ|jD ]}
|d	 rud
 qgq2 S )z@Fix names in a graph and return whether modifications were made.Fr	   r%   c                   s    td   t  | jD ]}|d r d q| jD ]}|d r2d q$t| tjrM| j	 D ]}|d rLd q>dS dS )z!Callback for entering a subgraph.TN)
appendsetinputs_process_valueoutputs
isinstancer3   Graphinitializersr2   )r8   input_valueoutput_valueinitializerr.   scoped_used_node_namesscoped_used_value_namesseen_valuesr   value_counterr   r   enter_graphq   s.   

z1NameFixPass._fix_graph_names.<locals>.enter_graphc                   s          dS )z Callback for exiting a subgraph.N)pop)_)rH   rI   r   r   
exit_graph   s   z0NameFixPass._fix_graph_names.<locals>.exit_graph)rL   rO   r;   TN)r	   r%   )r=   collectionsCounterr3   	traversalRecursiveGraphIteratorr   _assign_node_name_fix_duplicate_node_namer>   r?   r@   )r   r8   node_counterrL   rO   r   rD   rE   r   rG   r   r/   a   sD   



zNameFixPass._fix_graph_namesr   r   used_value_namesset[str]rJ   set[ir.Value]rK   collections.Counter[str]c                 C  sP   ||v rdS d}|j s| |||}n| |||}|j dus!J || |S )z8Process a value only if it hasn't been processed before.FN)r   _assign_value_name_fix_duplicate_value_nameadd)r   r   rW   rJ   rK   r.   r   r   r   r?      s   
zNameFixPass._process_value
used_namescounterc                 C  :   |j rJ d| j|}t||||_ td|j  dS )z<Assign a name to an unnamed value. Returns True if modified.zDvalue should not have a name already if function is called correctlyz!Assigned name %s to unnamed valueT)r   r(   r   !_find_and_record_next_unique_nameloggerdebug)r   r   r^   r_   preferred_namer   r   r   r[         zNameFixPass._assign_value_namer   r   c                 C  r`   )z;Assign a name to an unnamed node. Returns True if modified.zCnode should not have a name already if function is called correctlyz Assigned name %s to unnamed nodeT)r   r(   r   ra   rb   rc   )r   r   r^   r_   rd   r   r   r   rT      re   zNameFixPass._assign_node_namec                 C  V   |j }|s	J d||vr|| dS | j|}t||||_ td||j  dS )zQFix a value's name if it conflicts with existing names. Returns True if modified.z@value should have a name already if function is called correctlyFz*Renamed value from %s to %s for uniquenessT)r   r]   r(   r   ra   rb   rc   )r   r   r^   r_   original_name	base_namer   r   r   r\      s   
z%NameFixPass._fix_duplicate_value_namec                 C  rf   )zPFix a node's name if it conflicts with existing names. Returns True if modified.z?node should have a name already if function is called correctlyFz)Renamed node from %s to %s for uniquenessT)r   r]   r(   r   ra   rb   rc   )r   r   r^   r_   rg   rh   r   r   r   rU      s   
z$NameFixPass._fix_duplicate_node_name)N)r#   r$   r	   r%   )r+   r,   r	   r-   )r8   r9   r	   r:   )
r   r   rW   rX   rJ   rY   rK   rZ   r	   r:   )r   r   r^   rX   r_   rZ   r	   r:   )r   r   r^   rX   r_   rZ   r	   r:   )r   r   r   r"   r'   r7   r/   r?   r[   rT   r\   rU   __classcell__r   r   r)   r   r   ,   s    



S


r   rd   r
   r^   rX   r_   rZ   r	   c                 C  sD   | }||v r||   d7  < |  d||   }||v s| | |S )zGGenerate a unique name based on the preferred name and current counter.   rN   )r]   )rd   r^   r_   new_namer   r   r   ra     s   
ra   )rd   r
   r^   rX   r_   rZ   r	   r
   )r"   
__future__r   __all__rP   loggingtypingr   onnx_irr3   	getLoggerr   rb   r   r   r4   InPlacePassr   ra   r   r   r   r   <module>   s   

 d