o
    @au                     @   sj   d Z ddl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dS )
z* DeadCodeElimination remove useless code.     )PureExpressionsDefUseChains	Ancestors)OMPDirective)TransformationNc                   @   s   e Zd Zdd Zdd ZdS )ClumsyOpenMPDependencyHandlerc                 C   s   t  | _d S N)set	blacklistself r   M/usr/lib/python3/dist-packages/pythran/optimizations/dead_code_elimination.py__init__   s   z&ClumsyOpenMPDependencyHandler.__init__c                 C   s*   |j D ]}t|tjr| j|j q|S r   )Zdeps
isinstanceastNamer
   addid)r   nodeZdepr   r   r   visit_OMPDirective   s
   
z0ClumsyOpenMPDependencyHandler.visit_OMPDirectiveN)__name__
__module____qualname__r   r   r   r   r   r   r      s    r   c                       s\   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
 fddZ  ZS )DeadCodeEliminationa  
    Remove useless statement like:
        - assignment to unused variables
        - remove alone pure statement
        - remove empty if

    >>> import gast as ast
    >>> from pythran import passmanager, backend
    >>> pm = passmanager.PassManager("test")
    >>> node = ast.parse("def foo(): a = [2, 3]; return 1")
    >>> _, node = pm.apply(DeadCodeElimination, node)
    >>> print(pm.dump(backend.Python, node))
    def foo():
        pass
        return 1
    >>> node = ast.parse("def foo(): 'a simple string'; return 1")
    >>> _, node = pm.apply(DeadCodeElimination, node)
    >>> print(pm.dump(backend.Python, node))
    def foo():
        pass
        return 1
    >>> node = ast.parse('''
    ... def bar(a):
    ...     return a
    ... def foo(a):
    ...    bar(a)
    ...    return 1''')
    >>> _, node = pm.apply(DeadCodeElimination, node)
    >>> print(pm.dump(backend.Python, node))
    def bar(a):
        return a
    def foo(a):
        pass
        return 1
    c                    s    t t| ttt t | _d S r   )superr   r   r   r   r   r	   r
   r   	__class__r   r   r   ;   s
   zDeadCodeElimination.__init__c                 C   s8   t |tjr|j| jv rdS | jj| }t| S dS NT)	r   r   r   r   r
   Zdef_use_chainsZchainsboolZusers)r   r   chainr   r   r   used_targetA   s   zDeadCodeElimination.used_targetc                 C   s"   t  }|| |j| _| |S r   )r   visitr
   generic_visit)r   r   Zcodhr   r   r   visit_FunctionDefI   s   

z%DeadCodeElimination.visit_FunctionDefc                 C   sN   | j | d }t|dd|gkr|S t|dd|gkr|S t|tr%|S d S )Nbodyr   orelse)Z	ancestorsgetattrmetadatagetr   )r   r   Zancestorr   r   r   
visit_PassO   s   zDeadCodeElimination.visit_Passc                    s`    fdd|j D }t|t|j kr|S ||_ d _|r|S |j jv r)t S tj|jdS )Nc                    s   g | ]	}  |r|qS r   )r!   ).0targetr   r   r   
<listcomp>Z   s    
z4DeadCodeElimination.visit_Assign.<locals>.<listcomp>Tvalue)targetslenupdater0   pure_expressionsr   PassExpr)r   r   r1   r   r   r   visit_AssignY   s   z DeadCodeElimination.visit_Assignc                 C   s4   || j v rt|jtjsd| _t S | | |S r   )r4   r   r0   r   ZYieldr3   r5   r#   )r   r   r   r   r   
visit_Exprg   s   

zDeadCodeElimination.visit_Exprc                 C   s   |  | z#t|jrt|tsd| _|jW S nt|ts'd| _|j	W S W n	 t
y1   Y nw tdd |jD }tdd |j	D }|sa|ratjt |jd}d| _tj||j	t dS |s|d| _|j| jv rpt S tj|jd}|  | |S )NTc                 s       | ]
}t |tj V  qd S r   r   r   r5   r,   xr   r   r   	<genexpr>       z/DeadCodeElimination.visit_If.<locals>.<genexpr>c                 s   r9   r   r:   r;   r   r   r   r=      r>   )opoperand)testr&   r'   r/   )r#   r   Zliteral_evalrA   r)   r*   r   r3   r&   r'   
ValueErroranyZUnaryOpZNotZIflistr4   r5   r6   )r   r   Z	have_bodyZ	have_elserA   r   r   r   visit_Ifo   s6   

zDeadCodeElimination.visit_Ifc                    sB   t |t}tt| |}t |ts|D ]}t || q|S )z4 Add OMPDirective from the old node to the new one. )r)   r*   r   r   r   r"   r   )r   r   Zold_ompZomp_directiver   r   r   r"      s   zDeadCodeElimination.visit)r   r   r   __doc__r   r!   r$   r+   r7   r8   rE   r"   __classcell__r   r   r   r   r      s    #
"r   )rF   Zpythran.analysesr   r   r   Zpythran.openmpr   Zpythran.passmanagerr   Zpythran.metadatar)   Zgastr   ZNodeVisitorr   r   r   r   r   r   <module>   s    