U
    ö¾|e�x  ã                   @   sž   d dl Z d dlZd dlZd dlmZ d dlmZ eddddgƒZG dd	„ d	e	ƒZ
G d
d„ de  dd¡ƒZG dd„ de jƒZG dd„ de	ƒZG dd„ de	ƒZdS )é    N)ÚLoc)ÚUnsupportedErrorZ
SETUP_LOOPÚFOR_ITERÚ
SETUP_WITHZBEFORE_WITHc                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚCFBlockc                 C   s"   || _ g | _i | _i | _d| _d S )NF)ÚoffsetÚbodyÚoutgoing_jumpsÚincoming_jumpsÚterminating)Úselfr   © r   úS/var/www/website-v5/atlas_env/lib/python3.8/site-packages/numba/core/controlflow.pyÚ__init__   s
    zCFBlock.__init__c                 C   s    | j t| jƒt| jƒf}d| S )Nz,block(offset:%d, outgoing: %s, incoming: %s))r   Úsortedr	   r
   )r   Úargsr   r   r   Ú__repr__   s
    þzCFBlock.__repr__c                 C   s
   t | jƒS ©N)Úiterr   ©r   r   r   r   Ú__iter__"   s    zCFBlock.__iter__N)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r   r   r      s   r   c                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )ÚLoopz?
    A control flow loop, as detected by a CFGraph object.
    r   c                 C   s   t |tƒo|j| jkS r   )Ú
isinstancer   Úheader©r   Úotherr   r   r   Ú__eq__3   s    zLoop.__eq__c                 C   s
   t | jƒS r   )Úhashr   r   r   r   r   Ú__hash__6   s    zLoop.__hash__N)r   r   r   Ú__doc__Ú	__slots__r   r!   r   r   r   r   r   &   s   r   )ÚentriesÚexitsr   r   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú_DictOfContainerszŒA defaultdict with customized equality checks that ignore empty values.

    Non-empty value is checked by: `bool(value_item) == True`.
    c                 C   s&   t |tƒr"|  ¡ }| ¡ }||kS tS r   )r   r&   Ú_non_empty_itemsÚNotImplemented)r   r   ZmineZtheirsr   r   r   r   @   s
    
z_DictOfContainers.__eq__c                 C   s    |   |¡}|tkr|S | S d S r   )r   r(   )r   r   Úretr   r   r   Ú__ne__H   s    
z_DictOfContainers.__ne__c                 C   s   dd„ t |  ¡ ƒD ƒS )Nc                 S   s   g | ]\}}|r||f‘qS r   r   )Ú.0ÚkÚvsr   r   r   Ú
<listcomp>P   s      z6_DictOfContainers._non_empty_items.<locals>.<listcomp>)r   Úitemsr   r   r   r   r'   O   s    z"_DictOfContainers._non_empty_itemsN)r   r   r   r"   r   r*   r'   r   r   r   r   r&   :   s   r&   c                   @   s  e Zd ZdZdd„ Zdd„ Zdsd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ejdd„ ƒZejdd„ ƒZejdd „ ƒZejd!d"„ ƒZejd#d$„ ƒZejd%d&„ ƒZejd'd(„ ƒZejd)d*„ ƒZejd+d,„ ƒZejd-d.„ ƒZejd/d0„ ƒZd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Z d9d:„ Z!d;d<„ Z"d=d>„ Z#d?d@„ Z$dAdB„ Z%dtdDdE„Z&dudFdG„Z'dvdIdJ„Z(dwdKdL„Z)dMdN„ Z*dxdOdP„Z+dQdR„ Z,dSdT„ Z-dUdV„ Z.dWdX„ Z/dYdZ„ Z0d[d\„ Z1dyd]d^„Z2d_d`„ Z3dadb„ Z4dzdcdd„Z5dedf„ Z6dgdh„ Z7didj„ Z8dkdl„ Z9dmdn„ Z:dodp„ Z;dqdr„ Z<dS ){ÚCFGraphzB
    Generic (almost) implementation of a Control Flow Graph.
    c                 C   s,   t ƒ | _tt ƒ| _tt ƒ| _i | _d | _d S r   )ÚsetÚ_nodesr&   Ú_predsÚ_succsÚ
_edge_dataÚ_entry_pointr   r   r   r   r   X   s
    

