o
    í@Ëa8  ã                   @   s˜   d 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 dd	lmZ dd	lmZ dd	lZdd	lZG d
d„ de
ƒZd	S )z8 LazynessAnalysis returns number of time a name is use. é    )ÚAliases)ÚArgumentEffects)ÚIdentifiers)ÚPureExpressions)ÚFunctionAnalysis)ÚPythranSyntaxError)Úget_variableÚisattrNc                       sª   e Zd ZdZedƒZejZ‡ fdd„Z	dd„ Z
dd„ Z‡ fd	d
„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZeZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡ fdd „Z‡  ZS )!ÚLazynessAnalysisaž  
    Returns number of time a name is used.

    +inf if it is use in a
    loop, if a variable used to compute it is modify before
    its last use or if it is use in a function call (as it is not an
    interprocedural analysis)

    >>> import gast as ast, sys
    >>> from pythran import passmanager, backend
    >>> code = "def foo(): c = 1; a = c + 2; c = 2; b = c + c + a; return b"
    >>> node = ast.parse(code)
    >>> pm = passmanager.PassManager("test")
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> res['a'], res['b'], res['c']
    (inf, 1, 2)
    >>> code = '''
    ... def foo():
    ...     k = 2
    ...     for i in [1, 2]:
    ...         builtins.print(k)
    ...         k = i
    ...     builtins.print(k)'''
    >>> node = ast.parse(code)
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> (res['i'], res['k']) == (sys.maxsize, 1)
    True
    >>> code = '''
    ... def foo():
    ...     k = 2
    ...     for i in [1, 2]:
    ...         builtins.print(k)
    ...         k = i
    ...         builtins.print(k)'''
    >>> node = ast.parse(code)
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> (res['i'], res['k']) == (sys.maxsize, 2)
    True
    >>> code = '''
    ... def foo():
    ...     d = 0
    ...     for i in [0, 1]:
    ...         for j in [0, 1]:
    ...             k = 1
    ...             d += k * 2
    ...     return d'''
    >>> node = ast.parse(code)
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> res['k']
    1
    >>> code = '''
    ... def foo():
    ...     k = 2
    ...     for i in [1, 2]:
    ...         builtins.print(k)'''
    >>> node = ast.parse(code)
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> res['k'] == sys.maxsize
    True
    >>> code = '''
    ... def foo():
    ...     k = builtins.sum
    ...     builtins.print(k([1, 2]))'''
    >>> node = ast.parse(code)
    >>> res = pm.gather(LazynessAnalysis, node)
    >>> res['k']
    1
    Úinfc                    sP   t ƒ | _t ƒ | _t ƒ | _tƒ | _t ƒ | _tƒ | _t ƒ | _t	t
| ƒ ttt¡ d S ©N)ÚdictÚresultÚ
name_countÚuseÚsetÚdeadÚpre_loop_countÚin_ompÚname_to_nodesÚsuperr
   Ú__init__r   r   r   ©Úself©Ú	__class__© úD/usr/lib/python3/dist-packages/pythran/analyses/lazyness_analysis.pyr   [   s   ÿzLazynessAnalysis.__init__c                    sR   ‡ fdd„| j  ¡ D ƒ}| j |¡ |D ]}dd„ | j| D ƒ}| j |¡ qd S )Nc                    s   g | ]
\}}ˆ |v r|‘qS r   r   )Ú.0ÚvarÚdeps©Únamer   r   Ú
<listcomp>q   s    z+LazynessAnalysis.modify.<locals>.<listcomp>c                 S   s   g | ]}t |tjƒr|j‘qS r   )Ú
isinstanceÚastÚNameÚid)r   Úaliasr   r   r   r#   t   s    
ÿ)r   Úitemsr   Úupdater   )r   r"   Z	dead_varsr   Zdead_aliasesr   r!   r   Úmodifyn   s   ýzLazynessAnalysis.modifyc                 C   sÎ   t |tjƒr| j |jtƒ ¡ |¡ |j| jv r| j 	|j¡ t
| j |jd¡| j |jd¡ƒ| j|j< | j |j¡ | j |jd¡}|d sQ|d df| j|j< |  |j¡ d| j|j< t|ƒ| j|j< d S )Nr   )r   Té   T)r$   r%   r&   r   Ú
setdefaultr'   r   Úaddr   ÚremoveÚmaxr   Úgetr   r   Údiscardr   r+   r   )r   ÚnodeZfrom_Úpre_loopr   r   r   Ú	assign_tox   s   ÿzLazynessAnalysis.assign_toc                    s”   | j }t |tj¡}|rt| j ¡ ƒ| _ tt	| ƒ 
|¡ |rEt| jƒ | j ¡}|D ]}|jD ]}t|tjƒr=t	j| j|j< q.q)| j |¡ || _ d S r   )r   Úmdr1   ÚopenmpZOMPDirectiver   r   Úkeysr   r
   ÚvisitÚ
