o
    "j                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZ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Zd dlZd dlZd dlmZmZmZ d dl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"m#Z# d	d
l$m%Z% d	dl&m'Z' d	dl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2 g Z3dZ4dZ5dZ6dZ7dZ8da9dZ:dZ;dZ<dZ=dZ>dZ?dZ@dZAdZBdZCdZDdZEdZFd ZGd!ZHd"ZId#ZJd$ZKd%ZLd&ZMejNjOjPejNjOjQejNjOjRejNjOjSgZTG d'd( d(e#jUZVd)d*d+d,d-d.d/d0ZWdd2d3ZXd4d5 ZYG d6d7 d7ZZG d8d9 d9e[Z\d:d; Z]d<d= Z^d>d? Z_d@dA Z`ddBdCZadDhZbdEdF ZcddGdHZddIdJ ZedKdL ZfdMdN ZgdOdP ZhdQdR ZidSdT Zjd	gdUfdVdWZkdXdY Zle#m dZfd[d\Znd]d^ Zod_d` Zpdadb ZqddcddZrdedf Zsdgdh ZtddidjZudkdl Zvdmdn ZwG dodp dpe#jUZxdqdr Zydsdt Zzdudv Z{dwdx Z|G dydz dzZ}G d{d| d|e#jUZ~d}d~ Zdd Zdd ZG dd dZdd Zdd Zdd Zdd ZdddZe!dd Zdd Ze!dd ZdS )    N)SourceFileLoader)base	get_flags	set_flags)backwardcore	frameworkunique_name)convert_dtype)LayerHelper)signature_safe_contextmanager)gast   )ast_to_source_code)StaticAnalysisVisitor)
DYGRAPH_MODULE_PREFIXDYGRAPH_TO_STATIC_MODULE_PREFIXPADDLE_MODULE_PREFIXNodeVarType_is_api_in_module_helperindex_in_listis_api_in_moduleis_dygraph_apiis_numpy_apiis_paddle_apiget_argsZset_argsZ__already_d2sZ__argsz1Original information of source code for ast node.TZ__for_loop_var_indexZ__for_loop_iter_tupleZ__for_loop_iter_targetZ__for_loop_iter_iteratorZ__for_loop_iter_tuple_indexZ__for_loop_var_lenZ__for_loop_iter_varZ__for_loop_iter_zipz[a-zA-Z0-9_]+z[a-zA-Z0-9_]+\.Z__no_value_return_varg7v-EZtrue_fnZfalse_fnZwhile_conditionZ
while_bodyZfor_loop_conditionZfor_loop_bodyzgrad/z@GRADc                   @   s    e Zd ZdZdd Zdd ZdS )BaseNodeVisitorz
    Implement customized NodeVisitor inherited from gast.NodeVisitor.
    Ancestor nodes are traced to easily support more operations of currently
    visited node.
    c                 C   s
   g | _ d S N)ancestor_nodesself r!   [/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/jit/dy2static/utils.py__init__n      
zBaseNodeVisitor.__init__c                 C   s<   | j | d|jj }t| || j}||}| j   |S )zVisit a node.visit_)r   append	__class____name__getattrgeneric_visitpop)r    nodemethodvisitorretr!   r!   r"   visitq   s   
zBaseNodeVisitor.visitN)r(   
__module____qualname____doc__r#   r0   r!   r!   r!   r"   r   g   s    r   Zcosine_decayZexponential_decayZinverse_time_decayZnatural_exp_decayZ
noam_decayZpiecewise_decayZpolynomial_decay)ZCosineDecayZExponentialDecayZInverseTimeDecayZNaturalExpDecayZ	NoamDecayZPiecewiseDecayZPolynomialDecayfloat32c              
   C   s^   t di t }t|}tt|D ]}|| du rd||< q|j| ||tjjj	d|dddS )a  
    This function creates a Tensor on the global block. The created Tensor
    doesn't check the dtype and the shape of feed data because dygraph input
    data can be various-length. This API is used in translating dygraph into
    static graph.

    Note:
        The default :code:`stop_gradient` attribute of the Tensor created by
        this API is true, which means the gradient won't be passed backward
        through the data Tensor. Set :code:`var.stop_gradient = False` If
        user would like to pass backward gradient.

    Args:
       name (str): The name/alias of the Tensor, see :ref:`api_guide_Name`
           for more details.
       shape (list|tuple): List|Tuple of integers declaring the shape. You can
           set "None" at a dimension to indicate the dimension can be of any
           size. For example, it is useful to set changeable batch size as "None"
       dtype (np.dtype|VarType|str, optional): The type of the data. Supported
           dtype: bool, float16, float32, float64, int8, int16, int32, int64,
           uint8. Default: float32
       lod_level (int, optional): The LoD level of the LoDTensor. Usually users
           don't have to set this value. Default: 0

    Returns:
        Tensor: The global Tensor that gives access to the data.
    dataNTF)nameshapedtypetypestop_gradient	lod_levelZis_dataZneed_check_feed)r5   )