zCFGraph.__init__c                 C   s   | j  |¡ dS )z“
        Add *node* to the graph.  This is necessary before adding any
        edges from/to the node.  *node* can be any hashable object.
        N)r2   Úadd©r   Únoder   r   r   Úadd_node_   s    zCFGraph.add_nodeNc                 C   sJ   || j krtd|| j f ƒ‚|| j kr8td|| j f ƒ‚|  |||¡ dS )zÇ
        Add an edge from node *src* to node *dest*, with optional
        per-edge *data*.
        If such an edge already exists, it is replaced (duplicate edges
        are not possible).
        z.Cannot add edge as src node %s not in nodes %sz/Cannot add edge as dest node %s not in nodes %sN)r2   Ú
ValueErrorÚ	_add_edge)r   ÚsrcÚdestÚdatar   r   r   Úadd_edgef   s    
ÿ
ÿzCFGraph.add_edgec                 c   s(   | j | D ]}|| j||f fV  q
dS )z¡
        Yield (node, data) pairs representing the successors of node *src*.
        (*data* will be None if no data was specified when adding the edge)
        N)r4   r5   )r   r=   r>   r   r   r   Ú
successorsu   s    zCFGraph.successorsc                 c   s(   | j | D ]}|| j||f fV  q
dS )z¤
        Yield (node, data) pairs representing the predecessors of node *dest*.
        (*data* will be None if no data was specified when adding the edge)
        N)r3   r5   )r   r>   r=   r   r   r   Úpredecessors}   s    zCFGraph.predecessorsc                 C   s   || j kst‚|| _dS )z=
        Set the entry point of the graph to *node*.
        N)r2   ÚAssertionErrorr6   r8   r   r   r   Úset_entry_point…   s    zCFGraph.set_entry_pointc                 C   s   | j dkrtdƒ‚|  ¡  dS )zÒ
        Compute essential properties of the control flow graph.  The graph
        must have been fully populated, and its entry point specified. Other
        graph properties are computed on-demand.
        Nzno entry point defined!)r6   ÚRuntimeErrorÚ_eliminate_dead_blocksr   r   r   r   ÚprocessŒ   s    
zCFGraph.processc                 C   s   | j S )zÅ
        Return a dictionary of {node -> set(nodes)} mapping each node to
        the nodes dominating it.

        A node D dominates a node N when any path leading to N must go through D
        )Ú_domsr   r   r   r   Ú
dominators–   s    zCFGraph.dominatorsc                 C   s   | j S )zÛ
        Return a dictionary of {node -> set(nodes)} mapping each node to
        the nodes post-dominating it.

        A node P post-dominates a node N when any path starting from N must go
        through P.
        )Ú
