o
    ei]                     @   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 d dl	m
Z
mZmZmZ d dlZd dlmZ d dlmZ d dlmZ G dd	 d	e jZG d
d deZdeejjef deejjef fddZdS )    N)Callable)FunctionType)AnycastOptionalUnion)normalize_source_lines)Tracer)Graphc                   @   s6   e Zd ZdZejjdef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rRtdt| |	|d  }dd }|||jdS )	N exec   zExpected 1 new key, got r   c                 S   s8   t | j|| j| j| jd}t|| }t| j|_|S )z?Based on https://stackoverflow.com/a/13503277/2988730 (@unutbu))nameargdefsclosure)	r   __code____name____defaults____closure__	functoolsupdate_wrappercopy__kwdefaults__)fglobalsg r   h/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/torch/fx/experimental/rewriter.pychange_func_globals8   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_sourcenormalized_str
source_astdest_astcodeglobals_dictkeys_beforenew_keysfn_compiledr    r   r   r   rewrite!   s    



zAST_Rewriter.rewritec                 C   s   t jddd}t|t jstdt| |j}t|t js(tdt| |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)modezExpected ast.Expression, got zExpected ast.Call, got r   N)valuekind)r@   )r&   r'   
isinstance
Expressionr0   typebodyCallmsgConstanttestargsExprcopy_location)r1   noden	call_noderG   expr_wrapperr   r   r   visit_AssertJ   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)))
        annotate)idctx)funcrJ   keywords)targetsr@   )r&   AssigntargetrF   NameLoadr@   
annotation)r1   rM   r   r   r   visit_AnnAssign`   s   	
zAST_Rewriter.visit_AnnAssignN)r   
__module____qualname____doc__torch_dynamodisabler   r=   rQ   r]   r   r   r   r   r      s    (r   c                       sF   e Zd Z	ddeejjef dee	e
ef  def fddZ  ZS )RewritingTracerNrootconcrete_argsreturnc                    s   t  t||S N)supertrace_rewrite)r1   re   rf   	__class__r   r   rj   t   s   zRewritingTracer.tracerh   )r   r^   r_   r   ra   nnModuler   r   dictstrr   r
   rj   __classcell__r   r   rl   r   rd   s   s    rd   r   rg   c                    s>   t | tjjrdtjjf fdd  | S t tt| 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 rh   )	ri   __init____dict__itemsrB   ra   rn   ro   r   )r1   origkv)rm   rewrite_moduler   r   rt      s   
zB_rewrite.<locals>.rewrite_module.<locals>.RewrittenModule.__init__)r   r^   r_   rt   rr   r   rz   rl   r   RewrittenModule   s    r|   )ra   rn   ro   r   r=   r   r   forward)rs   r|   r{   r   r   rz      s
   	
z _rewrite.<locals>.rewrite_module)rB   ra   rn   ro   r   r=   r   r   )r   r   r{   r   rk   |   s   rk   )r&   r   r   r!   r$   collections.abcr   typesr   typingr   r   r   r   ra   torch._sourcesr   torch.fx._symbolic_tracer	   torch.fx.graphr
   NodeTransformerr   rd   rn   ro   rk   r   r   r   r   <module>   s   a.	