r   localslistrangelenZcreate_global_variabler   VarDescVarTypeZ
LOD_TENSOR)r7   r8   r9   r<   helperir!   r!   r"   data_layer_not_check   s    rE   c                  C   sR   t tddgd} d| _tdi t }|jj}d|j_t	t
|  ||j_| S )NZundefined_varr   Zfloat64Fcreate_undefined_variabler   )rF   )rE   r	   generater;   r   r=   Zmain_programZcurrent_block_idxpaddleZassignRETURN_NO_VALUE_MAGIC_NUM)varrC   Zsaved_block_idsr!   r!   r"   rF      s   rF   c                   @   s   e Zd Zdd Zdd ZdS )UndefinedVarc                 C   
   || _ d S r   r7   r    r7   r!   r!   r"   r#      r$   zUndefinedVar.__init__c                 C   s   t d)Nz6local variable '{}' should be created before using it.)UnboundLocalErrorr   r!   r!   r"   check   s   zUndefinedVar.checkN)r(   r1   r2   r#   rP   r!   r!   r!   r"   rK      s    rK   c                       s   e Zd Z fddZ  ZS )Dygraph2StaticExceptionc                    s   t  | d S r   )superr#   )r    messager'   r!   r"   r#         z Dygraph2StaticException.__init__)r(   r1   r2   r#   __classcell__r!   r!   rT   r"   rQ      s    rQ   c                 C   s   t | tr	|  S | S r   )
isinstancerK   rP   xr!   r!   r"   saw   s   
rZ   c                 C   sx   t | }|j}|rd|d kr|jdd }i }|j}|r8t|t|ks(J |t| d }tt||}||fS )zB
    Returns full argument names as list. e.g ['x', 'y', 'z']
    r    r   r   N)inspectgetfullargspecargsdefaultsr@   dictzip)functionfullargspec	arg_namesZdefault_kwargsdefault_valuesZdefault_kwarg_namesr!   r!   r"   parse_arg_and_kwargs   s   
re   c                 C   s   t | }|j}|S )zU
    Returns varargs name string of function. e.g: 'input' from `foo(x, *input)`
    )r[   r\   varargs)ra   rb   rf   r!   r!   r"   parse_varargs_name   s   
rg   c                 C   s
   t | jS r   )r:   r(   )vr!   r!   r"   	type_name   r$   ri   c                 C   s   t | tttfrttt| S zt|  W | S  tyI   t | tj	r+t| 
  Y S t | tr;ttt|   Y S |p>d}t|dt|   w )z
    Makes input `x` hashable.

    For some unhashable objects, such as `dict/list/set/np.ndarray`,applying hash function by using their values.
    zRequires a hashable object.z But received type: %s)rW   tupler>   setmapmake_hashablehash	TypeErrornpZndarrayZtostringr_   values
ValueErrorri   )rY   	error_msgr!   r!   r"   rm      s   

rm   z$paddle.nn.layer.container.Sequentialc                 C   s   t |  dS )z
    Append API or class as ignored case for is_paddle_func, and they
    will be retured False while calling is_paddle_func(func).
    N)AS_NOT_INNER_FUNC_LISTadd)pathr!   r!   r"   as_not_paddle_func  s   rw   c                 C   s   dd }zBt | tjr| j} t| dd}t| r"| jjj	}| j
} n	t| dr+| jj	}t| }|duo9|j	t}|rD|oC||| }|W S  tyP   Y dS w )z
    Return True if function is defined in Paddle module.
    Skip to check APIs in white list if specifying ignore_white_list as True.
    c                 S   s   |d u rdS | j d | tv S )NF.)r(   rt   )module	func_namer!   r!   r"   in_white_list(  s   z%is_paddle_func.<locals>.in_white_listr(   Nr'   F)rW   	functoolspartialfuncr)   r[   ismethod__self__r'   r(   __func__hasattr	getmodule
startswithr   	Exception)r~   Zignore_white_listr{   rz   mflagr!   r!   r"   is_paddle_func"  s$   



r   c                    sT   t | tjsJ tt| j}td| d}|d   fdd| jD | _d S )Ninspect.getfullargspec()r   c                    s   g | ]	}|j  v r|qS r!   )arg).0kfull_args_namer!   r"   
<listcomp>I      z)_delete_keywords_from.<locals>.<listcomp>)	rW   r   Callastor	to_sourcegast_to_astr~   evalkeywords)r,   Zfunc_src	full_argsr!   r   r"   _delete_keywords_fromB  s
   r   c                 C   s    | t v rt |  S td|  d)NzPaddle dygraph API z0 cannot be converted to static graph at present.)dygraph_class_to_static_apiNotImplementedError)Zdygraph_classr!   r!   r"   to_static_apiL  s
   
r   c                 C   s   t | tjsJ |dkr*| jD ]
}|jdkrd|_q| jtjdtjdd dd |dkr<| jD ]
}|jdkr;d|_q1|d	krN| jD ]}|jd
krMd|_qCd S d S )NZLinearZ
output_dimsizeZnum_flatten_dimsr6   )valuekindr   r   ZBilinearTensorProductZPReluinputrY   )rW   r   r   r   r   r&   keywordConstant)r,   Zdygraph_api_nameZast_keywordr!   r!   r"   _add_keywords_toV  s.   





r   c                 C   s   t | tjsJ t |tjsJ t|jj}tj|t tjdt tjt dd d ddd| _t	| |d | j
|j
 | j|j t| |jj t|  t|  | S )NZlayersr   )ctxid
annotationtype_comment)attrr   r   forward)rW   r   r   r   r~   r   	AttributeLoadNameupdate_args_of_funcr]   extendr   r   r   fix_missing_locations)r,   Z
class_nodeZ
static_apir!   r!   r"   to_static_astn  s*   
r   c           	      C   s   t | tjsJ |dvrtdtt|j}|dks%td| dr:td| d| d}d	d
 |d D }ng }g }t	| j
D ]\}}|tj|| |d qCg | _
|| j | _d S )N)r#   r   zIThe method name of class to update args should be '__init__' or 'forward'r#   zissubclass(z, paddle.nn.Layer)r   rx   r   c                 S   s   g | ]}|d kr|qS r   r!   )r   Zarg_namer!   r!   r"   r     s    z'update_args_of_func.<locals>.<listcomp>r   r   )rW   r   r   rr   r   r   r   r~   r   	enumerater]   r&   r   r   )	r,   Zdygraph_nodemethod_nameZ	class_srcr   r   Zadded_keywordsidxr   r!   r!   r"   r     s&   