_post_domsr   r   r   r   Úpost_dominatorsŸ   s    zCFGraph.post_dominatorsc                 C   s   | j S )z®
        Return a dictionary of {node -> node} mapping each node to its
        immediate dominator (idom).

        The idom(B) is the closest strict dominator of V
        )Ú_idomr   r   r   r   Úimmediate_dominators©   s    zCFGraph.immediate_dominatorsc                 C   s   | j S )a.  
        Return a dictionary of {node -> set(nodes)} mapping each node to
        the nodes in its dominance frontier.

        The dominance frontier _df(N) is the set of all nodes that are
        immediate successors to blocks dominated by N but which aren't
        strictly dominated by N
        )Ú_dfr   r   r   r   Údominance_frontier²   s    	zCFGraph.dominance_frontierc                 C   s   | j S )zÐ
        return a dictionary of {node -> set(nodes)} mapping each node to
        the set of nodes it immediately dominates

        The domtree(B) is the closest strict set of nodes that B dominates
        )Ú_domtreer   r   r   r   Údominator_tree½   s    zCFGraph.dominator_treec                 C   s   |   ¡ S r   )Ú_find_exit_pointsr   r   r   r   Ú_exit_pointsÆ   s    zCFGraph._exit_pointsc                 C   s   |   ¡ S r   )Ú_find_dominatorsr   r   r   r   rH   Ê   s    zCFGraph._domsc                 C   s   |   ¡ S r   )Ú_find_back_edgesr   r   r   r   Ú_back_edgesÎ   s    zCFGraph._back_edgesc                 C   s   |   ¡ S r   )Ú_find_topo_orderr   r   r   r   Ú_topo_orderÒ   s    zCFGraph._topo_orderc                 C   s   |   ¡ S r   )Ú_find_descendentsr   r   r   r   Ú_descsÖ   s    zCFGraph._descsc                 C   s   |   ¡ S r   )Ú_find_loopsr   r   r   r   Ú_loopsÚ   s    zCFGraph._loopsc                 C   s   |   ¡ S r   )Ú_find_in_loopsr   r   r   r   Ú	_in_loopsÞ   s    zCFGraph._in_loopsc                 C   s   |   ¡ S r   )Ú_find_post_dominatorsr   r   r   r   rJ   â   s    zCFGraph._post_domsc                 C   s   |   ¡ S r   )Ú_find_immediate_dominatorsr   r   r   r   rL   æ   s    zCFGraph._idomc                 C   s   |   ¡ S r   )Ú_find_dominance_frontierr   r   r   r   rN   ê   s    zCFGraph._dfc                 C   s   |   ¡ S r   )Ú_find_dominator_treer   r   r   r   rP   î   s    zCFGraph._domtreec                 C   s
   | j | S )zx
        Return the set of descendents of the given *node*, in topological
        order (ignoring back edges).
        )rZ   r8   r   r   r   Údescendentsò   s    zCFGraph.descendentsc                 C   s   | j dk	st‚| j S )z.
        Return the entry point node.
        N)r6   rC   r   r   r   r   Úentry_pointù   s    zCFGraph.entry_pointc                 C   s   | j S )zG
        Return the computed set of exit nodes (may be empty).
        )rS   r   r   r   r   Úexit_points   s    zCFGraph.exit_pointsc                 C   s   | j | j S )zÿ
        Return the set of nodes constituting the graph's backbone.
        (i.e. the nodes that every path starting from the entry point
         must go through).  By construction, it is non-empty: it contains
         at least the entry point.
        )rJ   r6   r   r   r   r   Úbackbone  s    zCFGraph.backbonec                 C   s   | j S )zˆ
        Return a dictionary of {node -> loop} mapping each loop header
        to the loop (a Loop instance) starting with it.
        ©r\   r   r   r   r   Úloops  s    zCFGraph.loopsc                    s   ‡ fdd„ˆ j  |d¡D ƒS )zm
        Return the list of Loop objects the *node* belongs to,
        from innermost to outermost.
        c                    s   g | ]}ˆ j | ‘qS r   rg   )r+   Úxr   r   r   r.     s     z$CFGraph.in_loops.<locals>.<listcomp>r   )r^   Úgetr8   r   r   r   Úin_loops  s    zCFGraph.in_loopsc                 C   s   | j S )zK
        Return the set of dead nodes (eliminated from the graph).
        )Ú_dead_nodesr   r   r   r   Ú
dead_nodes  s    zCFGraph.dead_nodesc                 C   s   | j S )z/
        Return the set of live nodes.
        )r2   r   r   r   r   Únodes#  s    zCFGraph.nodesc                 C   s   | j S )zb
        Return the sequence of nodes in topological order (ignoring back
        edges).
        )rX   r   r   r   r   Ú
topo_order)  s    zCFGraph.topo_orderFc                 c   s6   t |ƒ}| j}|rt|ƒ}|D ]}||kr|V  qdS )z†
        Iterate over the *nodes* in topological order (ignoring back edges).
        The sort isn't guaranteed to be stable.
        N)r1   rX   Úreversed)r   rn   ÚreverseÚitÚnr   r   r   Ú	topo_sort0  s    zCFGraph.topo_sortc                 C   sÎ   ddl }|ptj}td|d� |  |¡ td|d� |j | j|d� td|d� |j | j|d� tdt| jƒ|d� td	|d� |j | j	|d� td
|d� |j | j
|d� td|d� |j |  ¡ |d� dS )z3
        Dump extensive debug information.
        r   NzCFG adjacency lists:©ÚfilezCFG dominators:©ÚstreamzCFG post-dominators:zCFG back edges:z
CFG loops:zCFG node-to-loops:zCFG backbone:)ÚpprintÚsysÚstdoutÚprintÚ_dump_adj_listsrH   rJ   r   rV   r\   r^   rf   )r   rv   ry   r   r   r   Údump=  s    

