o
    Xi,                     @  s"  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 g dZ
ddl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ZG dd deZejG dd dZG dd dejZG dd deZG dd deZG dd deZG dd deZG dd deZd!dd Z dS )"z!Passes infrastructure for the IR.    )annotationsN)Sequence)Literalfinal)PassBase
SequentialInPlacePassFunctionalPassPassManager
PassResultfunctionalizeInvariantErrorPreconditionErrorPostconditionError	PassErrorc                   @     e Zd ZdZdS )r   z%Raised when an invariant is violated.N__name__
__module____qualname____doc__ r   r   N/home/ubuntu/.local/lib/python3.10/site-packages/onnx_ir/passes/_pass_infra.pyr   ,       r   c                   @  r   )r   z'Raised when a precondition is violated.Nr   r   r   r   r   r   0   r   r   c                   @  r   )r   z(Raised when a postcondition is violated.Nr   r   r   r   r   r   4   r   r   c                   @  r   )r   z*Raised when an error occurs during a pass.Nr   r   r   r   r   r   8   r   r   c                   @  s"   e Zd ZU dZded< ded< dS )r   zResult of a pass.

    Attributes:
        model: The transformed model.
        modified: Whether the resulting model is different from the input model.
    ir.ModelmodelboolmodifiedN)r   r   r   r   __annotations__r   r   r   r   r   <   s   
 r   c                   @  st   e Zd ZdZeejdddZeejdddZeddd	Z	dddZ
ejdddZdddZdddZdS )r   a  Base class for all passes.

    ``in_place`` and ``changes_input`` properties and what they mean:

    +------------+------------------+----------------------------+
    |            | changes_inputs   | not changes_inputs         |
    +------------+------------------+----------------------------+
    | in_place   | in place         | Side-effect-only pass      |
    +------------+------------------+----------------------------+
    | not        | destructive      | functional                 |
    | in_place   |                  |                            |
    +------------+------------------+----------------------------+
    returnr   c                 C     t )zWhether the pass modifies the model in place and returns it.

        If True, the pass will return the same model object that was passed in.
        If False, the pass will return a new model object.
        NotImplementedErrorselfr   r   r   in_placeX   s   zPassBase.in_placec                 C  r    )z&Whether the pass modifies input model.r!   r#   r   r   r   changes_inputb      zPassBase.changes_inputc                 C  s   | j  o| jS )zWhether the pass will destroy the input model when ``in_place=False``.

        A pass is destructive if it is not in place and it modifies the input model.
        )r%   r&   r#   r   r   r   destructiveh   s   zPassBase.destructivemodel_or_resultir.Model | PassResultr   c             
   C  s$  t |tr	|j}n|}z| | W n ty     ty0 } ztd| jj d|d }~ww | |}z| 	|j W n t
yF     ty\ } zt
d| jj d|d }~ww t |tsltd| jj d| jr~|j|ur~td| jj d| js|j|u rtd| jj d|S )	NzPre-condition for pass 'z' failedzPost-condition for pass 'zThe result of the pass 'zK' should be type PassResult. Please create one with ir.passes.PassResult().z
The pass 'z' is declared in-place, but the model returned is *not* the same object as the input model. Pass developer: Pass should return the same model object or the in_place property should return False.z' is declared not in-place, but the model returned *is* the same object as the input model. Pass developer: Pass should return a new model object or the in_place property should return True.)
isinstancer   r   requiresr   	Exception	__class__r   callensuresr   	TypeErrorr%   r   )r$   r)   r   eresultr   r   r   __call__p   sR   


zPassBase.__call__r   r   c                 C     dS )z"The main entry point for the pass.Nr   r$   r   r   r   r   r/      s   zPassBase.callNonec                 C     ~dS )zPre-conditions for the pass.

        This is optional to implement, will be called before call() if run by a pass manager.
        Nr   r6   r   r   r   r,         zPassBase.requiresc                 C  r8   )zPost-conditions for the pass.

        This is optional to implement, will be called after call() if run by a pass manager.
        Nr   r6   r   r   r   r0      r9   zPassBase.ensuresNr   r   )r)   r*   r   r   r   r   r   r   )r   r   r   r7   )r   r   r   r   propertyabcabstractmethodr%   r&   r(   r4   r/   r,   r0   r   r   r   r   r   I   s    
0
r   c                   @  4   e Zd ZdZeed	ddZeed	ddZdS )
r   z=A pass that modifies the input model in place and returns it.r   Literal[True]c                 C  r5   )zAn in-place pass is in place.Tr   r#   r   r   r   r%      r'   zInPlacePass.in_placec                 C  r5   )z)An in-place pass changes the input model.Tr   r#   r   r   r   r&      r'   zInPlacePass.changes_inputN)r   r@   r   r   r   r   r<   r   r%   r&   r   r   r   r   r          r   c                   @  r?   )
r	   zDA pass that returns a new model but does not modify the input model.r   Literal[False]c                 C  r5   )z"A functional pass is not in place.Fr   r#   r   r   r   r%      r'   zFunctionalPass.in_placec                 C  r5   )z2A functional pass does not change the input model.Fr   r#   r   r   r   r&      r'   zFunctionalPass.changes_inputN)r   rC   rA   r   r   r   r   r	      rB   r	   c                   @  s@   e Zd ZdZdddZeddd	Zedd
dZdddZdS )r   a  Run a sequence of passes in order.

    Example::
        import onnx_ir as ir
        import onnx_ir.passes.common as common_passes

        passes = ir.passes.Sequential(
            common_passes.DeduplicateHashedInitializersPass(size_limit=1024 * 1024),
            common_passes.CommonSubexpressionEliminationPass(),
            common_passes.ClearMetadataAndDocStringPass(),
        )
        result = passes(model)
    passesr   c                 G  sD   |st d|| _tdd |D | _| jd jp| jd j| _d S )Nz&Sequential must take at least one passc                 s  s    | ]}|j V  qd S N)r%   ).0pass_r   r   r   	<genexpr>   s    z&Sequential.__init__.<locals>.<genexpr>r   )