r   c                 C   s   t | tjtjtjfsJ t | tjr%tjtdjd j| gg d}|S t | tjr>tjtdjd j| jgg d}|S t | tjrQt	
| }t|j|_|S d S )Nzpaddle.shaper   )r~   r]   r   )rW   r   r   r   	Subscriptr   parsebodyr   copydeepcopycreate_api_shape_node)Ztensor_shape_nodeZapi_shape_nodeZresult_noder!   r!   r"   r     s,   
r   Zint64c              
   C   s*   t |  dt| dt| d| dS )Nz = paddle.full(z, "z", r   )r   r   str)r7   r   r8   r9   r!   r!   r"   get_constant_variable_node  s   "r   c                 C   s(   t | tjs
J dtt|  S )Nz3Input non-Attribute node to get attribute full name)rW   r   r   r   r   r   strip)r,   r!   r!   r"   get_attribute_full_name  s   r   Fc                    s   t | tr| g} t | tttfstdtt|  fdd  fdd| D }t|dkr7|s7|d }|S tj	|d}|S )	am  
    If name_ids is list or tuple or set with multiple strings, this function
    generates gast.Tuple of gast.Name.
    If the name_ids is single string or contains only 1 string, this function
    returns gast.Name if gen_tuple_if_single==False else returns gast.Tuple
    with only one gast.Name

    This function is used at several gast.Return statements.
    z6name_ids must be list or tuple or set, but received %sc                    s,   d| vrt j|  d d dS t | jd jS )Nrx   )r   r   r   r   r   )r   r   r   r   r   rM   r   r!   r"   create_node_for_name  s
   z0generate_name_node.<locals>.create_node_for_namec                    s   g | ]} |qS r!   r!   )r   name_id)r   r!   r"   r     s    z&generate_name_node.<locals>.<listcomp>r   r   )eltsr   )
rW   r   r>   rj   rk   ro   r:   r@   r   Tuple)name_idsr   Zgen_tuple_if_singleZ
gast_names	name_noder!   )r   r   r"   generate_name_node  s   


r   c                 C   sR   t  | } |r| tjt|d n	| tjdd tj||| g ddd}|S )zh
    Wrapper all statements of nodes into one ast.FunctionDef, which can be
    called by ast.Call.
    )r   N)r7   r]   r   decorator_listreturnsr   )r   r&   r   Returnr   FunctionDef)nodesr7   Z
input_argsZreturn_name_idsZfunc_def_noder!   r!   r"   create_funcDef_node  s   
r   c                 C   s(   t | t d}tj|g|d}||fS )zT
    Creates a `gast.Assign` node by given name_id as target and node as value.
    r   )targetsr   )r   r   StoreAssign)r7   r,   r   Zassign_noder!   r!   r"   create_assign_node  s   r   c                  C   sZ   dt   } t jt jd| }tjd}|r t j|}t j	|s+t 
| |S )z+
    Return @to_static temp directory.
    zpaddle/to_static_tmp/z~/.cachewin)osgetpidrv   join
expandusersysplatformr   normpathexistsmakedirs)dir_nametemp_dirZ
is_windowsr!   r!   r"   get_temp_dir  s   
r   c                 C   s&  dd }dd }t | }t | }t }tjd||dd|dd	}| tj|jd
d }|	| W d
   n1 s>w   Y  |rPt
rPtj||d da
|j}	t||j}
tj|
j|
}tj|}|
| t|drx|j}|	|_nt||	rt||	}ntd|	 t|| ||jfS )z
    Transform modified AST of decorated function into python callable object.
    TODO: If only decorate one of inner function instead of decorating the main
    function, the other inner functions are invisible for the decorated function.
    c                 S   s   t j| rt|  d S d S r   )r   rv   r   shutilrmtreeZdir_pathr!   r!   r"   remove_if_exit$  s   z#ast_to_func.<locals>.remove_if_exitc                 S   s<   | j }t| drz| jjj d | j  }W |S    Y |S |S )Nr   _)r(   r   r   r'   )r~   Zpre_fixr!   r!   r"   func_prefix(  s   
z ast_to_func.<locals>.func_prefixwz.pyFzutf-8)modeprefixsuffixdeletedirencodingNr   __i_m_p_l__z>Function: %s doesn't exist in the Module transformed from AST.)r   _inject_import_statementsr   tempfileNamedTemporaryFiler   rv   basenamer7   writeDEL_TEMP_DIRatexitregisterr(   r   	importlibutilspec_from_loadermodule_from_specexec_moduler   r   r)   rr   recover_globals_attribute)ast_rootZdyfuncZdelete_on_exitr   r   sourcer   fmodule_namerz   loaderspecry   Zcallable_funcr!   r!   r"   ast_to_func  sJ   	





r  c                  C   s   g d} d | d S )N)zimport paddlezfrom paddle import Tensorzimport paddle.base as basez#import paddle.jit.dy2static as _jstzfrom typing import *zimport numpy as npzimport warningsz>warnings.filterwarnings('ignore', category=DeprecationWarning)
r   )Zimport_statementsr!   r!   r"   r   _  s   
r   c                 C   sN   d}t | |i }t ||i }| D ]\}}|dr |ds$|||< qd S )N__globals____)r)   itemsr   endswith)Zsrc_objZdst_obj	attr_nameZsrc_globalsZdst_globalsr   rh   r!   r!   r"   r   m  s   r   c                 C   sr   t | tjr	| j} t| st| stdt	| j
t| \}}dd |D }d|}|r7t|}|S )z=
    Transforms function into raw string of source code.
    zGThe type of 'function' should be a function or method, but received {}.c                 S   s"   g | ]}|  d s|ndqS )#r  )lstripr   )r   liner!   r!   r"   r     s    z'func_to_source_code.<locals>.<listcomp> )rW   r|   r}   r~   r[   
isfunctionr   ro   formatr:   r(   getsourcelinesr   textwrapdedent)ra   r  Zsource_code_listr   Zsource_coder!   r!   r"   func_to_source_codey  s    