zCFGraph.dumpúnumba_cfg.dotc                 C   s„   zddl }W n tk
r(   tdƒ‚Y nX |j|d�}| jD ]}| t|ƒ¡ q<| jD ](}| j| D ]}| t|ƒt|ƒ¡ qdqV|S )zïRender the controlflow graph with GraphViz DOT via the
        ``graphviz`` python binding.

        Returns
        -------
        g : graphviz.Digraph
            Use `g.view()` to open the graph in the default PDF application.
        r   NzcThe feature requires `graphviz` but it is not available. Please install with `pip install graphviz`)Úfilename)ÚgraphvizÚImportErrorÚDigraphr2   r9   Ústrr4   Úedge)r   r€   ÚgvÚgrs   r…   r   r   r   Ú
render_dotR  s    
ÿ


zCFGraph.render_dotc                 C   s2   | j |  |¡ | j|  |¡ || j||f< d S r   )r3   r7   r4   r5   )r   Úfrom_Útor?   r   r   r   r<   o  s    zCFGraph._add_edgec                 C   sd   | j  |d¡D ] }| j|  |¡ | j||f= q| j |d¡D ] }| j |  |¡ | j||f= q>d S )Nr   )r4   Úpopr3   Úremover5   )r   r9   ÚsuccÚpredr   r   r   Ú_remove_node_edgesv  s    zCFGraph._remove_node_edgesc                 c   sb   |d kr| j f}tƒ }t|ƒ}|r^| ¡ }||kr|V  | |¡ | j| D ]}| |¡ qLqd S r   )r6   r1   Úlistr‹   r7   r4   Úappend)r   r$   ÚseenÚstackr9   r�   r   r   r   Ú_dfs~  s    
zCFGraph._dfsc                 C   sJ   t ƒ }|  ¡ D ]}| |¡ q| j| | _|| _| jD ]}|  |¡ q6dS )zx
        Eliminate all blocks not reachable from the entry point, and
        stash them into self._dead_nodes.
        N)r1   r”   r7   r2   rl   r�   )r   Zliver9   Údeadr   r   r   rF   ‹  s    
zCFGraph._eliminate_dead_blocksc                 C   s,   t ƒ }| jD ]}| j |¡s| |¡ q|S )z2
        Compute the graph's exit points.
        )r1   r2   r4   rj   r7   )r   re   rs   r   r   r   rR   ™  s
    
