U
    dC                     @   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__ C/tmp/pip-unpacked-wheel-ua33x9lu/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_|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#   node)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,   @   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@   Y   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   k   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   Y