o
    @a                     @   sL   d Z ddlmZ ddlmZ ddlmZ ddlZdd Z	G dd	 d	eZ
dS )
z0 Computes the Control Flow Graph of a function.     )FunctionAnalysis)isnum)DiGraphNc                 C   sf   t | r	| jr	dS t| tjr| jdkrdS t| tjtjtjfr&| j	r&dS t| tj
r1| jr1dS dS )NTTrueF)r   value
isinstanceastZ	AttributeattrZListZTupleSeteltsZDictkeys)node r   6/usr/lib/python3/dist-packages/pythran/analyses/cfg.pyis_true_predicate
   s   r   c                       s   e Zd ZdZe Z fddZdd Zdd Ze Z	 Z
Ze Z ZZe ZZdd	 Zd
d ZeZdd Zdd Ze ZZdd Zdd Zdd Z  ZS )CFGa  
    Computes the Control Flow Graph of a function.

    The processing of a node yields a pair containing
    * the OUT nodes, to be linked with the IN nodes of the successor
    * the RAISE nodes, nodes that stop the control flow (exception/break/...)
    c                    s   t  | _tt|   d S )N)r   resultsuperr   __init__)self	__class__r   r   r   &   s   zCFG.__init__c                 C   s   | j | |f}|jD ]}| j | |D ]	}| j || q| |\}}q| j tj |D ]
}| j |tj q1|fdfS zOUT = node, RAISES = ()r   )r   add_nodebodyadd_edgevisitr   NIL)r   r   currsncurr_r   r   r   visit_FunctionDef*   s   

zCFG.visit_FunctionDefc                 C   s
   |fdfS r   r   r   r   r   r   r   
visit_Pass;      
zCFG.visit_Passc                 C   s   dS )zOUT = (), RAISES = ())r   r   r   r#   r   r   r   visit_ReturnD   s   zCFG.visit_Returnc           	      C   s0  |f}t  }d}|jD ]?}| j| |D ]	}| j|| q| |\}}|D ]!}t|tjr6||f7 }q(t|tj	rD| j|| q(||f7 }q(q|D ]	}| j|| qM|j
rz|j
D ]}| j| |D ]	}| j|| qg| |\}}q]n|f}t|tjrt|jr||fS || |fS || |fS )zm
        OUT = (node,) + last body statements
        RAISES = body's that are not break or continue
        r   )tupler   r   r   r   r   r   r   ZBreakZContinueorelseZWhiler   test)	r   r   r   Zbreak_currsraisesr   r    nraisesnraiser   r   r   	visit_ForH   s<   


zCFG.visit_Forc           	      C   s   |f}d}|j D ]}| j| |D ]	}| j|| q| |\}}||7 }q|}|}|f}|jD ]}| j| |D ]	}| j|| q<| |\}}|| }q2t|jr[||fS || |fS )z^
        OUT = true branch U false branch
        RAISES = true branch U false branch
        r   )r   r   r   r   r   r(   r   r)   )	r   r   r   r*   r   r    r+   ZtcurrsZtraisesr   r   r   visit_Ifw   s(   




zCFG.visit_Ifc                 C   s
   d|ffS )zOUT = (), RAISES = (node)r   r   r#   r   r   r   visit_Raise   r%   zCFG.visit_Raisec                 C   s   |f|ffS )zOUT = RAISES = (node)r   r#   r   r   r   visit_Assert   s   zCFG.visit_Assertc           
      C   s   |f}d}|j D ]}| j| q|jD ]9}| j| |D ]	}| j|| q| |\}}|D ]}t|tjrG|j D ]	}| j|| q<q1||f7 }q1q|j D ]}| |\}	}||	7 }||7 }qQ||fS )z
        OUT = body's U handler's
        RAISES = handler's
        this equation is not has good has it could be...
        but we need type information to be more accurate
        r   )	handlersr   r   r   r   r   r   r   ZRaise)
r   r   r   r*   Zhandlerr   r    r+   r,   Zncurrsr   r   r   	visit_Try   s*   




zCFG.visit_Tryc                 C   sX   |f}d}|j D ]}| j| |D ]	}| j|| q| |\}}||7 }q||fS )zOUT = body's, RAISES = body'sr   )r   r   r   r   r   )r   r   r   r*   r   r    r+   r   r   r   visit_ExceptHandler   s   

zCFG.visit_ExceptHandler)__name__
__module____qualname____doc__objectr   r   r"   r$   Zvisit_AssignZvisit_AugAssignZvisit_ImportZ
visit_ExprZvisit_PrintZvisit_ImportFromZvisit_YieldZvisit_Deleter&   r-   Zvisit_Whiler.   r/   Zvisit_BreakZvisit_Continuer0   r2   r3   __classcell__r   r   r   r   r      s$    - r   )r7   Zpythran.passmanagerr   Zpythran.utilsr   Zpythran.graphr   Zgastr   r   r   r   r   r   r   <module>   s    