zCFGraph._find_exit_pointsc                    sZ   | j ‰| j‰ g ‰tƒ ‰g ‰‡ ‡‡‡‡‡fdd„‰ˆ| jfg‰ˆrVˆ ¡ \}}||ƒ q<ˆS )Nc                    sN   | ˆkrJˆ  | ¡ ˆ ˆj| f¡ ˆ|  D ]}| |fˆ kr*ˆ ˆ|f¡ q*d S r   ©r7   r‘   ©r9   r>   ©Ú
back_edgesÚdfs_recÚ
post_orderr’   r“   Úsuccsr   r   rš   ¬  s    
z(CFGraph._find_postorder.<locals>.dfs_rec)r4   rV   r1   r6   r‹   )r   Úcbr?   r   r˜   r   Ú_find_postorder£  s    
zCFGraph._find_postorderc                    s¦   ‡ ‡fdd„}| j }| j}|  ¡ }dd„ t|ƒD ƒ‰||i‰ | ¡  | ¡  d}|r¢d}|D ]B}t |‡ fdd„|| D ƒ¡}|ˆ ks’ˆ | |kr\|ˆ |< d}q\qPˆ S )	Nc                    sB   | |kr>ˆ|  ˆ| k r"ˆ |  } qˆ|  ˆ| kr ˆ | }q"q | S r   r   )ÚuÚv©ÚidomÚidxr   r   Ú	intersectÅ  s    
z5CFGraph._find_immediate_dominators.<locals>.intersectc                 S   s   i | ]\}}||“qS r   r   )r+   ÚiÚer   r   r   Ú
<dictcomp>Ñ  s      z6CFGraph._find_immediate_dominators.<locals>.<dictcomp>TFc                 3   s   | ]}|ˆ kr|V  qd S r   r   )r+   r    )r¢   r   r   Ú	<genexpr>Û  s    ÿz5CFGraph._find_immediate_dominators.<locals>.<genexpr>)r6   r3   rž   Ú	enumerater‹   rq   Ú	functoolsÚreduce)r   r¤   ÚentryÚpreds_tableÚorderÚchangedrŸ   Znew_idomr   r¡   r   r`   »  s&    
ÿz"CFGraph._find_immediate_dominatorsc                 C   sL   | j }ttƒ}| ¡ D ]0\}}||kr0tƒ ||< ||kr||  |¡ q|S r   )rL   r&   r1   r/   r7   )r   r¢   ZdomtreerŸ   r    r   r   r   rb   ã  s    
zCFGraph._find_dominator_treec                 C   sl   | j }| j}dd„ |D ƒ}|D ]H}t|| ƒdk r4q|| D ](}||| kr<||  |¡ || }q@q<q|S )Nc                 S   s   i | ]}|t ƒ “qS r   )r1   )r+   rŸ   r   r   r   r§   ó  s      z4CFGraph._find_dominance_frontier.<locals>.<dictcomp>é   )rL   r3   Úlenr7   )r   r¢   r­   ÚdfrŸ   r    r   r   r   ra   ð  s    z CFGraph._find_dominance_frontierc           
         s  |rt | jƒ}| j}| j}nt | jgƒ}| j}| j}|s@tdƒ‚i ‰ |D ]}t |gƒˆ |< qHg }| jD ]$}||krft | jƒˆ |< | |¡ qf|�r| ¡ }||kr¤qŒt |gƒ}|| }	|	rÚ|t	 
t j‡ fdd„|	D ƒ¡O }|ˆ | krŒt|ƒtˆ | ƒk �s t‚|ˆ |< | || ¡ qŒˆ S )Nz5no entry points: dominator algorithm cannot be seededc                    s   g | ]}ˆ | ‘qS r   r   )r+   Úp©Údomsr   r   r.   #  s     z5CFGraph._find_dominators_internal.<locals>.<listcomp>)r1   rS   r4   r3   r6   rE   r2   r‘   r‹   rª   r«   Úintersectionr±   rC   Úextend)
r   Úpostr$   r­   Zsuccs_tabler¦   Útodors   Znew_domsÚpredsr   r´   r   Ú_find_dominators_internalÿ  s@    



ÿz!CFGraph._find_dominators_internalc                 C   s   | j dd�S )NF©r¸   )r»   r   r   r   r   rT   *  s    zCFGraph._find_dominatorsc                 C   s„   t ƒ }| j |¡ | j ¡ D ]"}|js|jD ]}|  ||¡ q,q| jdd�}||= | ¡ D ]}| 	|¡ qZ|  
|¡ | j |¡ |S )NTr¼   )ÚobjectrS   r7   r\   Úvaluesr%   r   r<   r»   Údiscardr�   rŒ   )r   Z
dummy_exitÚloopÚbZpdomsrµ   r   r   r   r_   -  s    

zCFGraph._find_post_dominatorsc           
         sê   |dk	r0t |tƒs$tdt|ƒ› �ƒ‚| dd¡ tƒ }g ‰i ‰ˆ  ¡ }tƒ }‡ ‡‡fdd„}||ƒ d}ˆrÎ|d7 }ˆd }ˆ| }|rº| ¡ }	|	ˆkr¨| ||	f¡ qÌ|	|krÌ||	ƒ qhˆ ¡  | |¡ qh|dk	ræ|d  |7  < |S )	zu
        Find back edges.  An edge (src, dest) is a back edge if and
        only if *dest* dominates *src*.
        Nz*stats* must be a dict; got Ziteration_countr   c                    s&   ˆ  | ¡ dd„ ˆ j|  D ƒˆ| < d S )Nc                 S   s   g | ]}|‘qS r   r   )r+   r>   r   r   r   r.   [  s     z@CFGraph._find_back_edges.<locals>.push_state.<locals>.<listcomp>)r‘   r4   )r9   ©r   r“   Zsuccs_stater   r   Ú
push_stateY  s    
z,CFGraph._find_back_edges.<locals>.push_stateé   éÿÿÿÿ)	r   ÚdictÚ	TypeErrorÚtypeÚ
setdefaultr1   rd   r‹   r7   )
r   Ústatsr™   rd   ÚcheckedrÃ   Ziter_ctZtosZ	tos_succsZcur_noder   rÂ   r   rU   B  s6    

zCFGraph._find_back_edgesc                    s@   | j ‰| j‰g ‰tƒ ‰‡ ‡‡‡‡fdd„‰ ˆ | jƒ ˆ ¡  ˆS )Nc                    sB   | ˆkr>ˆ  | ¡ ˆ|  D ]}| |fˆkrˆ |ƒ qˆ | ¡ d S r   r–   r—   ©Ú_dfs_recr™   r›   r’   rœ   r   r   rÍ     s    

z*CFGraph._find_topo_order.<locals>._dfs_rec)r4   rV   r1   r6   rq   r   r   rÌ   r   rW   y  s    
zCFGraph._find_topo_orderc                 C   s\   i }t | jƒD ]H}tƒ  ||< }| j| D ]*}||f| jkr*| |¡ | || ¡ q*q|S r   )rp   rX   r1   r4   rV   r7   Úupdate)r   Zdescsr9   Z
node_descsr�   r   r   r   rY   ‹  s    
zCFGraph._find_descendentsc                 C   sè   i }| j D ]l\}}|}t|gƒ}|g}|rV| ¡ }||kr&| |¡ | | j| ¡ q&||krn||  |¡ q
|||< q
i }| ¡ D ]^\}}tƒ }	tƒ }
|D ],}|	 | j| | ¡ |
 | j| | ¡ qœt	|||	|
d�}|||< q„|S )zC
        Find the loops defined by the graph's back edges.
        )r   r   r$   r%   )
rV   r1   r‹   r7   r·   r3   rÎ   r/   r4   r   )r   Zbodiesr=   r>   r   r   Úqueuers   rh   r$   r%   rÀ   r   r   r   r[   •  s.    



zCFGraph._find_loopsc                 C   sT   | j }tdd„ | jD ƒƒ}t| ¡ dd„ d�D ] }|jD ]}||  |j¡ q8q.|S )Nc                 s   s   | ]}|g fV  qd S r   r   )r+   rs   r   r   r   r¨   ¼  s     z)CFGraph._find_in_loops.<locals>.<genexpr>c                 S   s
   t | jƒS r   )r±   r   )rÀ   r   r   r   Ú<lambda>¿  ó    z(CFGraph._find_in_loops.<locals>.<lambda>)Úkey)r\   rÆ   r2   r   r¾   r   r‘   r   )r   rh   rk   rÀ   rs   r   r   r   r]   ¹  s    
zCFGraph._find_in_loopsc                 C   s2   t dd„ | j ¡ D ƒƒ}dd l}|j||d� d S )Nc                 s   s"   | ]\}}|t t|ƒƒfV  qd S r   )r   r�   )r+   r=   Zdestsr   r   r   r¨   Å  s   ÿz*CFGraph._dump_adj_lists.<locals>.<genexpr>r   rw   )rÆ   r4   r/   ry   )r   rv   Z	adj_listsry   r   r   r   r}   Ä  s
    ÿzCFGraph._dump_adj_listsc                 C   sB   t |tƒst‚dD ]*}t| |d ƒ}t||d ƒ}||kr dS qdS )N)r2   r5   r6   r3   r4   FT)r   r0   ÚNotImplementedErrorÚgetattr)r   r   ri   ÚthisÚthatr   r   r   r   Ê  s    
zCFGraph.__eq__c                 C   s   |   |¡ S r   )r   r   r   r   r   r*   Õ  s    zCFGraph.__ne__)N)F)N)r   )N)N)F)N)=r   r   r   r"   r   r:   r@   rA   rB   rD   rG   rI   rK   rM   rO   rQ   rª   Úcached_propertyrS   rH   rV   rX   rZ   r\   r^   rJ   rL   rN   rP   rc   rd   re   rf   rh   rk   rm   rn   ro   rt   r~   rˆ   r<   r�   r”   rF   rR   rž   r`   rb   ra   r»   rT   r_   rU   rW   rY   r[   r]   r}   r   r*   r   r   r   r   r0   S   s†   

	
		










	