r  c                 C   s6   t | tjtjtjtjtjtjf}dt| v }|p|S )z@
    Nodes with specified type will be dependent on tensor.
    z.numpy())	rW   r   CompareBoolOpUnaryOpForIfWhiler   )r,   Zis_compare_nodeZhas_numpy_attrr!   r!   r"   is_candidate_node  s   r  c                 C   sf   t | tjr1| j| jfD ]$}t |tr|d }t |tjr"|jdu s-t |tjr0|j	dkr0 dS qdS )zB
    Whether the comparator of `gast.Compare` node is `None`.
    r   NNoneTF)
rW   r   r  leftcomparatorsr>   r   r   r   r   )r,   childr!   r!   r"   compare_with_none  s   


r  c                   @   s   e Zd ZdZ	d!ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  ZdS )"IsControlFlowVisitora#  
    Judge whether the ast_node of control flow from Dygraph code dependent on paddle Tensor.
    `ast_node` can be gast.If, gast.For, gast.While, gast.If.test(gast.Compare, gast.BoolOp, gast.UnaryOp).

    If returns True,
    gast.If.test must meet at least one of the following requirements:
        1. involves at least one var whose type is Tensor.
        2. the Tensor var calls `.numpy()[]` interface or Tensor.shape is [1].
        3. involves Tensor.shape[i] and the shape[i] is unknown in compile time.
    gast.While must meet at least one of the requirements 1 to 5:
        4. has `break` statement.
        5. has `continue` statement.
    gast.For must meet at least one of the requirements 4 to 8:
        6. calls `range` function in `for` statement and the argument of range is Tensor.
        7. calls `enumerate` function in `for` statement and the argument of enumerate is Tensor.
        8. the iterable varaible in `for` statement is Tensor.
        TODO: Support non-range case

    The following examples should not be considered as control_flow_if:
        1. `if Tensor_var` or `if Tensor_var is None`
        2. if Tensor.shape[i] is determined with fixed value (not -1 or None)

    Note: pred in ConditionalBlock require variable, which means all vars should be Tensor
          or transformed into Tensor, like fill_constant(shape=[1], dtype='int32', value=Tensor.shape[i]).

    TODO: 1. need to deal with `tensor.shape[i]` which need to eval the data of shape[i],
             because reshape_op may be called before this statement.
    Nc                 C   s\   t |tjsJ dt| || _|d u rt|}|| _| j | _|| _	d| _
t | _d S )Nz7Type of input node should be gast.AST, but received %s.r   )rW   r   ASTr:   r   r   static_analysis_visitorZget_node_to_wrapper_mapnode_to_wrapper_mapnode_var_type_mapis_control_flow_numrk   _compare_node_tenor_set)r    Zast_noder!  r#  r!   r!   r"   r#     s    zIsControlFlowVisitor.__init__c                 C   sb   | j }t|tjr| | nt|tjr| | nt|tjr'| | n| 	| | j
dkS )Nr   )r   rW   r   r  	_visit_Ifr  
_visit_Forr  _visit_Whiler0   r$  r    r,   r!   r!   r"   	transform  s   

zIsControlFlowVisitor.transformc                 C   s    t |tjsJ | |j d S r   )rW   r   r  r0   testr)  r!   r!   r"   r&    s   zIsControlFlowVisitor._visit_Ifc                 C   s   t |tjsJ t |jtjrNt |jjtjr4|jjjdks%|jjjdkr2|jjD ]}| 	| q)n,d S t |jjtj
rL|jjjdkrJ| |j nd S d S t |jtjr\| 	|j nd S t|D ]}t |tjtjfrs| | qcd S )Nr?   r   numpy)rW   r   r  iterr   r~   r   r   r]   r0   r   r   _visit_CallwalkContinueBreak_visit_break_continue)r    r,   r   
child_noder!   r!   r"   r'    s,   
zIsControlFlowVisitor._visit_Forc                 C   sP   t |tjsJ |j}| | t|D ]}t |tjtjfr%| | qd S r   )	rW   r   r  r+  r*   r/  r0  r1  r2  )r    r,   r+  r3  r!   r!   r"   r(    s   

z!IsControlFlowVisitor._visit_Whilec                 C   sz   t |tjtjfsJ | j|}|sd S |jr;|jj}t |tjtj	fr5|| j
u r3|  jd7  _d S d S |j}|jsd S Nr   )rW   r   r1  r0  r"  getparentr,   r  r  r   r$  )r    r,   wrapper_nodeZparent_noder!   r!   r"   r2  #  s   
z*IsControlFlowVisitor._visit_break_continuec                 C   s"   t |jD ]	\}}| | q|S r   )r   rq   r0   )r    r,   rD   r  r!   r!   r"   visit_BoolOp7  s   z!IsControlFlowVisitor.visit_BoolOpc                 C   sX   | j }t|s| | t|D ]}t|tjr| | q| j |kr*| j	| |S r   )
r$  r  r*   r   r/  rW   r   _visit_Subscriptr%  ru   )r    r,   Zpre_control_flow_numr  r!   r!   r"   visit_Compare<  s   


z"IsControlFlowVisitor.visit_Comparec                 C   s2   |  | t|drt|jtjr| |j |S )Nr   )r*   r   rW   r   r   r   r.  r)  r!   r!   r"   r9  G  s   
z%IsControlFlowVisitor._visit_Subscriptc                 C   sH   t |tjsJ t |jtjr |j}|jdkr"|  jd7  _d S d S d S )Nr,  r   )rW   r   r   r~   r   r   r$  )r    r,   Z	attr_noder!   r!   r"   r.  M  s   
z IsControlFlowVisitor._visit_Callc                 C   s$   |  | t|r|  jd7  _|S r4  )r.  r   r$  r)  r!   r!   r"   
visit_CallT  s   
zIsControlFlowVisitor.visit_Callc                 C       |  ||jr|  jd7  _|S r4  )_is_node_with_tensorr   r$  r)  r!   r!   r"   
visit_NameZ     zIsControlFlowVisitor.visit_Namec                 C   r<  r4  )r=  r   r$  r)  r!   r!   r"   visit_Constant_  r?  z#IsControlFlowVisitor.visit_Constantc                 C   s^   | j r|rt|tr| j |d }|r|tj@ rdS | j|d }|d ur-|jtj@ r-dS dS NTF)r#  rW   r   r5  r   ZTENSOR_TYPESr"  Znode_var_type)r    r,   r   Zvar_typer7  r!   r!   r"   r=  d  s   z)IsControlFlowVisitor._is_node_with_tensorc                 C      | j S r   )r%  r   r!   r!   r"   get_compare_nodes_with_tensors     z2IsControlFlowVisitor.get_compare_nodes_with_tensor)NN)r(   r1   r2   r3   r#   r*  r&  r'  r(  r2  r8  r:  r9  r.  r;  r>  r@  r=  rC  r!   r!   r!   r"   r    s$    
 r  c                 C   s&   dd }| }||r|j }||s
