U
    ©Ê¹jO  ã                   @   sÎ   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
mZmZmZ d dlmZ d dlmZ d dlmZ d dlZG dd„ de jƒZG d	d
„ d
eƒZe	ejje
f e	ejje
f dœdd„ZdS )é    N)ÚFunctionType)ÚcastÚUnionÚCallableÚDictÚOptionalÚAny)ÚTracer)ÚGraph)Únormalize_source_linesc                   @   s.   e Zd ZdZedœdd„Zdd„ Zdd„ Zd	S )
ÚAST_Rewriterax  
    Take a FunctionType object representing a `forward` method, then
    perform an AST rewrite to swap out nodes that are not symbolically
    traceable with a callsite to the FX alternative.

    To support swapping out an AST node, define a new `visit` method on
    that node. For more details, see:
    https://docs.python.org/3/library/ast.html#ast.NodeTransformer
    ©Úfnc                 C   s¸   t  |¡\}}t|ƒ}d |¡}t |¡}t |¡}t |  	|¡¡}t
|ddƒ}t |j¡}	t|	 ¡ ƒ}
t||	ƒ tt|	 ¡ ƒ|
 ƒ}t|ƒdks–t‚|	|d  }dd„ }|||jd�S )NÚ Úexecé   r   c                 S   s8   t | j|| j| j| jd�}t || ¡}t | j¡|_|S )z?Based on https://stackoverflow.com/a/13503277/2988730 (@unutbu))ÚnameZargdefsÚclosure)	r   Ú__code__Ú__name__Ú__defaults__Ú__closure__Ú	functoolsÚupdate_wrapperÚcopyÚ__kwdefaults__)ÚfÚglobalsÚg© r   ú]/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/fx/experimental/rewriter.pyÚchange_func_globals.   s    ûz1AST_Rewriter.rewrite.<locals>.change_func_globals)r   )ÚinspectÚgetsourcelinesr   ÚjoinÚtextwrapÚdedentÚastÚparseÚfix_missing_locationsÚvisitÚcompiler   Ú__globals__ÚsetÚkeysr   ÚlistÚlenÚAssertionError)Úselfr   ÚsourcelinesÚ_ÚsourceZnormalized_strZ
source_astZdest_astÚcodeZglobals_dictZkeys_beforeZnew_keysZfn_compiledr!   r   r   r    Úrewrite   s    



zAST_Rewriter.rewritec                 C   sr   t jddd�}t|t jƒst‚|j}t|t jƒs4t‚|jr@|jnt jddd�}|j	|g|_
t j|d�}t  ||¡S )z‹
        Swap out the Assert node (Python's `assert`) with a callsite to the
        symbolically-traceable torch._assert function
        ztorch._assert()Úeval)Úmoder   N)ÚvalueÚkind)r:   )r'   r(   Ú
isinstanceÚ
Expressionr1   ÚbodyÚCallÚmsgÚConstantÚtestÚargsÚExprÚcopy_location)r2   ÚnodeÚnZ	call_noder@   Zexpr_wrapperr   r   r    Úvisit_Assert?   s    zAST_Rewriter.visit_Assertc                 C   s4   t j|jgt jt jdt  ¡ d�|j|jgg d�d�S )a  
        Swap out Python's AnnAssign with an Assign node where the annotation function is called.
        Example:
             Original:
             y: Tensor_Type(1,2,3, Dyn) = f2(x)
            Output:
             y = annotate(f2(x),Tensor_Type((1,2,3,Dyn)))
        Zannotate)ÚidÚctx)ÚfuncrC   Úkeywords)Útargetsr:   )r'   ÚAssignÚtargetr?   ÚNameÚLoadr:   Ú
annotation)r2   rF   r   r   r    Úvisit_AnnAssignS   s
    	
 þzAST_Rewriter.visit_AnnAssignN)r   Ú
__module__Ú__qualname__Ú__doc__r   r7   rH   rS   r   r   r   r    r      s   
'r   c                       s@   e Zd Zdeejjef ee	e
ef  edœ‡ fdd„Z‡  ZS )ÚRewritingTracerN)ÚrootÚconcrete_argsÚreturnc                    s   t ƒ  t|ƒ|¡S ©N)ÚsuperÚtraceÚ_rewrite)r2   rX   rY   ©Ú	__class__r   r    r]   b   s    zRewritingTracer.trace)N)r   rT   rU   r   ÚtorchÚnnÚModuler   r   r   Ústrr   r
   r]   Ú__classcell__r   r   r_   r    rW   a   s   rW   )r   rZ   c                    sB   t | tjjƒr,tjjdœ‡ fdd„‰ ˆ | ƒS tƒ  tt| ƒ¡S d S )N)Úmc                    s6   G ‡ fdd„dt jjƒ}tƒ  tt| jƒ¡|_|| ƒS )Nc                       s   e Zd Z‡ ‡fdd„Z‡  ZS )z9_rewrite.<locals>.rewrite_module.<locals>.RewrittenModulec                    sV   t ƒ  ¡  |j ¡ D ]<\}}t|tjjƒr@t ˆ|ƒ¡| j|< qt |¡| j|< qd S r[   )	r\   Ú__init__Ú__dict__Úitemsr<   ra   rb   rc   r   )r2   ÚorigÚkÚv)r`   Úrewrite_moduler   r    rg   m   s
    
zB_rewrite.<locals>.rewrite_module.<locals>.RewrittenModule.__init__)r   rT   rU   rg   re   r   ©rm   r_   r    ÚRewrittenModulel   s   ro   )ra   rb   rc   r   r7   r   r   Úforward)rf   ro   rn   r   r    rm   k   s    z _rewrite.<locals>.rewrite_module)r<   ra   rb   rc   r   r7   r   r   r   r   rn   r    r^   f   s    r^   )r'   r"   r%   r   r   Útypesr   Útypingr   r   r   r   r   r   Ztorch.fx._symbolic_tracer	   Ztorch.fx.graphr
   Ztorch._sourcesr   ra   ÚNodeTransformerr   rW   rb   rc   r^   r   r   r   r    Ú<module>   s    T