U
    ©Ê¹jî  ã                   @   sâ   d dl mZ d dlmZ d dlmZmZmZ d dlZe 	e
¡Zddddd	d
gZeedœdd„Zejfeedœdd„Zdeee ee dœdd„Zeeegef ee dœdd„Zeedœdd	„Zeedœdd
„ZG dd„ dƒZdS )é    ©Úwraps©Úunwrap)ÚCallableÚListÚOptionalNÚ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© ©ZgmÚval©r   r   ú[/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/fx/passes/pass_manager.pyÚ
wrapped_fn   s    z#inplace_wrapper.<locals>.wrapped_fnr   )r   r   r   r   r   r
      s    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.


    ```
    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Úlogr   ©r   Úlevelr   r   r   E   s    zlog_hook.<locals>.wrapped_fnr   )r   r   r   r   r   r   r   &   s    ©Ú	base_passÚn_iterÚ	predicatec                    s4   ˆdk	ˆdk	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                    sb   | }ˆd k	r,ˆdkr,t ˆƒD ]}ˆ |ƒ}qn2ˆd k	rHˆ|ƒr^ˆ |ƒ}q4ntdˆ› dˆ› d�ƒ‚|S )Nr   z3loop_pass must be given positive int n_iter (given z) xor predicate (given ú))ÚrangeÚRuntimeError)ÚsourceÚoutputÚ_r   r   r   Únew_pass_   s    ÿzloop_pass.<locals>.new_pass)ÚAssertionErrorr   )r   r   r   r&   r   r   r   r   O   s    ÿþ)Ú
constraintÚpassesc                 C   sn   t |ƒD ]`\}}t ||d d … ƒD ]B\}}| ||ƒr8q$td|› d|› d|› d|› d|› d|› d�ƒ‚q$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_constraintv   s    
(ÿr0   )ÚthisÚthatc                    s   t t dœ‡ ‡fdd„}|S )zd
    Defines a partial order ('depends on' function) where `this` must occur
    before `that`.
    ©r-   r/   c                    s   | ˆ kr|ˆkrdS dS ©NFTr   r3   ©r2   r1   r   r   Ú
depends_onŠ   s    z4this_before_that_pass_constraint.<locals>.depends_on©r   )r1   r2   r6   r   r5   r   r   „   s    ©ÚtheseÚthosec                    s   t t dœ‡ ‡fdd„}|S )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]
    r3   c                    s    t | ƒˆkrt |ƒˆ krdS dS r4   r   r3   r8   r   r   r6   «   s    z6these_before_those_pass_constraint.<locals>.depends_onr7   )r9   r:   r6   r   r8   r   r   ’   s    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edœdd„Zdd„ Zee dœ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)   r;   )Úselfr)   r;   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   s   | j  |¡ d| _d S ©NF)r)   Úappendr<   )r=   rB   r   r   r   Úadd_passÕ   s    zPassManager.add_passc                 C   s   | j  |¡ d| _d S rC   )r;   rD   r<   ©r=   r(   r   r   r   Úadd_constraintÙ   s    zPassManager.add_constraint)Ú_passesc                 C   s@   |d krd S g }| j D ]}|j|kr| |¡ q|| _ d| _d S rC   )r)   Ú__name__rD   r<   )r=   rH   Zpasses_leftZpsr   r   r   Úremove_passÝ   s    

zPassManager.remove_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<   r;   r0   r)   rF   r   r   r   Úvalidateç   s
    
zPassManager.validatec                 C   s$   |   ¡  |}| jD ]}||ƒ}q|S r   )rK   r)   )r=   r#   ÚoutrB   r   r   r   Ú__call__ò   s
    

zPassManager.__call__)NN)rI   Ú
__module__Ú__qualname__Ú__doc__r   r   Ú__annotations__r<   Úboolr>   ÚclassmethodrA   rE   rG   rJ   rK   rM   r   r   r   r   r	   ³   s   
  ý


)NN)Ú	functoolsr   Úinspectr   Útypingr   r   r   ÚloggingÚ	getLoggerrI   r   Ú__all__r
   ÚINFOr   Úintr   rR   r0   r   r   r	   r   r   r   r   Ú<module>   s(   
ú)( ÿ!