|S )z3
    Returns the object wrapped by decorators.
    c                 S   s
   t | dS )N__wrapped__)r   )r   r!   r!   r"   _is_wrapped}  r$   zunwrap.<locals>._is_wrapped)rE  )r~   rF  Zunwrapped_fr!   r!   r"   unwrapx  s   rG  c                 C   s   t | }|t |kr| D ]	}||vr dS qdS t| |D ]#\}}t|tjjs/t|tjjr8t||s7 dS qt||s@ dS qdS )aV  
    Returns True if the two input specs are compatible, otherwise False.

    args:
        src_input_spec (list or tuple[InputSpec et.al]): list/tuple of
            paddle.static.InputSpec or int/str et.al
        desired_input_specs (list or tuple[InputSpec et.al]): list/tuple of
            paddle.static.InputSpec or int/str et.al
    FT)r@   r`   rW   rH   static	InputSpec_compatible_tensor_spec_compatible_non_tensor_spec)Zsrc_input_specsZdesired_input_specsZ	len_specsr   src_specdesired_specr!   r!   r"   input_specs_compatible  s$   


rN  c           	      C   s   | |fD ]}t |tjjs dS q| j}|j}t|}|t|kr#dS t|D ]'}|| du s5|| dk r6q'|| du sB|| dk rCq'|| || krN dS q't| j}t|j}||kr_dS dS )z;
    Check whether two tensor type spec is compatible.
    FNr   T)	rW   rH   rH  rI  r8   r@   r?   r
   r9   )	rL  rM  r   Z	src_shapeZother_shapeZ	len_shapejZ	src_dtypeZother_dtyper!   r!   r"   rJ    s,   

rJ  c                 C   s(   dd }|| }||}||krdS dS )z?
    Check whether two non-tensor type spec is compatible.
    c                 S   s    zt | }W |S    d }Y |S r   )rm   )r   hash_valr!   r!   r"   
hash_value  s   
z/_compatible_non_tensor_spec.<locals>.hash_valueFTr!   )rL  rM  rQ  Zsrc_hash_valZdesired_hash_valr!   r!   r"   rK    s   rK  c                   @   sd   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )	NameScopec                 C   s:   t  | _t  | _t  | _d| _t  | _t  | _t  | _dS )a(  
        A NameScope is a object which manager all the variable names.
        only FunctionDef and Controlflow node will have a namescope property.

        type can be "function" and "controlflow"

        we don't analyze the read only variable because they don't affect the analysis.
        N)rk   globals	nonlocalsr]   fatherw_varscreatedpush_pop_varsr   r!   r!   r"   r#     s   	zNameScope.__init__c                 C   rL   r   )rU  )r    rU  r!   r!   r"   
set_father  r$   zNameScope.set_fatherc                 C   s*   | j | j | j | j }ttdd |S )zWvars existing in current scope.
        they must not contain qualified names.
        c                 S      d| vS Nrx   r!   rX   r!   r!   r"   <lambda>      z(NameScope.existed_vars.<locals>.<lambda>)rV  rS  rT  r]   rk   filter)r    
local_varsr!   r!   r"   existed_vars  s   zNameScope.existed_varsc                 C   rB  r   )rW  r   r!   r!   r"   created_vars  rD  zNameScope.created_varsc                 C   rB  r   )rV  r   r!   r!   r"   modified_vars  s   zNameScope.modified_varsc              
   C   sV   g }| j D ]!}| |r!| |r!td| d| d| d q|| qt|S )a  
        At present, we do not support global append, such as

        import numpy as np
        a = []
        def func():
            a.append() # global names `a`, we will raise a warning.
            p.append(a, 1) # global names `np`, we will raise a warning.
        zFind variable `z$` defined in global scope and call `z.append() or zI.pop()`, which will be ignored and never be transfered into tensor array.)rX  _is_simple_nameis_global_varwarningswarnr&   rk   )r    Znon_global_push_pop_namesrJ   r!   r!   r"   variadic_length_vars  s   

zNameScope.variadic_length_varsc                 C   s$   | j }| jj|@ f}|| j | dS )N)globalnonlocal)rV  rU  global_vars)r    Zvalid_namestmpr!   r!   r"   control_flow_vars  s   zNameScope.control_flow_varsc                 C   s   d|v sd|v r
dS dS )Nrx   [FTr!   rN   r!   r!   r"   rc    s   zNameScope._is_simple_namec                 C   sR   |  |s	J d| }|dur'||jv rdS ||j|jB v r dS |j}|dusdS )a  
        Return whether the name is a var created in global scope.
        Search from bottom to top. If it is not created or modified,
        it means global vars; otherwise, it means local vars.
        Only valid after FunctionNameLivenessAnalysis visitor.
        z5is_global_var accept a simple name, but get `{name}`.NTF)rc  rS  rT  rV  rU  )r    r7   Zancestorr!   r!   r"   rd    s   
zNameScope.is_global_varc                 C   s   |  | S r   )rd  rN   r!   r!   r"   is_local_var0  s   zNameScope.is_local_varc                 C   sT   |  j |j O  _ |  j|jO  _|  j|jO  _|  j|jO  _|  j|jO  _d S r   )rS  rT  r]   rV  rX  )r    Z
name_scoper!   r!   r"   
merge_from3  s
   zNameScope.merge_fromN)r(   r1   r2   r#   rY  r`  ra  rb  rg  rl  rc  rd  rn  ro  r!   r!   r!   r"   rR    s    rR  c                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,S )-FunctionNameLivenessAnalysisa  analyze the liveness of a function.

    every variables stored in this scope will be collected,
    in addition with global/nonlocal information and
    push_pop information.

    1. global variable is stored in node.var_globals.
    2. nonlocal variable is stored in node.var_nonlocals.
    3. arguments is stored in node.var_args.
    4. if a variable's push and pop attribute is called,
       it will be collected in push_pop_vars. They are
       used for transformation to tensor_array.
       NOTE: push_pop_vars **may not** in w_vars.
       a.push(0) don't modify the variable a, but the content
       of a.

    For example:

    def func(*args, **kargs):
        a = 12
        global i,j
        nonlocal x,y
        print(a)
        i = k
        b = []
        c = [1,2,3]
        for m in range(10):
            q = 12
            b.push(1)
            c.pop()

    After this visitor we have:
    # node is the FunctionDef node with name: "func"
    node.pd_scope = NameScope(
        globals = ['i', 'j'],
        nonlocals = ['x', 'y'],
        args = ['args', 'kargs'],
        wr_vars = ['a', 'i', 'q', 'm', 'c', 'b']
        push_pop_vars = ['b', 'c']
    )
    c                 C   s   g | _ | | d S r   )scope_node_stackr0   )r    Z	root_noder!   r!   r"   r#   f  s   z%FunctionNameLivenessAnalysis.__init__c                 C   s   t  |_d S r   )rR  pd_scoper)  r!   r!   r"   _reset_name_scopej  s   z.FunctionNameLivenessAnalysis._reset_name_scopec                 C   s   t |ds	t |_|jS )Nrr  )r   rR  rr  r)  r!   r!   r"   _get_name_scopen  s   
