o
    í@Ëaz  ã                   @   sh   d Z ddlmZ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ddlmZ G dd	„ d	eƒZdS )
z+ Simplify modulo computation based on indexé    )ÚUseDefChainsÚ	AncestorsÚAliasesÚRangeValues)ÚIdentifiers)ÚTransformation)ÚMODULESN)Údeepcopyc                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚModIndexa]  
    Simplify modulo on loop index

    >>> import gast as ast
    >>> from pythran import passmanager, backend
    >>> pm = passmanager.PassManager("test")
    >>> code = """
    ... def foo(x):
    ...     y = builtins.len(x)
    ...     for i in builtins.range(8):
    ...         z = i % y"""
    >>> node = ast.parse(code)
    >>> _, node = pm.apply(ModIndex, node)
    >>> print(pm.dump(backend.Python, node))
    def foo(x):
        y = builtins.len(x)
        i_m = ((0 - 1) % y)
        for i in builtins.range(8):
            i_m = (0 if ((i_m + 1) == y) else (i_m + 1))
            z = i_m
    c                 C   s    t  | ttttt¡ tƒ | _d S )N)	r   Ú__init__r   r   r   r   r   ÚdictÚ	loops_mod)Úself© r   ú@/usr/lib/python3/dist-packages/pythran/optimizations/modindex.pyr   #   s   ÿzModIndex.__init__c                 C   s    | j | }t|ƒdko|d jS )Né   r   )Zuse_def_chainsÚlenÚnode)r   r   Úchainr   r   r   Ú
single_def(   s   
zModIndex.single_defc                 C   sŠ  t |jtjƒs|  |¡S t |jtjƒs|  |¡S |  |j¡}|s%|  |¡S | j|jj	 j
dk r4|  |¡S t |jtjƒs@|  |¡S |  |j¡}|sM|  |¡S | j| d }t |tjƒs_|  |¡S t |jtjƒsk|  |¡S || j| v rw|  |¡S d }| j|jj D ]}|td d u r|}q€ |d u r—|  |¡S |jj	d }d}|| jv rµd |jj	|¡}|d7 }|| jv s¤|jj}	t|	ƒdkrÃ|	d nt dd ¡}
t t |t ¡ d d ¡gt t t|
ƒt ¡ t dd ¡¡t ¡ t|jƒ¡d ¡}t t |t ¡ d d ¡t ¡ t dd ¡¡}t t |t ¡ d d ¡gt t  |t !¡ gt|jƒg¡t dd ¡t|ƒ¡d ¡}| j" #|g ¡ $||f¡ d| _%t |t ¡ d d ¡S )	Nr   éÿÿÿÿÚbuiltinsÚrangeZ_mz{}_m{}r   T)&Ú
isinstanceÚopÚastZModÚgeneric_visitÚrightÚNamer   Zrange_valuesÚidZlowÚleftZ	ancestorsZForÚiterZCallÚaliasesÚfuncr   ZidentifiersÚformatÚargsr   ZConstantZAssignZStoreZBinOpr	   ZSubZLoadZAddZIfExpZCompareZEqr   Ú
setdefaultÚappendÚupdate)r   r   Z	right_defÚheadZloopZrange_ÚaliasZnew_idÚiZrargsÚlowerÚheaderZincrÚstepr   r   r   Úvisit_BinOp,   s€   











þ 

þûù
þÿ
üúzModIndex.visit_BinOpc                 C   sV   |   |¡ || jvr|S dd„ | j| D ƒ}dd„ | j| D ƒ}||j |_||g S )Nc                 S   s   g | ]\}}|‘qS r   r   )Ú.0ÚhÚ_r   r   r   Ú
<listcomp>   ó    z&ModIndex.visit_For.<locals>.<listcomp>c                 S   s   g | ]\}}|‘qS r   r   )r0   r2   Úsr   r   r   r3   ‚   r4   )r   r   Úbody)r   r   ZheadersZstepsr   r   r   Ú	visit_For|   s   


zModIndex.visit_ForN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r/   r7   r   r   r   r   r
      s    Pr
   )r;   Zpythran.analysesr   r   r   r   r   Zpythran.passmanagerr   Zpythran.tablesr   Zgastr   Úcopyr	   r
   r   r   r   r   Ú<module>   s    