(
+
7
$r0   c                   @   sð   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd0dd„Zdd„ Z	d1d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eZeZeZeZeZeZeZeZd$d%„ ZeZeZd&d'„ Zd(d)„ Z e Z!d*d+„ Z"d,d-„ Z#d.d/„ Z$d
S )2ÚControlFlowAnalysiszæ
    Attributes
    ----------
    - bytecode

    - blocks

    - blockseq

    - doms: dict of set
        Dominators

    - backbone: set of block offsets
        The set of block that is common to all possible code path.

    c                 C   sF   || _ i | _i | _g | _d | _d | _d| _d | _g | _g | _	g | _
d S ©NT)ÚbytecodeÚblocksÚ
liveblocksÚblockseqrµ   rf   Ú_force_new_blockÚ	_curblockÚ_blockstackr\   Ú_withs)r   rÚ   r   r   r   r   ê  s    zControlFlowAnalysis.__init__c                 c   s   | j D ]}| j| V  qdS )z=
        Return all blocks in sequence of occurrence
        N)rÝ   rÛ   ©r   r¥   r   r   r   Ú
iterblocksø  s    
zControlFlowAnalysis.iterblocksc                 c   s&   | j D ]}|| jkr| j| V  qdS )zB
        Return all live blocks in sequence of occurrence
        N)rÝ   rÜ   rÛ   râ   r   r   r   Úiterliveblocksÿ  s    