z,FunctionNameLivenessAnalysis._get_name_scopec                 C   s   |  | jd S )Nr6   )rt  rq  r   r!   r!   r"   _current_name_scopes  rU   z0FunctionNameLivenessAnalysis._current_name_scopec                 C   s"   t | jdkr	d S | | jd S )Nr   )r@   rq  rt  r   r!   r!   r"   _father_name_scopev  s   z/FunctionNameLivenessAnalysis._father_name_scopec                 C   sF   t | jdkr	d S | jdd d D ]}t|tjr | |  S qd S )Nr   rv  r6   )r@   rq  rW   r   r   rt  r)  r!   r!   r"   _nearest_function_scope{  s   z4FunctionNameLivenessAnalysis._nearest_function_scopec                 C      dS )z[ i for i in range(10) ]
        In this case, `i` will not created in FunctionScope.
        We don't collect `i` by not calling generic_visit.
        Nr!   r)  r!   r!   r"   visit_ListComp  s   z+FunctionNameLivenessAnalysis.visit_ListCompc                 C   ry  )zthe same as ListComp.Nr!   r)  r!   r!   r"   visit_DictComp  s   z+FunctionNameLivenessAnalysis.visit_DictCompc                 C   s@   |  | tjtjtjf}t|j|r|  j	|j
 d S d S r   )r*   r   r   AugStoreDelrW   r   ru  rV  ru   r   r    r,   write_contextr!   r!   r"   r>    s
   
z'FunctionNameLivenessAnalysis.visit_Namec                    s.    fdd} fdd}  || d S )Nc                      s       jt O  _d S r   )ru  r]   rk   _get_argument_namesr!   r,   r    r!   r"   pre_func  s   z@FunctionNameLivenessAnalysis.visit_FunctionDef.<locals>.pre_funcc                     sh   t t ttttg  fdd}  r0|  r2  j jO  _  j jO  _dS dS dS )a  NOTE: why we need merge w_vars and push_pop_vars here ?
            because we do ifelse_transformer after loop_transformer. Loops will changed into functioons. but we know this function will be called in if. so we add w_vars to father function scope.
            c                     s     D ]} j | r dS qdS rA  )r7   r   )r   )control_flow_function_defr,   r!   r"   is_control_flow_def_node  s
   zcFunctionNameLivenessAnalysis.visit_FunctionDef.<locals>.post_func.<locals>.is_control_flow_def_nodeN)	WHILE_BODY_PREFIXFOR_CONDITION_PREFIXFOR_BODY_PREFIXTRUE_FUNC_PREFIXFALSE_FUNC_PREFIXrw  rV  ru  rX  )r  r  )r  r"   	post_func  s    	


zAFunctionNameLivenessAnalysis.visit_FunctionDef.<locals>.post_func_visit_scope_noder    r,   r  r  r!   r  r"   visit_FunctionDef  s   z.FunctionNameLivenessAnalysis.visit_FunctionDefc                 C   sT   |  | | j| |  |   |r|  | | |r#|  | j  dS )zQscope node main visit logic.
        pre_func and post_func is callbacks
        N)rs  rq  r&   ru  rY  rx  r*   r+   r  r!   r!   r"   r    s   