differencer    r$   r%   r&   ÚINFr   r'   r   r*   )r   r3   Zold_ompZ	omp_nodesZ	new_nodesZomp_nodeÚnr   r   r   r9      s   
€þ
zLazynessAnalysis.visitc                 C   s   |   t|¡| _|  |¡ d S r   )Úgatherr   ÚidsZgeneric_visit)r   r3   r   r   r   Úvisit_FunctionDefœ   s   z"LazynessAnalysis.visit_FunctionDefc                 C   s¶   t  | |¡ |  |j¡ |  t|j¡}|jD ]B}t|tjƒr2|  	||¡ |j| j
vr1tj| j|j< qt|tjƒs<t|ƒrTt|ƒ}t|tjƒrS|  |j¡ tj| j|j< qtd|ƒ‚d S )NzAssign to unknown node)r6   r9   Úvaluer=   r   Útargetsr$   r%   r&   r5   Zpure_expressionsr
   r;   r   r'   Ú	Subscriptr	   r   r+   r   )r   r3   r>   ÚtargetÚvar_namer   r   r   Úvisit_Assign    s"   
€€
òzLazynessAnalysis.visit_Assignc                 C   s’   t  | |¡ |  |j¡ t|jtjƒr$|  |jj¡ t	j
| j|jj< d S t|jtjƒs0t|jƒrDt|jƒ}|  |j¡ t	j
| j|j< d S td|ƒ‚)NzAugAssign to unknown node)r6   r9   r@   r$   rC   r%   r&   r+   r'   r
   r;   r   rB   r	   r   r   )r   r3   rD   r   r   r   Úvisit_AugAssign´   s   

z LazynessAnalysis.visit_AugAssignc                    s8  t |jtjƒrl|jˆjv rl‡fdd„‰ ‡ fdd„ˆj| D ƒ}dd„ |D ƒ}| |j¡ |D ];}|jˆjv s<|jˆj	v rCt
jˆj|< q.|ˆjv rhˆj|  d7  < ˆj |d¡}|d sg|d	 d d
fˆj|< q.	 q.d S t |jtjƒr‚d	ˆj|j< tƒ ˆj|j< d S t |jtjƒr™t
jˆj|j< tƒ ˆj|j< d S 	 d S )Nc                    s   t | tjƒo| jˆ jv S r   )r$   r%   r&   r'   r>   )Úxr   r   r   Ú
is_loc_varÊ   s   z/LazynessAnalysis.visit_Name.<locals>.is_loc_varc                    s   g | ]}ˆ |ƒr|‘qS r   r   )r   r   )rH   r   r   r#   Ì   s    
ÿz/LazynessAnalysis.visit_Name.<locals>.<listcomp>c                 S   s   h | ]}|j ’qS r   )r'   )r   rG   r   r   r   Ú	<setcomp>Î   s    z.LazynessAnalysis.visit_Name.<locals>.<setcomp>r,   )r   Fr   F)r$   Úctxr%   ZLoadr'   r   Úaliasesr.   r   r   r
   r;   r   r   r   r-   ZParamr   ZStore)r   r3   Zalias_namesr(   r4   r   )rH   r   r   Ú
visit_NameÆ   s6   
ÿ
ÿ€òzLazynessAnalysis.visit_Namec                 C   sj  t  | |¡ |  |j¡ t| jƒ}t| jƒ}dd„ | j ¡ D ƒ}t	|j
tƒr)|j
n|j
g}|D ]}|  |¡ q/| j}| j}| j}	|| _|| _|| _t	|jtƒrR|jn|jg}
|
D ]}|  |¡ qX| jD ]}||	v rs| j|  |	| ¡ qc|	D ]}|| jvr†t|	| ƒ| j|< qvt| j ¡ ƒ | ¡ ¡}|D ]}| |d¡}| j |d¡}t||ƒ| j|< q•| j |¡ d S )Nc                 S   s   i | ]	\}}|t |ƒ“qS r   )r   )r   ÚaÚbr   r   r   Ú
<dictcomp>ï   s    z-LazynessAnalysis.visit_If.<locals>.<dictcomp>r   )r6   r9   Útestr   r   r   r   r   r)   r$   ÚbodyÚlistÚorelser*   r8   Úunionr1   r0   )r   r3   Z	old_countZold_deadZold_depsrQ   ÚstmtZ	mid_countZmid_deadZmid_depsrS   ÚkeyÚnamesr"   Zval_bodyZval_elser   r   r   Úvisit_Ifê   sB   

