o
    @a                     @   sp   d Z ddlm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mZ ddlZG d	d
 d
eZdS )z; LoopFullUnrolling fully unrolls loops with static bounds.     )metadata)HasBreakHasContinue	NodeCount)OMPDirective)to_ast)TransformationdeepcopyNc                   @   s   e Zd ZdZdZdd ZdS )LoopFullUnrollinga%  
    Fully unroll loops with static bounds

    >>> import gast as ast
    >>> from pythran import passmanager, backend
    >>> node = ast.parse('for j in [1,2,3]: i += j')
    >>> pm = passmanager.PassManager("test")
    >>> _, node = pm.apply(LoopFullUnrolling, node)
    >>> print(pm.dump(backend.Python, node))
    j = 1
    i += j
    j = 2
    i += j
    j = 3
    i += j

    >>> node = ast.parse('for j in (a,b): i += j')
    >>> pm = passmanager.PassManager("test")
    >>> _, node = pm.apply(LoopFullUnrolling, node)
    >>> print(pm.dump(backend.Python, node))
    j = a
    i += j
    j = b
    i += j

    >>> node = ast.parse('for j in {1}: i += j')
    >>> pm = passmanager.PassManager("test")
    >>> _, node = pm.apply(LoopFullUnrolling, node)
    >>> print(pm.dump(backend.Python, node))
    j = 1
    i += j

    >>> node = ast.parse('for j in builtins.enumerate("1"): j')
    >>> pm = passmanager.PassManager("test")
    >>> _, node = pm.apply(LoopFullUnrolling, node)
    >>> print(pm.dump(backend.Python, node))
    j = (0, '1')
    j
    i   c                    s  t trS  tfddjD }tfddjD }|s)|r+S t}fdddd  dd	 }tj	t
jt
jfrptj	j| }|tjk }|rpd
_t fddtj	jD g S tt
t
j	dd}ztt|dtdi}	W n ty    Y S w t|	| }|tjk }|rzt fddt|	D g }
d
_|
W S  ty    Y S w S )Nc                 3       | ]	}  t|V  qd S N)gatherr   .0nself K/usr/lib/python3/dist-packages/pythran/optimizations/loop_full_unrolling.py	<genexpr>A       z.LoopFullUnrolling.visit_For.<locals>.<genexpr>c                 3   r   r   )r   r   r   r   r   r   r   C   r   c                    s   t t jg| d g| S r   )astZAssignr
   target)eltbody)noder   r   unrollL   s   z+LoopFullUnrolling.visit_For.<locals>.unrollc                 S   s   ||d kr| S t | S )N   r	   )r   ir   r   r   r   dcO   s   z'LoopFullUnrolling.visit_For.<locals>.dcc                 S   s   t t | dd dd S )Nfuncattr)getattr)r   r   r   r   getrangeU   s   z-LoopFullUnrolling.visit_For.<locals>.getrangeTc                    s$   g | ]\}}| j |qS r   )r   r   r   r   )r    
elts_countr   r   r   r   
<listcomp>^   s    z/LoopFullUnrolling.visit_For.<locals>.<listcomp>z<loop unrolling>evalbuiltinsc                    s(   g | ]\}}t | j|qS r   )r   r   r%   )r    r   r   values_countr   r   r'   l   s
    )r   getr   Zgeneric_visitanyr   r   r   
isinstanceiterr   ZTupleZListleneltsr   MAX_NODE_COUNTupdatesum	enumeratecompileZgast_to_astZ
Expressionlistr(   
__import__	Exception)r   r   Z	has_breakZhas_contZ
node_countr$   Ztotal_countZissmallcodevaluesZnew_noder   )r    r&   r   r   r   r*   r   	visit_For8   sd   



zLoopFullUnrolling.visit_ForN)__name__
__module____qualname____doc__r1   r;   r   r   r   r   r      s    (r   )r?   Zpythranr   Zpythran.analysesr   r   r   Zpythran.openmpr   Zpythran.conversionr   Zpythran.passmanagerr   copyr
   Zgastr   r   r   r   r   r   <module>   s    