z.FunctionNameLivenessAnalysis._visit_scope_nodec                    s.    fdd} fdd}  || d S )Nc                      sX             j  _  j jO  _d S r   )rw  ro  ru  rx  r`  before_createdrW  r!   r  r!   r"   r    s   


zGFunctionNameLivenessAnalysis._visit_controlflow_node.<locals>.post_funcc                      s       _d S r   )rx  r`  r  r!   r  r!   r"   r       zFFunctionNameLivenessAnalysis._visit_controlflow_node.<locals>.pre_funcr  )r    r,   r  r  r!   r  r"   _visit_controlflow_node  s   z4FunctionNameLivenessAnalysis._visit_controlflow_nodec                 C      |  | d S r   r  r)  r!   r!   r"   	visit_For     z&FunctionNameLivenessAnalysis.visit_Forc                 C   r  r   r  r)  r!   r!   r"   visit_While  r  z(FunctionNameLivenessAnalysis.visit_Whilec                 C   r  r   r  r)  r!   r!   r"   visit_If  r  z%FunctionNameLivenessAnalysis.visit_Ifc                 C      |    jt|jO  _d S r   )ru  rS  rk   namesr)  r!   r!   r"   visit_Global     z)FunctionNameLivenessAnalysis.visit_Globalc                 C   r  r   )ru  rT  rk   r  r)  r!   r!   r"   visit_Nonlocal  r  z+FunctionNameLivenessAnalysis.visit_Nonlocalc                 C   sJ   |  | tjtjtjf}t|j|r#t| }| 	 j
| d S d S r   )r*   r   r   r|  r}  rW   r   r   r   ru  rV  ru   )r    r,   r  r7   r!   r!   r"   visit_Attribute  s   
z,FunctionNameLivenessAnalysis.visit_Attributec                 C   sv   |  | tjtjtjf}t|j|r7t|jtjr$|j}t|jtjst|jtj	r9| 
 j|jj d S d S d S r   )r*   r   r   r|  r}  rW   r   r   r   r   ru  rV  ru   r   r~  r!   r!   r"   visit_Subscript  s   
z,FunctionNameLivenessAnalysis.visit_Subscriptc                 C   sX   |  | t|jtjsd S ddg}|jj|vrd S t|jj }| 	 j
| d S )Nr&   r+   )r*   rW   r~   r   r   r   r   r   r   ru  rX  ru   )r    r,   Zvariadic_length_methodr7   r!   r!   r"   r;    s   
z'FunctionNameLivenessAnalysis.visit_Callc                 C   sN   t |tjs
J dt|jj}||jj ||jj dd |D }|S )zget all arguments name in the functiondef node.
        this node is local to the function and shouldn't
        be created.
        z&Input node is not function define nodec                 S   s   g | ]	}|d ur|j qS r   )r   )r   rD   r!   r!   r"   r     r   zDFunctionNameLivenessAnalysis._get_argument_names.<locals>.<listcomp>)rW   r   r   r>   r]   r&   varargkwarg)r    r,   r  r!   r!   r"   r    s   z0FunctionNameLivenessAnalysis._get_argument_namesN)r(   r1   r2   r3   r#   rs  rt  ru  rw  rx  rz  r{  r>  r  r  r  r  r  r  r  r  r  r  r;  r  r!   r!   r!   r"   rp  ;  s.    *#	rp  c                 C   s|   dd }t | ttfsJ t| }| s| S |g krd}nt|d }d}|jtt|d	| d}t
t|jd S )z{
    Create get_args function as follows:

        def get_args_0():
            nonlocal x, y
            return x, y
    c                  S   s(   dt t d} tt| jd S )N
        def z():
            return
        r   )r	   rG   GET_ARGS_FUNC_PREFIXr   r   r  r  r   func_defr!   r!   r"   
empty_node  s   z(create_get_args_node.<locals>.empty_noder  r   zK
    def {func_name}():
        {nonlocal_vars}
        return {vars},
    ,)rz   nonlocal_varsvars)rW   r>   rj   create_nonlocal_stmt_nodesr   r  r	   rG   r  r   r   r   r  r  r   r  r  r,   r  templater  r!   r!   r"   create_get_args_node  s   	r  c                 C   s~   dd }t | ttfsJ t| }| s| S |g krd}nt|d }d}|jttt	|d
| d}tt|jd S )z
    Create set_args function as follows:

        def set_args_0(__args):
            nonlocal x, y
            x, y = __args
    c                  S   s.   dt t dt d} tt| jd S )Nr  (z):
            pass
        r   )	r	   rG   SET_ARGS_FUNC_PREFIX	ARGS_NAMEr   r   r  r  r   r  r!   r!   r"   r  ?  s   z(create_set_args_node.<locals>.empty_noder  r   zS
    def {func_name}({args}):
        {nonlocal_vars}
        {vars}, = {args}
    r  )rz   r]   r  r  )rW   r>   rj   r  r   r  r	   rG   r  r  r   r   r   r  r  r   r  r!   r!   r"   create_set_args_node6  s    	r  c                 C   sn   t | ttfs	J ttdd | }ttdd |}t||jd} | s&g S dd| }t	|j