z"ControlFlowAnalysis.iterliveblocksc                 c   s2   |j  ¡ D ]"\}}|| jkr
| j| |fV  q
dS )zQ
        Yield (incoming block, number of stack pops) pairs for *block*.
        N)r
   r/   rÜ   rÛ   )r   Úblockr¥   Úpopsr   r   r   Úincoming_blocks  s    
z#ControlFlowAnalysis.incoming_blocksNc                 C   s   | j jd d� d S )Nru   )Úgraphr~   )r   rv   r   r   r   r~     s    zControlFlowAnalysis.dumpc                    sð  ˆ   ¡ D ]l}d|j }tˆ |d ƒ}|d k	r4||ƒ q|jrtˆ jjj|jƒ}|jdkr\d}n
d|j }t	||d�‚qqt
ˆ jˆ jdd … ƒD ](\}}ˆ j| }|jsŒ|jsŒd|j|< qŒtƒ }	ˆ jD ]}
|	 |
¡ qÂˆ j ¡ D ](}
|
j ¡ D ]\}}|	 |
j||¡ qêqÜ|	 tˆ jƒ¡ |	 ¡  |	ˆ _ˆ j ¡ D ].}
|
j ¡ D ]\}}|ˆ j| j|
j< �q<�q.t‡ fdd	„ˆ j ¡ D ƒƒˆ _tˆ jƒD ]}|ˆ jk�r† �q¨�q†td
ƒ‚ˆ j ¡ }t ƒ }ˆ j !¡ D ]}
ˆ j "|
¡�rÂ| #|
¡ �qÂ|| ˆ _d S )Nzop_%s>   ÚSETUP_FINALLYz2'try' block not supported until python3.7 or laterz$Use of unsupported opcode (%s) found)ÚlocrÄ   r   c                 3   s   | ]}|ˆ j | fV  qd S r   )rÛ   )r+   r¥   r   r   r   r¨   :  s   ÿz*ControlFlowAnalysis.run.<locals>.<genexpr>zNo live block that exits!?)$Ú
_iter_instÚopnamerÔ   Zis_jumpr   rÚ   Úfunc_idr€   Úlinenor   ÚziprÝ   rÛ   r	   r   r0   r:   r¾   r/   r@   r   rD   ÚminrG   rè   r
   rÆ   rn   rÜ   rp   rC   rf   r1   Úkeysrk   r7   )r   ÚinstÚfnameÚfnÚlÚmsgÚcurZnxtÚblkrè   rÁ   Úoutræ   Zlastblkrf   Zinloopblocksr   r   r   Úrun  sR    





ÿ


zControlFlowAnalysis.runr   c                 C   s   || j j|< dS )z–
        Register a jump (conditional or not) to *target* offset.
        *pops* is the number of stack pops implied by the jump (default 0).
        N)rß   r	   )r   Útargetræ   r   r   r   ÚjumpP  s    zControlFlowAnalysis.jumpc                 c   sD   | j D ]8}|  |¡r(|  |¡ |  |¡ | jj |j¡ |V  qd S r   )rÚ   Ú_use_new_blockÚ_guard_with_asÚ_start_new_blockrß   r   r‘   r   ©r   rò   r   r   r   rë   W  s    



zControlFlowAnalysis._iter_instc                 C   s4   |j | jjkrd}n|jtkr$d}n| j}d| _|S )NTF)r   rÚ   Úlabelsrì   ÚNEW_BLOCKERSrÞ   )r   rò   Úresr   r   r   rý   _  s    
z"ControlFlowAnalysis._use_new_blockc                 C   s,   t |jƒ| _| j| j|j< | j |j¡ d S r   )r   r   rß   rÛ   rÝ   r‘   r   r   r   r   rÿ   j  s    z$ControlFlowAnalysis._start_new_blockc                 C   s0   |j dkr,| j|j j }|dkr,d}t|ƒ‚dS )zÞChecks if the next instruction after a SETUP_WITH is something other
        than a POP_TOP, if it is something else it'll be some sort of store
        which is not supported (this corresponds to `with CTXMGR as VAR(S)`).r   ÚPOP_TOPzGThe 'with (context manager) as (variable):' construct is not supported.N)rì   rÚ   Únextr   )r   Zcurrent_instZnext_oprö   r   r   r   rþ   o  s
    
