o
    @ad                     @   sV   d Z ddlmZmZ ddlmZ ddlZddlZG dd deZ	G dd dej
ZdS )	z! Inlining inline functions body.     )	InlinableAliases)TransformationNc                       sX   e Zd ZdZ fddZdd ZeZeZeZeZ	eZ
eZeZeZeZeZdd Z  ZS )Inlininga  
    Inline one line functions.

    >>> import gast as ast
    >>> from pythran import passmanager, backend
    >>> pm = passmanager.PassManager("test")
    >>> node = ast.parse('''
    ... def foo(a, b):
    ...     return b + b * a
    ... def bar(b):
    ...     return foo(2 * b, b) * foo(b, b)''')
    >>> _, node = pm.apply(Inlining, node)
    >>> print(pm.dump(backend.Python, node))
    def foo(a, b):
        return (b + (b * a))
    def bar(b):
        __pythran_inlinefooa0 = (2 * b)
        __pythran_inlinefoob0 = b
        __pythran_inlinefooa1 = b
        __pythran_inlinefoob1 = b
        return ((__pythran_inlinefoob0 + (__pythran_inlinefoob0 * __pythran_inlinefooa0)) * (__pythran_inlinefoob1 + (__pythran_inlinefoob1 * __pythran_inlinefooa1)))
    c                    s*   d| _ t | _d| _tt| tt dS )z6 fun : Function {name :body} for inlinable functions. Fr   N)	updatelistdefs
call_countsuperr   __init__r   r   )self	__class__ @/usr/lib/python3/dist-packages/pythran/optimizations/inlining.pyr   %   s   zInlining.__init__c                 C   s8   | j pt t }| _ | | | j |}| _ ||g S )z3 Add new variable definition before the Statement. )r   r   Zgeneric_visit)r   nodeZ	save_defsZnew_defsr   r   r   
visit_Stmt,   s   

zInlining.visit_Stmtc                 C   s$  | j |j }t|dkrtt|}t|tjr|j| j	v rd| _
t| j	|j }t }|j}||jjt|jt|jj d 7 }t|jj|D ]4\}}d|j|j| j}	tj|	t ddd}
| jtj|
g|dd tj|	t ddd||j< qJ|  jd7  _t||jd S |S )z~
        Replace function call by inlined function's body.

        We can inline if it aliases on only one function.
           TNz__pythran_inline{}{}{})idctx
annotationtype_comment)targetsvaluer   r   )aliasesfunclennextiter
isinstanceastZFunctionDefnameZ	inlinabler   copyZdeepcopydictargsdefaultszipformatr   r	   NameZStorer   appendZAssignZLoadInlinervisitbody)r   r   Zfunc_aliasesZfunction_defZ	to_inlineZarg_to_valuevaluesZarg_funZarg_callZv_nameZnew_varr   r   r   
visit_Call>   sD   

zInlining.visit_Call)__name__
__module____qualname____doc__r   r   visit_ReturnZvisit_AssignZvisit_AugAssignZvisit_PrintZ	visit_ForZvisit_WhileZvisit_IfZ
visit_WithZvisit_AssertZ
visit_Exprr.   __classcell__r   r   r   r   r   
   s    r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )r*   z> Helper transform that performed inlined body transformation. c                    s   || _ tt|   dS )z; match : {original_variable_name : Arguments use on call}. N)matchr
   r*   r   )r   r5   r   r   r   r   f   s   zInliner.__init__c                 C   s   | j |j|S )z0 Transform name from match values if available. )r5   getr   r   r   r   r   r   
visit_Namek   s   zInliner.visit_Namec                 C   s   |  |jS )z% Remove return keyword after inline. )r+   r   r7   r   r   r   r3   o   s   zInliner.visit_Return)r/   r0   r1   r2   r   r8   r3   r4   r   r   r   r   r*   b   s
    r*   )r2   Zpythran.analysesr   r   Zpythran.passmanagerr   Zgastr    r"   r   ZNodeTransformerr*   r   r   r   r   <module>   s    X