o
    @a                     @   st   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	m
Z
 ddlmZ ddlZdd	 Zd
d ZG dd deZdS )zH
ExtendedSyntaxCheck performs various syntax checks on the pythran AST.
    )ModuleAnalysis)StrictAliasesArgumentEffects)PythranSyntaxError)ConstantIntrFunctionIntr)metadataNc                 C   s2   t | trdS t | tjsdS t| jd tjS )NTFr   )
isinstancer   astFunctionDefr   getbodyZStaticReturnnode r   H/usr/lib/python3/dist-packages/pythran/analyses/extended_syntax_check.pyis_global_constant   s
   
r   c                 C   s   t | ttjfpt| S N)r	   r   r
   r   r   r   r   r   r   	is_global   s   r   c                   @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )ExtendedSyntaxChecka  
    Perform advanced syntax checking, based on strict aliases analysis:
    - is there a function redefinition?
    - is there a function call that does not match the called expression arity?
    - is there an operation that updates a global variable?
    c                 C   s,   d | _ d| _d| _t | _t| tt d S )NF)	resultupdateinassertset	functionsr   __init__r   r   selfr   r   r   r   %   s
   zExtendedSyntaxCheck.__init__c                 C   s`   t |tjsd S z| j|j }W n
 ty   Y d S w |D ]}t|r-td|j	|jqd S )Nz=Cannot modify '{}': global variables are constant in pythran.)
r	   r
   Callstrict_aliasesfuncKeyErrorr   r   formatname)r   r   argaliasesaliasr   r   r   check_global_with_side_effect,   s    z1ExtendedSyntaxCheck.check_global_with_side_effectc                 C   s:   |j | jv rtd|j || j|j  | | d S )NzFunction {} redefined)r#   r   r   r"   addgeneric_visitr   r   r   r   r   visit_FunctionDef;   s   z%ExtendedSyntaxCheck.visit_FunctionDefc                 C   s   | j rtd|d S )Nz4Cannot call a function with side effect in an assert)r   r   )r   r   r$   r   r   r   check_assert_with_side_effectD   s
   z1ExtendedSyntaxCheck.check_assert_with_side_effectc                 C   s   d| _ | | d| _ d S )NTF)r   r)   r*   r   r   r   visit_AssertI   s   

z ExtendedSyntaxCheck.visit_Assertc                    sJ  t |tjrdS t |tjrt fdd|jD S t |tjr& |jS t |tj	rSt
|d|}z j| }W n
 tyC   Y dS w |sHdS tdd |D rSdS t |tjrt
|d|}z j| }W n
 typ   Y dS w |sudS tdd |D rdS t |tjrz j| }W n
 ty   Y dS w tdd |D rdS dS )	NTc                 3   s    | ]}  |V  qd S r   )is_immutable_constant).0eltr   r   r   	<genexpr>S   s    z<ExtendedSyntaxCheck.is_immutable_constant.<locals>.<genexpr>r    Fc                 s       | ]}t |V  qd S r   )r   r/   r&   r   r   r   r1   b       c                 s   r2   r   )r   r3   r   r   r   r1   o   r4   c                 s   s    | ]	}t |tjV  qd S r   )r	   r
   r   r3   r   r   r   r1   x   s    )r	   r
   ZConstantZTuplealleltsZUnaryOpr.   operandr   getattrr   r!   Z	AttributeName)r   r   targetr%   r   r   r   r.   N   sJ   z)ExtendedSyntaxCheck.is_immutable_constantc                 C   s.   |  | |jD ]}| |std|qd S )NzkPythran does not support mutable default values. Use a `None' default and set the value at runtime instead.)r)   defaultsr.   r   )r   r   Zarg_defaultr   r   r   visit_arguments}   s   


z#ExtendedSyntaxCheck.visit_argumentsc              
   C   s~  |  | |j}z| j| }W n ty$   tdt|dd p ||w t }|D ]w}z| j| }t	|D ]\}}|rA|
| q6W n	 tyL   Y nw t|tjsTq*t|jj}	|	t|jj }
t|jt|j }|
|  krv|	kryn nq*|
|	krd}||jt|jjt|j}nd}||j|
|	t|j}t||t	|jD ]\}}||vrq| || | || qd S )Nz+Call to unknown function `{}`, it's a trap!idz1Invalid call to {}: expected {} arguments, got {}z=Invalid {} call: expected between {} and {} arguments, got {})r)   r    r   r!   r   r"   r8   r   argument_effects	enumerater(   r	   r
   r   lenargsr;   keywordsr#   r'   r,   )r   r   r    r%   r>   r&   Zfunc_aesiZeffectZuboundZlboundZcall_args_countmsgr$   r   r   r   
visit_Call   s`   




zExtendedSyntaxCheck.visit_CallN)__name__
__module____qualname____doc__r   r'   r+   r,   r-   r.   r<   rE   r   r   r   r   r      s    	/	r   )rI   Zpythran.passmanagerr   Zpythran.analysesr   r   Zpythran.syntaxr   Zpythran.intrinsicr   r   Zpythranr   Zgastr
   r   r   r   r   r   r   r   <module>   s    