z"ControlFlowAnalysis._guard_with_asc                 C   s<   |  ¡ }| j |¡ | j |j|f¡ |  |j¡ d| _d S rÙ   )Úget_jump_targetrà   r‘   r\   r   rü   r  rÞ   ©r   rò   Úendr   r   r   Úop_SETUP_LOOP{  s
    z!ControlFlowAnalysis.op_SETUP_LOOPc                 C   s<   |  ¡ }| j |¡ | j |j|f¡ |  |j¡ d| _d S rÙ   )r  rà   r‘   rá   r   rü   r  rÞ   r  r   r   r   Úop_SETUP_WITH…  s
    z!ControlFlowAnalysis.op_SETUP_WITHc                 C   s   | j  ¡  d S r   )rà   r‹   r   r   r   r   Úop_POP_BLOCK�  s    z ControlFlowAnalysis.op_POP_BLOCKc                 C   s$   |   | ¡ ¡ |   |j¡ d| _d S rÙ   ©rü   r  r  rÞ   r   r   r   r   Úop_FOR_ITER’  s    zControlFlowAnalysis.op_FOR_ITERc                 C   s$   |   | ¡ ¡ |   |j¡ d| _d S rÙ   r  r   r   r   r   Ú_op_ABSOLUTE_JUMP_IF—  s    z(ControlFlowAnalysis._op_ABSOLUTE_JUMP_IFc                 C   s(   |   | ¡ ¡ | j |jdd� d| _d S )NrÄ   )ræ   Tr  r   r   r   r   Ú_op_ABSOLUTE_JUMP_OR_POP¦  s    z,ControlFlowAnalysis._op_ABSOLUTE_JUMP_OR_POPc                 C   s   |   | ¡ ¡ d| _d S rÙ   ©rü   r  rÞ   r   r   r   r   Úop_JUMP_ABSOLUTE®  s    z$ControlFlowAnalysis.op_JUMP_ABSOLUTEc                 C   s   |   | ¡ ¡ d| _d S rÙ   r  r   r   r   r   Úop_JUMP_FORWARD²  s    z#ControlFlowAnalysis.op_JUMP_FORWARDc                 C   s   d| j _d| _d S rÙ   ©rß   r   rÞ   r   r   r   r   Úop_RETURN_VALUE¸  s    z#ControlFlowAnalysis.op_RETURN_VALUEc                 C   s   d| j _d| _d S rÙ   r  r   r   r   r   Úop_RAISE_VARARGS¼  s    z$ControlFlowAnalysis.op_RAISE_VARARGSc                 C   s   |   | jd ¡ d| _d S )NrÅ   T)rü   rà   rÞ   r   r   r   r   Úop_BREAK_LOOPÀ  s    z!ControlFlowAnalysis.op_BREAK_LOOP)N)r   )%r   r   r   r"   r   rã   rä   rç   r~   rú   rü   rë   rý   rÿ   rþ   r	  r
  r  r  r  Zop_POP_JUMP_IF_FALSEZop_POP_JUMP_IF_TRUEZop_JUMP_IF_FALSEZop_JUMP_IF_TRUEZop_POP_JUMP_FORWARD_IF_FALSEZop_POP_JUMP_BACKWARD_IF_FALSEZop_POP_JUMP_FORWARD_IF_TRUEZop_POP_JUMP_BACKWARD_IF_TRUEr  Zop_JUMP_IF_FALSE_OR_POPZop_JUMP_IF_TRUE_OR_POPr  r  Zop_JUMP_BACKWARDr  r  r  r   r   r   r   rØ   Ù  sD   
>


rØ   )Úcollectionsrª   rz   Únumba.core.irr   Únumba.core.errorsr   Ú	frozensetr  r½   r   Ú
namedtupler   Údefaultdictr&   r0   rØ   r   r   r   r   Ú<module>   s,      ÿÿ     