ÿ
€
€zLazynessAnalysis.visit_Ifc           	      C   s  | j }tƒ | _ |D ]}|  |¡ q	dd„ | j  ¡ D ƒ}| j t|tjgt	|ƒ ƒ¡ | j  ¡ D ]\}}|d | j
|  }t| j |d¡|ƒ| j|< q/| j | j ¡}| j t|tjgt	|ƒ ƒ¡ | ¡ D ](\}}|d sq|| j vrw|| j |< qd|d | j | d  | j | d f| j |< qdd S )Nc                 S   s   g | ]
\}\}}|s|‘qS r   r   )r   r<   Ú_rM   r   r   r   r#   "  s    
ÿz/LazynessAnalysis.visit_loop.<locals>.<listcomp>r   r,   )r   r   r9   r)   r   r*   Úzipr
   ÚMANYÚlenr   r0   r1   r   Úintersectionr;   )	r   rQ   Zold_pre_countrU   Z	no_assignÚkÚvZ
loop_valuer   r   r   r   Ú
visit_loop  s(   
ÿÿüzLazynessAnalysis.visit_loopc                 C   s|   t  | |¡ |  t|j¡}t|jtjƒr$|  	|j|¡ t
j| j|jj< nd}t||ƒ‚|  |j¡ |jD ]}|  |¡ q4d S )Nz%Assignation in for loop not to a Name)r6   r9   r=   r   Úiterr$   rC   r%   r&   r5   r
   r;   r   r'   r   r`   rQ   rS   )r   r3   r>   ÚerrrU   r   r   r   Ú	visit_For7  s   

ÿzLazynessAnalysis.visit_Forc                 C   s>   t  | |¡ |  |j¡ |  |j¡ |jD ]}|  |¡ qd S r   )r6   r9   rP   r`   rQ   rS   )r   r3   rU   r   r   r   Úvisit_WhileF  s   
ÿzLazynessAnalysis.visit_Whilec                 C   sº   | j | D ]U}t|tjƒr|  |jd |jdd … | |¡ q|| jv rIt| j| ƒD ]\}}|rGt|ƒ|krGt|| tj	ƒrG|  
|| j¡ q+qt|tj	ƒrPq|D ]}|  
|¡ qRqd S )Nr   r,   )rK   r$   r%   ZCallÚfunc_args_lazynessÚargsZargument_effectsÚ	enumerater\   r&   r+   r'   )r   Z	func_namerf   r3   ZfunÚiÚargr   r   r   re   O  s    $
€üÿðz#LazynessAnalysis.func_args_lazynessc                 C   sD   t  | |¡ |jD ]}|  |¡ q	|  |j|j|¡ |  |j¡ dS )zÌ
        Compute use of variables in a function call.

        Each arg is use once and function name too.
        Information about modified arguments is forwarded to
        func_args_lazyness.
        N)r6   r9   rf   re   Úfunc)r   r3   ri   r   r   r   Ú
visit_Callc  s
   
zLazynessAnalysis.visit_Callc                    sJ   t t| ƒ |¡}| j ¡ D ]\}}| |d¡}t||ƒ||< q|| _| jS )Nr   )r   r
   Úrunr   r)   r1   r0   r   )r   r3   r   r"   ÚvalZold_valr   r   r   rl   q  s   zLazynessAnalysis.run)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úfloatr;   ÚsysÚmaxsizer[   r   r+   r5   r9   r?   rE   rF   rL   rX   Zvisit_IfExpr`   rc   rd   re   rk   rl   Ú__classcell__r   r   r   r   r
      s(    E
$,	r
   )rq   Zpythran.analyses.aliasesr   Z!pythran.analyses.argument_effectsr   Zpythran.analyses.identifiersr   Z!pythran.analyses.pure_expressionsr   Zpythran.passmanagerr   Zpythran.syntaxr   Zpythran.utilsr   r	   Zpythran.metadataZmetadatar6   Zpythran.openmpr7   Zgastr%   rs   r
   r   r   r   r   Ú<module>   s    