o
    í@Ëa¤  ã                   @   sÀ   d Z ddlZddlZddlZdd„ ZG dd„ deƒZG dd„ deƒZG d	d
„ d
eej	ƒZ
G dd„ de
ƒZG dd„ de
ƒZG dd„ de
ƒZG dd„ deƒZG dd„ deejƒZG dd„ deƒZdS )ao  
This module provides classes and functions for pass management.

There are two kinds of passes: transformations and analysis.
    * ModuleAnalysis, FunctionAnalysis and NodeAnalysis are to be
      subclassed by any pass that collects information about the AST.
    * gather is used to gather (!) the result of an analyses on an AST node.
    * Backend is to be sub-classed by any pass that dumps the AST content.
    * dump is used to dump (!) the AST using the given backend.
    * Transformation is to be sub-classed by any pass that updates the AST.
    * apply is used to apply (sic) a transformation on an AST node.
é    Nc                 C   s    t  dd| ¡}t  dd|¡ ¡ S )z<Transform CamelCase naming convention into C-ish convention.z(.)([A-Z][a-z]+)z\1_\2z([a-z0-9])([A-Z]))ÚreÚsubÚlower)ÚnameÚs1© r   ú5/usr/lib/python3/dist-packages/pythran/passmanager.pyÚuncamel   s   r	   c                   @   s   e Zd ZdZdd„ ZdS )ÚAnalysisContextz{
    Class that stores the hierarchy of node visited.

    Contains:
        * parent module
        * parent function
    c                 C   s   d | _ d | _d S ©N)ÚmoduleÚfunction)Úselfr   r   r   Ú__init__#   s   
zAnalysisContext.__init__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r
      s    r
   c                       sV   e Zd ZdZ‡ fdd„Zddd„Zdd„ Z‡ fd	d
