
    9j7                     ,   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 d dlZd dlmZ d dlmZ d dlmZ  G d d	e j&                        Z G d
 de      Zdej,                  j.                  ez  dej,                  j.                  ez  fdZy)    N)Callable)FunctionType)Anycast)normalize_source_lines)Tracer)Graphc                   Z    e Zd ZdZej
                  j                  defd       Zd Z	d Z
y)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                 z   t        j                  |      \  }}t        |      }dj                  |      }t	        j
                  |      }t        j                  |      }t        j                  | j                  |            }t        |dd      }t        j                  |j                        }	t        |	j                               }
t        ||	       t!        t        |	j                               |
z
        }t#        |      dk7  rt%        dt#        |             |	|d      }d } |||j                        S )N exec   zExpected 1 new key, got r   c                     t        | j                  || j                  | j                  | j                        }t        j                  ||       }t        j                  | 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gs      ^/media/conek/DATA/Code/OCR/venv/lib/python3.12/site-packages/torch/fx/experimental/rewriter.pychange_func_globalsz1AST_Rewriter.rewrite.<locals>.change_func_globals8   s]     

ZZA ((A.A#yy)9)9:AH    )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!   s                 r    rewritezAST_Rewriter.rewrite!   s    !//3Q,[9%!0 YY~.
,,TZZ
-CD xV,yy0,++-.T< L--/0;>?x=A #;CM?!KLL"8A;/	  #;GGr"   c                    t        j                  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      }|j                  |g|_        t        j                  |	      }t        j                  ||      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)rC   )r(   r)   
isinstance
Expressionr2   typebodyCallmsgConstanttestargsExprcopy_location)r3   noden	call_noderJ   expr_wrappers         r    visit_AssertzAST_Rewriter.visit_AssertJ   s     II'f5!S^^, #@a	!JKKFF	)SXX. #:4	?:K!LMM((dhh2D(I))S)	 xxi0   t44r"   c           
          t        j                  |j                  gt        j                  t        j                  dt        j
                               |j                  |j                  gg             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)funcrM   keywords)targetsrC   )r(   AssigntargetrI   NameLoadrC   
annotation)r3   rP   s     r    visit_AnnAssignzAST_Rewriter.visit_AnnAssign`   sQ     zz[[M((XX<jj$//2
 	
r"   N)r   
__module____qualname____doc__torch_dynamodisabler   r?   rT   ra    r"   r    r   r      s:     ]]&H, &H &HP5,
r"   r   c                   n     e Zd Z	 ddej                  j
                  ez  deee	f   dz  de
f fdZ xZS )RewritingTracerNrootconcrete_argsreturnc                 6    t         |   t        |      |      S N)supertrace_rewrite)r3   rk   rl   	__class__s      r    rq   zRewritingTracer.tracet   s    
 w}Xd^];;r"   ro   )r   rb   rc   re   nnModuler   dictstrr   r	   rq   __classcell__)rs   s   @r    rj   rj   s   sH     04<hhoo(< CH~,< 
	< <r"   rj   r   rm   c                     t        | t        j                  j                        r(dt        j                  j                  ffd |       S t	               j                  t        t        |             S )Nmc                      G fddt         j                  j                        }t               j	                  t        t        | j                              |_         ||       S )Nc                   "     e Zd Z fdZ xZS )9_rewrite.<locals>.rewrite_module.<locals>.RewrittenModulec                 D   t         |           |j                  j                         D ]t  \  }}t	        |t
        j                  j                        r)t        j                   |            | j                  |<   St        j                  |      | j                  |<   v y ro   )	rp   __init____dict__itemsrE   re   rt   ru   r   )r3   origkvrs   rewrite_modules       r    r   zB_rewrite.<locals>.rewrite_module.<locals>.RewrittenModule.__init__   sr    G$& $ 3 3 5 <1%a9/3yy9J/KDMM!,/3yy|DMM!,	<r"   )r   rb   rc   r   rx   )rs   r   s   @r    RewrittenModuler}      s    < <r"   r   )re   rt   ru   r   r?   r   r   forward)rz   r   r   s     r    r   z _rewrite.<locals>.rewrite_module   sI    <%((// < '3n&<&<\199-'O# #1%%r"   )rE   re   rt   ru   r   r?   r   r   )r   r   s    @r    rr   rr   |   sR    "ehhoo&	&ehhoo 	& b!! ~%%d<&<==r"   )r(   r   r   r#   r&   collections.abcr   typesr   typingr   r   re   torch._sourcesr   torch.fx._symbolic_tracer   torch.fx.graphr	   NodeTransformerr   rj   rt   ru   rr   rh   r"   r    <module>r      sy         $    1 +  ^
3&& ^
B<f <>8+ >(0J >r"   