d gS )Nc                 S   rZ  r[  r!   nr!   r!   r"   r\  _  r]  z,create_nonlocal_stmt_nodes.<locals>.<lambda>c                 S   rZ  )Nrm  r!   r  r!   r!   r"   r\  `  r]  )keyznonlocal {}r  r   )rW   r>   rj   r^  sortedindexr  r   r   r   r   )r  Zmapped	func_coder!   r!   r"   r  \  s   r  c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )GetterSetterHelperzwe have two classes of names in setter and getter function:
    w_vars(loop_vars) + push_pop_vars
    To simplify the setter logic in convert_while and convert_cond,
    we extract the helper class here.
    c                 G   sf   dd |D }dd |D }t tdd |t | _| j  || _|| _dd t| jD | _	d S )Nc                 s   s     | ]}|d u r
g n|V  qd S r   r!   r   rY   r!   r!   r"   	<genexpr>r  s    z.GetterSetterHelper.__init__.<locals>.<genexpr>c                 s   s    | ]}t |V  qd S r   )rk   r  r!   r!   r"   r  s  s    c                 S   s   | |B S r   r!   )rY   yr!   r!   r"   r\  u  r]  z-GetterSetterHelper.__init__.<locals>.<lambda>c                 S   s   i | ]\}}||qS r!   r!   )r   r   r7   r!   r!   r"   
<dictcomp>z      z/GetterSetterHelper.__init__.<locals>.<dictcomp>)
r>   r|   reducerk   _unionsortgettersetterr   name2id)r    Zgetter_funcZsetter_funcZ
name_listsZ	name_setsr!   r!   r"   r#   q  s   
zGetterSetterHelper.__init__c                 C   rB  r   )r  r   r!   r!   r"   union|  rD  zGetterSetterHelper.unionc                    sh   |d u rg }   d u rdS |D ]}| jv s'J d| d j  dqt fdd|D S )Nr!   
the name `` not in name union set``.c                 3   s    | ]
} j |  V  qd S r   r  r   r  r    r  r!   r"   r    s    z)GetterSetterHelper.get.<locals>.<genexpr>)r  r  keysrj   )r    r  r  r!   r  r"   r5    s   zGetterSetterHelper.getc                    s   |d u rg }|d u rg }   }|d u rd S |D ]}| jv s-J d| d j  dqt|} fdd|D }t||D ]\}}|||< q@ | d S )Nr  r  r  c                    s   g | ]} j | qS r!   r  r  r   r!   r"   r     r  z*GetterSetterHelper.set.<locals>.<listcomp>)r  r  r  r>   r`   r  )r    r  rq   r  r  indicesrD   rh   r!   r   r"   rk     s    
zGetterSetterHelper.setN)r(   r1   r2   r3   r#   r  r5  rk   r!   r!   r!   r"   r  j  s    r  c                 C   s$   | sdS dd | D }dd | S )z(
    Return "('x', 'y')" for [x, y]
    r  c                 S   s   g | ]
}d | dd qS )z'%s''z\')replace)r   r7   r!   r!   r"   r     s    z#create_name_str.<locals>.<listcomp>z(%s, )r  r  )r   Z	names_strr!   r!   r"   create_name_str  s   r  c                 C   s   t | |pt S r   )cinn_is_enabledprim_is_enabled)build_strategybackendr!   r!   r"   prim_or_cinn_is_enabled  rU   r  c                 C   sD   |dkrdS | d ur| j rdS td}|d ur | dv r dS dS )NCINNTZFLAGS_use_cinn)true1F)Zbuild_cinn_passr   getenvlower)r  r  r   r!   r!   r"   r    s   
r  c                   C   s   t   t  pt  S r   )r   check_and_set_prim_all_enabled_is_bwd_prim_enabled_is_fwd_prim_enabledr!   r!   r!   r"   r    s   r  c                    s@    fdd}t  tjr| rdS  tj v r| rdS dS )zpredict whether a function is a builtin function with name={name}.
    if name == None, then any builtin function will return True
    c                      s   d u p j kS r   )r(   r!   r~   r7   r!   r"   
name_judge  r  zis_builtin.<locals>.name_judgeTF)rW   typesBuiltinFunctionTypebuiltins__dict__rq   )r~   r7   r  r!   r  r"   
is_builtin  s   r  c              	   c   sd    t   t  }t  }| dkrt d zd V  W t | t | d S t | t | w )Nr  T)r   r  r  r  Z_set_prim_all_enabledZ_set_prim_forward_enabledZ_set_prim_backward_enabled)r  Z	orign_fwdZ	orign_bwdr!   r!   r"   backend_guard  s   


r  c           	      C   sj   i }dd }t | |}tt|||d< t | |}tt|||d< t | |}tt|||d< |S )Nc                 S   s   t | tjr	| jS tjS r   )rW   r   Variabler7   ZEMPTY_VAR_NAME)Zgrad_varr!   r!   r"   r\    s   
z&construct_grad_names.<locals>.<lambda>rY   paramout)r   Z_get_grad_varsr>   rl   )	Zgrad_info_mapZx_varsZ
param_varsZout_varsZgrad_var_namesfnZx_grad_varsZparam_grad_varsZout_grad_varsr!   r!   r"   construct_grad_names  s   r  c              	   c   s    z1t | t |ksJ dd | D }t| |D ]\}}||_qd V  W t| |D ]\}}||_q)d S t| |D ]\}}||_q8w )Nc                 S   s   g | ]}|j qS r!   rM   )r   tr!   r!   r"   r     s    z%tensor_name_guard.<locals>.<listcomp>)r@   r`   r7   )Ztensorsr  Zorigin_namesr  r7   r!   r!   r"   tensor_name_guard  s   r  )r4   r   r   )T)r   r  r   r|   importlib.utilr   r[   r   r   r   r   r  r  re  importlib.machineryr   r   r,  rp   rH   r   r   r   Zpaddle.baser   r   r   r	   Zpaddle.base.data_feederr
   Zpaddle.base.layer_helperr   Zpaddle.base.wrapped_decoratorr   Zpaddle.utilsr   Z	ast_utilsr   Zstatic_analysisr   Zutils_helperr   r   r   r   r   r   r   r   r   r   __all__r  r  ZALREADY_D2Sr  Z
ORIGI_INFOr   ZFOR_ITER_INDEX_PREFIXZFOR_ITER_TUPLE_PREFIXZFOR_ITER_TARGET_PREFIXZFOR_ITER_ITERATOR_PREFIXZFOR_ITER_TUPLE_INDEX_PREFIXZFOR_ITER_VAR_LEN_PREFIXZFOR_ITER_VAR_NAME_PREFIXZFOR_ITER_ZIP_TO_LIST_PREFIXZ	RE_PYNAMEZRE_PYMODULEZRETURN_NO_VALUE_VAR_NAMErI   r  r  ZWHILE_CONDITION_PREFIXr  r  r  ZGRAD_PREFIXZGRAD_SUFFIXrA   rB   ZREADERZSTEP_SCOPESZFEED_MINIBATCHZ
FETCH_LISTZNO_SHAPE_VAR_TYPENodeVisitorr   r   rE   rF   rK   r   rQ   rZ   re   rg   ri   rm   rt   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r  r  r  r  rG  rN  rJ  rK  rR  rp  r  r  r  r  r  r  r  r  r  r  r  r  r!   r!   r!   r"   <module>   s   0
.
	

	 

!	
B
 @d W%&4

