o
    "j?9                     @   s   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	m
Z
mZmZmZmZmZ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mZ g Zd	Zd
ZdZ G dd deZ!G dd dej"Z#dd Z$dd Z%	dddZ&dS )    N)defaultdict)unique_name)FOR_ITER_INDEX_PREFIXFOR_ITER_ITERATOR_PREFIXFOR_ITER_TARGET_PREFIXFOR_ITER_TUPLE_INDEX_PREFIXFOR_ITER_TUPLE_PREFIXFOR_ITER_VAR_LEN_PREFIXFOR_ITER_VAR_NAME_PREFIXFOR_ITER_ZIP_TO_LIST_PREFIXFunctionNameLivenessAnalysisGetterSetterHelperast_to_source_codecreate_funcDef_nodecreate_get_args_nodecreate_name_strcreate_nonlocal_stmt_nodescreate_set_args_node)gast   )BaseTransformer)FALSE_FUNC_PREFIXTRUE_FUNC_PREFIXget_argsset_argsZ__argsc                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )IfElseTransformerzC
    Transform if/else statement of Dygraph into Static Graph.
    c                 C   s   || _ t| j  d S N)rootr   )selfr    r   h/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/jit/dy2static/ifelse_transformer.py__init__;   s   zIfElseTransformer.__init__c                 C   s   |  | j dS )z1
        Main function to transform AST.
        N)visitr   )r   r   r   r    	transformA   s   zIfElseTransformer.transformc           	      C   sJ   |  | t|| j\}}}}}}t|||j||||}||||g|g S r   )generic_visittransform_if_elser   create_convert_ifelse_nodetest)	r   nodetrue_func_nodefalse_func_nodeget_args_nodeset_args_nodereturn_name_idspush_pop_idsnew_noder   r   r    visit_IfG   s2   

zIfElseTransformer.visit_Ifc                 C   s2   t |jtjr|j}|jdkr|j}| | |S )Nnumpy)
isinstancefuncr   	Attributeattrvaluer$   )r   r(   	attributer   r   r    
visit_Callc   s   

zIfElseTransformer.visit_Callc              	   C   s<   |  | tdd|j|j|jddd}t|tjr|j}|S )zQ
        Transformation with `true_fn(x) if Tensor > 0 else false_fn(x)`
        NT)	r$   r&   r'   bodyorelser2   r   Exprr6   )r   r(   r/   r   r   r    visit_IfExpl   s   
zIfElseTransformer.visit_IfExpN)	__name__
__module____qualname____doc__r!   r#   r0   r8   r<   r   r   r   r    r   6   s    	r   c                   @   sf   e 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S )NameVisitorNc                 C   sD   || _ || _tt| _g | _|d u | _tjtj	tj
f| _t | _d S r   )
after_nodeend_noder   listname_idsancestor_nodes	_in_ranger   StoreLoadParam_candidate_ctxsset_def_func_names)r   rB   rC   r   r   r    r!      s   

zNameVisitor.__init__c                 C   sn   | j dur|| j krd| _dS || jkrd| _dS | j| d|jj }t| || j}||}| j	  |S )zVisit a node.NTFvisit_)
rB   rG   rC   rF   append	__class__r=   getattrr$   pop)r   r(   methodvisitorretr   r   r    r"      s   

zNameVisitor.visitc                 C   s   | j r| js| | dS t| j}| |j}| j s#| | dS | |j	}| j s3| | dS | 
||}|D ]}|| t  q;|| _dS )a}  
        For nested `if/else`, the created vars are not always visible for parent node.
        In addition, the vars created in `if.body` are not visible for `if.orelse`.

        Case 1:
            x = 1
            if m > 1:
                res = new_tensor
            res = res + 1   # Error, `res` is not visible here.

        Case 2:
            if x_tensor > 0:
                res = new_tensor
            else:
                res = res + 1   # Error, `res` is not visible here.

        In above two cases, we should consider to manage the scope of vars to parsing
        the arguments and returned vars correctly.
        N)rG   rC   r$   copydeepcopyrE   _visit_childr9   _update_name_idsr:   _find_new_name_idsrO   r   rH   )r   r(   Zbefore_if_name_idsbody_name_idselse_name_idsnew_name_idsZnew_name_idr   r   r    r0      s    

zNameVisitor.visit_Ifc                 C   s"   | j r| |s| | d S d S r   )rG   _is_call_func_name_noder$   r   r(   r   r   r    visit_Attribute   s   zNameVisitor.visit_Attributec                 C   sr   | j s
| | d S h d}|j|v rd S |j| jv rd S | |s5t|j| jr7| j|j 	|j d S d S d S )N>   NoneFalseTrue)
rG   r$   idrM   r^   r2   ctxrK   rE   rO   )r   r(   Z	blacklistr   r   r    
visit_Name   s   


zNameVisitor.visit_Namec                 C   s(   | j s
| | d S d|_| | d S )N)r6   targets)rG   r$   _fieldsr_   r   r   r    visit_Assign   s
   
