o
    j9:j                     @   s   d dl Z d dlmZ d dlmZ d dlmZ e eZ	g dZ
dedefdd	Ze jfdedefd
dZ		ddededB dedB fddZdeeegef dee fddZdedefddZdedefddZG dd dZdS )     NCallablewrapsunwrap)PassManagerinplace_wrapperlog_hook	loop_pass this_before_that_pass_constraint"these_before_those_pass_constraintfnreturnc                    s   t   fdd}|S )z
    Convenience wrapper for passes which modify an object inplace. This
    wrapper makes them return the modified object instead.

    Args:
        fn (Callable[Object, Any])

    Returns:
        wrapped_fn (Callable[Object, Object])
    c                    s    |  | S N )gmr   r   c/home/nk/hobo-godmode/plappi-mvp/.venv/lib/python3.10/site-packages/torch/fx/passes/pass_manager.py
wrapped_fn"   s   z#inplace_wrapper.<locals>.wrapped_fnr   )r   r   r   r   r   r	      s   r	   c                    s   t   fdd}|S )a  
    Logs callable output.

    This is useful for logging output of passes. Note ``inplace_wrapper`` replaces
    the pass output with the modified object. If we want to log the original
    output, apply this wrapper before ``inplace_wrapper``.

    Example::

        def my_pass(d: Dict) -> bool:
            changed = False
            if "foo" in d:
                d["foo"] = "bar"
                changed = True
            return changed


        pm = PassManager(passes=[inplace_wrapper(log_hook(my_pass))])

    Args:
        fn (Callable[Type1, Type2])
        level: logging level (e.g. logging.INFO)

    Returns:
        wrapped_fn (Callable[Type1, Type2])
    c                    s    | }t d | |S )NzRan pass %s	 Return value: %s)loggerlog)r   valr   levelr   r   r   F   s   zlog_hook.<locals>.wrapped_fnr   )r   r   r   r   r   r   r
   *   s   r
   	base_passn_iter	predicatec                    s4   duduA st dt  fdd}|S )aW  
    Convenience wrapper for passes which need to be applied multiple times.

    Exactly one of `n_iter`or `predicate` must be specified.

    Args:
        base_pass (Callable[Object, Object]): pass to be applied in loop
        n_iter (int, optional): number of times to loop pass
        predicate (Callable[Object, bool], optional):

    Nz8Exactly one of `n_iter`or `predicate` must be specified.c                    sh   | }d urdkrt D ]} |}q|S d ur)|r' |}|s|S td d d)Nr   z3loop_pass must be given positive int n_iter (given z) xor predicate (given ))rangeRuntimeError)sourceoutput_r   r   r   r   r   new_passb   s"   
	zloop_pass.<locals>.new_pass)AssertionErrorr   )r   r   r   r%   r   r$   r   r   O   s
   r   
constraintpassesc                 C   sl   t |D ]/\}}t ||d d  D ] \}}| ||rqtd| d| d| d| d| d| dqd S )	N   z,pass schedule constraint violated. Expected z before z but found z
 at index z and z	 at indexz in pass list.)	enumerater    )r'   r(   iajbr   r   r   "_validate_pass_schedule_constrainty   s"   
r/   thisthatc                       dt dt f fdd}|S )zd
    Defines a partial order ('depends on' function) where `this` must occur
    before `that`.
    r,   r.   c                    s   |  kp|kS r   r   r,   r.   r1   r0   r   r   
depends_on   s   z4this_before_that_pass_constraint.<locals>.depends_onr   )r0   r1   r5   r   r4   r   r      s   r   thesethosec                    r2   )a\  
    Defines a partial order ('depends on' function) where ``these`` must occur
    before ``those``. Where the inputs are 'unwrapped' before comparison.

    For example, the following pass list and constraint list would be invalid::

        passes = [
            loop_pass(pass_b, 3),
            loop_pass(pass_a, 5),
        ]

        constraints = [these_before_those_pass_constraint(pass_a, pass_b)]

    Args:
        these (Callable): pass which should occur first
        those (Callable): pass which should occur later

    Returns:
        depends_on (Callable[[Object, Object], bool])
    r,   r.   c                    s   t | kpt | kS r   r   r3   r6   r7   r   r   r5      s   z6these_before_those_pass_constraint.<locals>.depends_onr   )r6   r7   r5   r   r8   r   r      s   r   c                   @   s   e Zd ZU dZee ed< ee ed< dZeed< 		dddZ	e
d	d
 ZdefddZdd Zdee fddZdd Zdd Zdd ZdS )r   aT  
    Construct a PassManager.

    Collects passes and constraints. This defines the pass schedule, manages
    pass constraints and pass execution.

    Args:
        passes (Optional[List[Callable]]): list of passes. A pass is a
            callable which modifies an object and returns modified object
        constraint (Optional[List[Callable]]): list of constraints. A
            constraint is a callable which takes two passes (A, B) and returns
            True if A depends on B and False otherwise. See implementation of
            `this_before_that_pass_constraint` for example.
    r(   constraintsF
_validatedNc                 C   s   |pg | _ |pg | _d S r   )r(   r9   )selfr(   r9   r   r   r   __init__   s   
zPassManager.__init__c                 C   s   t |}|S r   )r   )clsr(   pmr   r   r   build_from_passlist   s   zPassManager.build_from_passlist_passc                 C      | j | d| _d S NF)r(   appendr:   )r;   r@   r   r   r   add_pass      
zPassManager.add_passc                 C   rA   rB   )r9   rC   r:   r;   r'   r   r   r   add_constraint   rE   zPassManager.add_constraint_passesc                    s0    d u rd S  fdd| j D }|| _ d| _d S )Nc                    s   g | ]	}|j  vr|qS r   )__name__).0psrH   r   r   
<listcomp>   s    z+PassManager.remove_pass.<locals>.<listcomp>F)r(   r:   )r;   rH   passes_leftr   rL   r   remove_pass   s
   
zPassManager.remove_passc                 C   sB   g }| j D ]}|j|jkr|| q|| q|| _ d| _d S rB   )r(   rI   rC   r:   )r;   _target_replacementrN   rK   r   r   r   replace_pass   s   

zPassManager.replace_passc                 C   s,   | j rdS | jD ]}t|| j qd| _ dS )z
        Validates that current pass schedule defined by `self.passes` is valid
        according to all constraints in `self.constraints`
        NT)r:   r9   r/   r(   rF   r   r   r   validate   s
   

zPassManager.validatec                 C   s$   |    |}| jD ]}||}q	|S r   )rS   r(   )r;   r!   outr@   r   r   r   __call__   s
   

zPassManager.__call__NN)rI   
__module____qualname____doc__listr   __annotations__r:   boolr<   classmethodr?   rD   rG   strrO   rR   rS   rU   r   r   r   r   r      s    
 


r   rV   )loggingcollections.abcr   	functoolsr   inspectr   	getLoggerrI   r   __all__r	   INFOr
   intr   r\   rZ   r/   r   r   r   r   r   r   r   <module>   s2   
'
*
