U
    ©Ê¹jf  ã                   @   s¬   d dl Z d dlmZmZmZmZmZ d dlZd dlZd dlm	Z	 d dlm
Z
mZ d dlmZmZmZmZ d dlmZmZmZ ddlmZ G dd	„ d	e
ƒZG d
d„ deƒZdS )é    N)ÚAnyÚCallableÚDictÚTupleÚOptional)ÚTransformerÚProxy)ÚArgumentÚTargetÚNodeÚmap_aggregate)Únormalize_moduleÚnormalize_functionÚcreate_type_hinté   )ÚAnnotateTypesWithSchemac                	       s¬   e Zd ZdZdejjedœ‡ fdd„Ze	e
dœ‡ fdd„Zdeeed
f eee
f eee
d
f  eeee
f  dœ‡ fdd„Zeeed
f eee
f dœ‡ fdd„Z‡  ZS )ÚNormalizeArgsa‡  
    Normalize arguments to Python targets. This means that
    `args/kwargs` will be matched up to the module/functional's
    signature and rewritten to exclusively kwargs in positional order
    if `normalize_to_only_use_kwargs` is true. Also populates default
    values. Does not support positional-only parameters or varargs
    parameters (*args, **kwargs).

    If the nodes have 'type' metadata, it will use it to disambiguate
    overloads. Otherwise, it will throw an error.

    Example usage:
        m = torchvision.models.resnet18()
        traced = torch.fx.symbolic_trace(m)
        traced = NormalizeArgs(traced).transform()
    T)ÚmoduleÚnormalize_to_only_use_kwargsc                    s   t ƒ  |¡ i | _|| _d S ©N)ÚsuperÚ__init__Únode_mapr   )Úselfr   r   ©Ú	__class__© ú^/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/fx/experimental/normalize.pyr   $   s    zNormalizeArgs.__init__)ÚnÚreturnc                    s´   |   ˆ¡\}}‡fdd„‰ tˆjˆ ƒ}t|tƒs4t‚tdd„ |D ƒƒ}‡ fdd„| ¡ D ƒ}ˆjdkr||  ˆj	||||¡}nt
ƒ  ˆ¡}ˆjdkr°ˆ| j|< ˆj|j_ˆj|j_|S )	Nc                    s,   t | tjƒr$dˆ jkr ˆ jd S d S t| ƒS )NÚtype)Ú
isinstanceÚfxr   Úmetar    )Úarg)r   r   r   Úget_type.   s    z(NormalizeArgs.run_node.<locals>.get_typec                 S   s   g | ]}t |ƒ‘qS r   )r   )Ú.0Úir   r   r   Ú
<listcomp>5   s     z*NormalizeArgs.run_node.<locals>.<listcomp>c                    s   i | ]\}}|ˆ |ƒ“qS r   r   )r&   ÚkÚv)r%   r   r   Ú
<dictcomp>6   s      z*NormalizeArgs.run_node.<locals>.<dictcomp>Úcall_functionÚoutput)Zfetch_args_kwargs_from_envr   Úargsr!   ÚtupleÚAssertionErrorÚitemsÚopr,   Útargetr   Úrun_noder   r#   Únoder    )r   r   r.   ÚkwargsÚ	arg_typesÚkwarg_typesÚoutr   )r%   r   r   r4   +   s    




zNormalizeArgs.run_nodeN.)r3   r.   r6   r7   r8   c           	         sR   t |ƒst‚t|||||| jƒ}|r>|\}}| j d|||¡S tƒ  |||¡S d S )Nr,   )Úcallabler0   r   r   ZtracerZcreate_proxyr   r,   )	r   r3   r.   r6   r7   r8   Únew_args_and_kwargsÚnew_argsÚ
new_kwargsr   r   r   r,   A   s$    ú   ÿzNormalizeArgs.call_function©r3   r.   r6   c                    sR   t |tƒst‚t| j|||| jƒ}|r>|\}}tƒ  |||¡S tƒ  |||¡S d S r   )r!   Ústrr0   r   r   r   r   Úcall_module)r   r3   r.   r6   r;   r<   r=   r   r   r   r@   Z   s    ûzNormalizeArgs.call_module)T)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Útorchr"   ZGraphModuleÚboolr   r   r   r4   r
   r   r	   r   r?   r   r,   r@   Ú__classcell__r   r   r   r   r      s(    ÿ ÿ  ú

ú 
 
ÿr   c                       sÈ   e Zd ZU dZejejejejejejej	ej
ejejejejejejejejejejejejejejejejiZeeeegef eeegef f ed< eeedf eeef dœ‡ fdd„Z‡  ZS )ÚNormalizeOperatorsaÚ  
    Normalize callsites that are different ways of "spelling" the same
    invocation into a single, canonical call. Currently supports:

    1. Normalize operators (e.g. operator.add) to the `torch` ops they
       ultimately invoke (e.g. torch.add) when it is possible to statically
       reason that

    Example usage:

        m = torchvision.models.resnet18()

        traced = torch.fx.symbolic_trace(m)

        traced = NormalizeOperators(traced).transform()
    Úbinary_magic_method_remap.r>   c                    sf   t |ƒst‚|| jkrVt|ƒdkr2tƒ  |||¡S |\}}tƒ j| j| ||fi d�S tƒ  |||¡S )Né   r>   )r:   r0   rI   Úlenr   r,   )r   r3   r.   r6   ÚlhsÚrhsr   r   r   r,   �   s    
ýz NormalizeOperators.call_function) rA   rB   rC   rD   rE   ÚaddÚoperatorÚmulÚsubÚdivÚtruedivZfloor_divideÚfloordivÚ	remainderÚmodÚeqÚneÚltÚleÚgtÚgerI   r   r   r   Ú__annotations__r
   r   r	   r?   r,   rG   r   r   r   r   rH   l   sB   
            ôþÿ 
 
ÿrH   )rO   Útypingr   r   r   r   r   rE   Ztorch.fxr"   r   r   Ztorch.fx.noder	   r
   r   r   Ztorch.fx.operator_schemasr   r   r   Zschema_type_annotationr   r   rH   r   r   r   r   Ú<module>   s   Z