zNameVisitor.visit_Assignc                 C   s   t |jv s
t|jv rd S | js| | d S | j|j | js'| | d S t	| j
}tt| _
| | | jsA| | d S || _
d S r   )GET_ARGS_FUNC_PREFIXnameSET_ARGS_FUNC_PREFIXrG   r$   rM   addrC   rV   rW   rE   r   rD   rY   )r   r(   Zbefore_name_idsr   r   r    visit_FunctionDef   s   





zNameVisitor.visit_FunctionDefc                 C   sX   t t| _t|tr|D ]}t|tjr| | qnt|tjr&| | t| jS r   )	r   rD   rE   r2   r   ASTr"   rV   rW   )r   r(   itemr   r   r    rX      s   



zNameVisitor._visit_childc                 C   s`   dd }t | t | @ }tj}t  }|D ]}||| |r-||| |r-|| q|S )Nc                 S   s   | D ]
}t ||r dS qdS )NTF)r2   )ctxsZrequired_ctxre   r   r   r    is_required_ctx
  
   
z7NameVisitor._find_new_name_ids.<locals>.is_required_ctx)rL   keysr   rH   rm   )r   r[   r\   rr   Zcandidate_name_idsZ	store_ctxr]   name_idr   r   r    rZ   	  s   
zNameVisitor._find_new_name_idsc                 C   sj   ddh}t | jdkr3| jd |ksJ | jd }t|tjr3|j|kr3t|tjo.|j|v }|s3dS dS )NrO   extendr   TF)lenrF   r2   r   Callr3   r4   r5   )r   r(   Zwhite_func_namesZparent_nodeshould_skipr   r   r    r^     s   
z#NameVisitor._is_call_func_name_nodec                 C   s*   |  D ]\}}|| j|  | j|< qd S r   )itemsrE   )r   r]   ru   rq   r   r   r    rY   ,  s   zNameVisitor._update_name_ids)NN)r=   r>   r?   r!   r"   r0   r`   rf   ri   rn   rX   rZ   r^   rY   r   r   r   r    rA   ~   s    
-rA   c                 C   sB   t | tsJ | D ]}||vrtd| d|| q	| | S )a  
    All var in return_name_ids should be in nonlocal_names.
    Moreover, we will always put return_name_ids in front of nonlocal_names.

    For Example:

        return_name_ids: [x, y]
        nonlocal_names : [a, y, b, x]

    Return:
        nonlocal_names : [x, y, a, b]
    zRequired returned var 'z4' must be in 'nonlocal' statement '', but not found.)r2   rD   
ValueErrorremove)r-   nonlocal_namesrk   r   r   r    _valid_nonlocal_names1  s   
r   c              	      s   t | j }t | j }t|}|  t||}ttt	t
tttttg	  fdd}tt||}|}t|}tjg g dg ddg d}t|| j tt|g d}t|| j tt|g d}	tdd||}
t|
 }t|
 }||	||||fS )zN
    Transform ast.If into control flow statement of Paddle static graph.
    c                    s    D ]
}|  |r dS qdS )NFT)
startswith)xrk   Zfilter_namesr   r    	remove_ifd  rs   z$transform_if_else.<locals>.remove_ifN)argsposonlyargsvararg
kwonlyargskw_defaultskwargdefaults)rk   Z
input_argsr-   )sortedZpd_scopeZmodified_varsZvariadic_length_varsrD   sortr   	ARGS_NAMEr   r   r   r   r   r	   r
   r   filterr   r   	argumentsr   r9   r   generater   r:   r   r   r   unionr   )r(   r   r-   r.   r   r   Znonlocal_stmt_nodeZempty_arg_noder)   r*   helperr+   r,   r   r   r    r%   I  sd   

r%   Fc                 C   sv   |rdt | }dt | }	n|j}|j}	tdjt |||	|s%|jnd|s+|jndt| t|djd }
|
S )z
    Create `paddle.jit.dy2static.convert_ifelse(
            pred, true_fn, false_fn, get_args, set_args, return_name_ids)`
    to replace original `python if/else` statement.
    z	lambda : zt_jst.IfElse({pred}, {true_fn}, {false_fn}, {get_args}, {set_args}, {return_name_ids}, push_pop_names={push_pop_ids})zlambda: Nonezlambda args: None)predZtrue_fnZfalse_fnr   r   r-   r.   r   )r   rk   r   parseformatr   r9   )r-   r.   r   Z	true_funcZ
false_funcZget_args_funcZset_args_funcZ
is_if_exprZtrue_func_sourceZfalse_func_sourceZconvert_ifelse_layerr   r   r    r&     s0   r&   )F)'rV   collectionsr   Zpaddle.baser   Zpaddle.jit.dy2static.utilsr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   Zpaddle.utilsr   Zbase_transformerr   utilsr   r   __all__rj   rl   r   r   NodeVisitorrA   r   r%   r&   r   r   r   r    <module>   s$   HH 4S