„Zdd„ Zdd„ Z	dd„ Z
‡  ZS )ÚContextManagerzŽ
    Class to be inherited from to add automatic update of context.

    The optional analysis dependencies are listed in `dependencies'.
    c                    s    || _ |  ¡  tt| ƒ ¡  dS )z3 Create default context and save all dependencies. N)ÚdepsÚverify_dependenciesÚsuperr   r   ©r   Zdependencies©Ú	__class__r   r   r   0   s   zContextManager.__init__Nc                 C   s   || _ |ptƒ | _d S r   )Úpassmanagerr
   Úctx)r   Zpmr   r   r   r   Úattach6   s   zContextManager.attachc                 C   sJ   t dt| jƒƒD ]}t| j| tƒr"t| j|d  tƒr"J d|  ƒ‚qdS )z…
        Checks no analysis are called before a transformation,
        as the transformation could invalidate the analysis.
        é   zinvalid dep order for %sN)ÚrangeÚlenr   Ú
isinstanceÚTransformationÚAnalysis)r   Úir   r   r   r   :   s   ÿþ€ÿz"ContextManager.verify_dependenciesc                    s\   t |tjƒr&|| j_| jD ]}t|tƒr%| jj	||f }t
| t|jƒ|ƒ qtt| ƒ |¡S r   )r!   ÚastÚFunctionDefr   r   r   Ú
issubclassÚFunctionAnalysisr   Ú_cacheÚsetattrr	   r   r   r   Úvisit)r   ÚnodeÚDÚresultr   r   r   r+   E   s   

€zContextManager.visitc                 C   sl   t |tjƒr|| j_n
t |tjƒr|| j_| jD ]}|ƒ }| | j	| j¡ | 
|¡}t| t|jƒ|ƒ qdS )z0Gather analysis result required by this analysisN)r!   r%   ÚModuler   r   r&   r   r   r   r   Úrunr*   r	   r   )r   r,   r-   Údr.   r   r   r   ÚprepareP   s   


üzContextManager.preparec                 C   s   |   |¡ |  |¡S )z=Override this to add special pre or post processing handlers.)r2   r+   ©r   r,   r   r   r   r0   ]   ó   

zContextManager.runc                 C   s    |ƒ }|  | j| j¡ | |¡S r   )r   r   r   r0   ©r   Zanalysisr,   Úar   r   r   Úgatherb   s   
zContextManager.gatherr   )r   r   r   r   r   r   r   r+   r2   r0   r7   Ú__classcell__r   r   r   r   r   (   s    
r   c                       s8   e Zd ZdZdd„ Z‡ fdd„Zdd„ Zdd	„ Z‡  ZS )
r#   zT
    A pass that does not change its content but gathers informations about it.
    c                 G   s.   t | dƒs	J dƒ‚d| _tj| g|¢R Ž  dS )z`dependencies' holds the type of all analysis required by this
            analysis. `self.result' must be set prior to calling this
            constructor.r.   z9An analysis must have a result attribute when initializedFN)ÚhasattrÚupdater   r   r   r   r   r   r   l   s
   ÿzAnalysis.__init__c                    sP   |t | ƒf}|| jjv r| jj| | _| jS tt| ƒ |¡ | j| jj|< | jS r   )Útyper   r)   r.   r   r#   r0   )r   r,   Úkeyr   r   r   r0   u   s   þzAnalysis.runc                 C   s   t |ƒ d S r   )Úprint)r   Údatar   r   r   Údisplay~   s   zAnalysis.displayc                 C   s   |   |  |¡¡ d|fS )NF)r?   r0   r3   r   r   r   Úapply   s   zAnalysis.apply)	r   r   r   r   r   r0   r?   r@   r8   r   r   r   r   r#   h   s    		r#   c                       ó    e Zd ZdZ‡ fdd„Z‡  ZS )ÚModuleAnalysisz,An analysis that operates on a whole module.c                    sD   t |tjƒs| jjd u rtd t| ƒj¡ƒ‚| jj}t	t
| ƒ |¡S ©Nz%{} called in an uninitialized context)r!   r%   r/   r   r   Ú
ValueErrorÚformatr;   r   r   rB   r0   r3   r   r   r   r0   ‰   s   ÿzModuleAnalysis.run©r   r   r   r   r0   r8   r   r   r   r   rB   †   s    rB   c                       rA   )r(   z(An analysis that operates on a function.c                    s–   t |tjƒr)|| j_d }|jD ]}t |tjƒr|  t| ƒ|¡}q|d u r'| j	S |S t |tjƒsC| jj
d u r?td t| ƒj¡ƒ‚| jj
}tt| ƒ |¡S rC   )r!   r%   r/   r   r   Úbodyr&   r7   r;   r.   r   rD   rE   r   r   r(   r0   )r   r,   ZlastZstmtr   r   r   r0   –   s   
€ÿzFunctionAnalysis.runrF   r   r   r   r   r(   ’   s    r(   c                   @   ó   e Zd ZdZdS )ÚNodeAnalysisz&An analysis that operates on any node.N©r   r   r   r   r   r   r   r   rI   §   ó    rI   c                   @   rH   )ÚBackendz&A pass that produces code from an AST.NrJ   r   r   r   r   rL   ¬   rK   rL   c                       s4   e Zd ZdZ‡ fdd„Z‡ fdd„Zdd„ Z‡  ZS )r"   z A pass that updates its content.c                    s    t t| ƒj|i |¤Ž d| _dS )z8 Initialize the update used to know if update happened. FN)r   r"   r   r:   )r   ÚargsÚkwargsr   r   r   r   µ   s   
zTransformation.__init__c                    s0   t t| ƒ |¡}| jrt |¡ | jj ¡  |S )zA Apply transformation and dependencies and fix new node location.)	r   r"   r0   r:   r%   Zfix_missing_locationsr   r)   Úclear)r   r,   Únr   r   r   r0   º   s
   
zTransformation.runc                 C   s   |   |¡}| j|fS )z8 Apply transformation and return if an update happened. )r0   r:   )r   r,   Znew_noder   r   r   r@   Æ   r4   zTransformation.apply)r   r   r   r   r   r0   r@   r8   r   r   r   r   r"   ±   s
    r"   c                   @   s2   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdS )ÚPassManagerz/
    Front end to the pythran pass system.
    Nc                 C   s   || _ |pt ¡ | _i | _d S r   )Úmodule_nameÚosÚgetcwdÚ
module_dirr)   )r   rR   rU   r   r   r   r   Ð   s   
zPassManager.__init__c                 C   ó(   t |tƒsJ ‚|ƒ }| | ¡ | |¡S )z5High-level function to call an `analysis' on a `node')r'   r#   r   r0   r5   r   r   r   r7   Õ   s   

zPassManager.gatherc                 C   rV   )zfHigh-level function to call a `backend' on a `node' to generate
        code for module `module_name'.)r'   rL   r   r0   )r   Zbackendr,   Úbr   r   r   ÚdumpÜ   s   

zPassManager.dumpc                 C   s,   t |ttfƒs	J ‚|ƒ }| | ¡ | |¡S )z¬
        High-level function to call a `transformation' on a `node'.
        If the transformation is an analysis, the result of the analysis
        is displayed.
        )r'   r"   r#   r   r@   )r   Ztransformationr,   r6   r   r   r   r@   ä   s   

zPassManager.applyr   )r   r   r   r   r   r7   rX   r@   r   r   r   r   rQ   Ì   s    
rQ   )r   Zgastr%   rS   r   r	   Úobjectr
   r   ZNodeVisitorr#   rB   r(   rI   rL   ZNodeTransformerr"   rQ   r   r   r   r   Ú<module>   s    @