ValueErrorrD   all	_in_placer&   r%   _changes_input)r$   rD   r   r   r   __init__   s
   zSequential.__init__r   r   c                 C     | j S rE   )rK   r#   r   r   r   r%         zSequential.in_placec                 C  rN   rE   )rL   r#   r   r   r   r&      rO   zSequential.changes_inputr   r   r   c                 C  s   d}t | jD ]=\}}td|| z||}W n# ty; } zdd | jd | D }td| d| |d }~ww |j}|pC|j}qt||S )NFzRunning the %s-th pass '%s'c                 S  s   g | ]}t |qS r   )str)rF   pr   r   r   
<listcomp>   s    z#Sequential.call.<locals>.<listcomp>z$An error occurred when running the 'z#' pass after the following passes: )		enumeraterD   loggerdebugr-   r   r   r   r   )r$   r   r   irG   pass_resultr2   prev_pass_namesr   r   r   r/      s&   
zSequential.callN)rD   r   r:   r;   )	r   r   r   r   rM   r<   r%   r&   r/   r   r   r   r   r      s    

r   c                      s6   e Zd ZdZ		dd fd
dZd fddZ  ZS )r
   a;  Pass manager for the IR.

    The PassManager is a Pass that runs a sequence of passes on a model.

    Example::
        import onnx_ir as ir
        import onnx_ir.passes.common as common_passes

        model = ir.load("model.onnx")
        passes = ir.passes.PassManager(
            [
                # Pass managers can be nested
                ir.passes.PassManager(
                    [
                        common_passes.DeduplicateHashedInitializersPass(size_limit=1024 * 1024),
                        common_passes.CommonSubexpressionEliminationPass(),
                    ],
                    steps=2,
                    early_stop=True,
                ),
                common_passes.ClearMetadataAndDocStringPass(),
            ],
            steps=2,
            early_stop=False,
        )

        # Apply the passes to the model
        result = passes(model)

    Attributes:
        passes: The passes to run.
        steps: The number of times to run the passes.
        early_stop: Whether to stop running the passes if the graph stops changing.
       TrD   Sequence[PassBase]stepsint
early_stopr   c                   s   t  j|  || _|| _d S rE   )superrM   r[   r]   )r$   rD   r[   r]   r.   r   r   rM   ,  s   
zPassManager.__init__r   r   r   r   c                   s   d}t | jD ]6}zt |}W n ty% } ztd| |d}~ww |j}|j}|p/|}|s=| jr=t	
d|  nqt||S )zPRun the set of passes `steps` number of times or until the graph stops changing.FzAn error occurred at step Nz9PassManager: No more graph changes detected after step %s)ranger[   r^   r/   r-   r   r   r   r]   rT   infor   )r$   r   overall_modifiedstepstep_resultr2   r   r_   r   r   r/   7  s    

zPassManager.call)rY   T)rD   rZ   r[   r\   r]   r   r;   )r   r   r   r   rM   r/   __classcell__r   r   r_   r   r
     s    &r
   c                   @  s    e Zd ZdddZdd
dZdS )_FunctionalPassWrapper
inner_passr   r   r7   c                 C  s
   || _ d S rE   )_inner_pass)r$   rg   r   r   r   rM   K  s   
z_FunctionalPassWrapper.__init__r   r   r   c                 C  s   |  | S rE   )rh   cloner6   r   r   r   r/   N  s   z_FunctionalPassWrapper.callN)rg   r   r   r7   r;   )r   r   r   rM   r/   r   r   r   r   rf   J  s    
rf   pass_instancer   c                 C  s   t | S )a
  Produce a functional pass from a given pass.

    A new functional pass is created that clones the input model before running the pass.

    .. versionadded:: 0.1.14

    Args:
        pass_instance: The pass to convert.

    Returns:
        A functional pass.
    )rf   )rj   r   r   r   r   R  s   r   )rj   r   r   r	   )!r   
__future__r   dataclassesloggingcollections.abcr   typingr   r   __all__r=   onnx_irir	getLoggerr   rT   r-   r   r   r   RuntimeErrorr   	dataclassr   ABCr   r   r	   r   r
   rf   r   r   r   r   r   <module>   s.   
k4B