o
    @a'                     @   s   d Z ddlmZ ddlmZ ddlmZmZmZm	Z	 ddl
mZ ddlZddlZddlZedZG dd	 d	eZG d
d dejZdd Zdd Zdd ZdS )z
This module performs a few early syntax check on the input AST.
It checks the conformance of the input code to Pythran specific
constraints.
    )MODULES)Class)TupleListSetDict)isstrNZpythranc                   @   s   e Zd ZdddZdd ZdS )PythranSyntaxErrorNc                 C   s6   t | | |rt|dd | _|j| _|j| _d S d S )Nfilename)SyntaxError__init__getattrr
   lineno
col_offsetoffset)selfmsgnode r   0/usr/lib/python3/dist-packages/pythran/syntax.pyr      s   zPythranSyntaxError.__init__c                 C   s   | j r<| jr<| jr<t| j %}t| jd D ]}|  qd|  d| j d }W d    n1 s6w   Y  nd }d| j pDd| j| j| jd }|d ur^|d7 }||7 }|d	7 }|S )
N   z{}
{} z
^~~~ (o_0)z{}:{}:{} error: {}
z	<unknown>r   z----
z
----
)	r
   r   r   openrangereadlineformatrstripargs)r   fiZextrarr   r   r   __str__   s(   
zPythranSyntaxError.__str__N)__name__
__module____qualname__r   r!   r   r   r   r   r	      s    
r	   c                   @   s   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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$d% Zd&d' Zd(d) Zd*S )+SyntaxCheckerz
    Visit an AST and raise a PythranSyntaxError upon unsupported construct.

    Attributes
    ----------
    attributes : {str}
        Possible attributes from Pythonic modules/submodules.
    c                    s0   t  _ fdd t D ]} | qdS )z) Gather attributes from MODULES content. c                    sJ   j |   |  D ]}t|tr | qt|tr" |j qdS )z< Recursively save Pythonic keywords as possible attributes. N)
attributesupdatekeysvalues
isinstancedictr   Zfields)module	signaturesave_attributer   r   r   r0   A   s   



z.SyntaxChecker.__init__.<locals>.save_attributeN)setr'   r   r*   )r   r-   r   r/   r   r   =   s
   	
zSyntaxChecker.__init__c                 C   s^   d}t jt jt jt jf}|jD ]}t|t jrt|j	rqt||r#qt
||| | d S )NzUTop level statements can only be assignments, strings,functions, comments, or imports)astFunctionDefZImportZ
ImportFromZAssignbodyr+   ZExprr   valuer	   generic_visit)r   r   errZ	WhiteListnr   r   r   visit_ModuleM   s   


zSyntaxChecker.visit_Modulec                 C   
   t d|)Nz!Interactive session not supportedr	   r   r   r   r   r   visit_InteractiveY      
zSyntaxChecker.visit_Interactivec                 C   r:   )Nz%Interactive expressions not supportedr;   r<   r   r   r   visit_Expression\   r>   zSyntaxChecker.visit_Expressionc                 C   r:   )Nz/Suites are specific to Jython and not supportedr;   r<   r   r   r   visit_Suite_   s   zSyntaxChecker.visit_Suitec                 C   s   t d)NzClasses not supportedr;   )r   _r   r   r   visit_ClassDefc   s   zSyntaxChecker.visit_ClassDefc                 C   s    |  | |jrtd|jd S )Nz+Printing to a specific stream not supported)r6   destr	   r<   r   r   r   visit_Printf   s   
zSyntaxChecker.visit_Printc                 C   r:   )NzWith statements not supportedr;   r<   r   r   r   
visit_Withl   r>   zSyntaxChecker.visit_Withc                 C   r:   )Nz&Call with star arguments not supportedr;   r<   r   r   r   visit_Starredo   s   zSyntaxChecker.visit_Starredc                 C   s   |j d u r
td|d S )NzCall with kwargs not supported)argr	   r<   r   r   r   visit_keywords   s   

zSyntaxChecker.visit_keywordc                 C   s   |  | d S r"   )r6   r<   r   r   r   
visit_Callw   s   zSyntaxChecker.visit_Callc                 C   st   |j tu rt|dr|g}ng }tdg|R  tt}t|j tr6|j|j   kr0|j	ks8n td|d S d S )Nr   zEllipsis are not supportedzlarge int not supported)
r5   Ellipsishasattrr	   npiinfointr+   minmax)r   r   r   rM   r   r   r   visit_Constantz   s   



zSyntaxChecker.visit_Constantc                 C   sB   |j rtd||jjrtd||jjrtd|| | d S )Nzdecorators not supportedzVarargs not supportedzKeyword arguments not supported)decorator_listr	   r   varargkwargr6   r<   r   r   r   visit_FunctionDef   s   

zSyntaxChecker.visit_FunctionDefc                 C   s   |  | |jrtd|d S )Nz'Cause in raise statements not supported)r6   causer	   r<   r   r   r   visit_Raise   s   
zSyntaxChecker.visit_Raisec                 C   s,   |  | |j| jvrtd|j|d S )NzAttribute '{0}' unknown)r6   attrr'   r	   r   r<   r   r   r   visit_Attribute   s   

zSyntaxChecker.visit_Attributec                 C   r:   )Nz@named expression are not supported yet, please open an issue :-)r;   r<   r   r   r   visit_NamedExpr   s   zSyntaxChecker.visit_NamedExprc                 C   sH   |j D ]}t}|jdD ]}||vrtd|j||| }qqdS )z- Check if imported module exists in MODULES. .Module '{0}' unknown.N)namesr   namesplitr	   r   )r   r   aliascurrent_modulepathr   r   r   visit_Import   s   


zSyntaxChecker.visit_Importc                 C   s   |j rtd||jstd||j}t}|dD ]}||vr(td|||| }q|jD ]}|jdkr8q0|j|vrGtd|j||q0dS )a,  
            Check validity of imported functions.

            Check:
                - no level specific value are provided.
                - a module is provided
                - module/submodule exists in MODULES
                - imported function exists in the given module/submodule
        zRelative import not supportedzimport from without moduler[   r\   *z*identifier '{0}' not found in module '{1}'N)levelr	   r-   r   r_   r   r]   r^   )r   r   r-   ra   rb   r`   r   r   r   visit_ImportFrom   s4   






zSyntaxChecker.visit_ImportFromc                 C   r:   )Nz#'exec' statements are not supportedr;   r<   r   r   r   
visit_Exec   r>   zSyntaxChecker.visit_Execc                 C   r:   )Nz%'global' statements are not supportedr;   r<   r   r   r   visit_Global   r>   zSyntaxChecker.visit_GlobalN)r#   r$   r%   __doc__r   r9   r=   r?   r@   rB   rD   rE   rF   rH   rI   rQ   rU   rW   rY   rZ   rc   rf   rg   rh   r   r   r   r   r&   2   s,    	
$r&   c                 C   s   t  |  dS )z7Does nothing but raising PythranSyntaxError when neededN)r&   Zvisit)r   r   r   r   check_syntax   s   rj   c                    s   ddl m}m}m  ddl m}m}m} | j D ]@\}}|| }	|D ]5}
| fdd|
D | }z|||||	 W q# |yX   t	d
||	dtt|jdd	 w qdS )
zh
    Does nothing but raising PythranSyntaxError if specs
    are incompatible with the actual code
    r   )unifyclonetr)FunctionTypeVariableInferenceErrorc                    s   g | ]} |qS r   r   ).0prm   r   r   
<listcomp>   s    zcheck_specs.<locals>.<listcomp>z\Specification for `{}` does not match inferred type:
expected `{}`
got `Callable[[{}], ...]`z, N)Zpythran.types.togrk   rl   rm   rn   ro   rp   	functionsitemsr	   r   joinmapstrtypes)specsr{   rk   rl   rn   ro   rp   fname
signaturesZftyper.   Zsig_typer   rs   r   check_specs   s(   r   c              	   C   s
  ddl m} dd |jD }| ||}|j D ]i\}}z|| }W n ty1   td|w || }	|D ]I}
t	|j
j
}t	|
|krMtd|t	|
|t	|j
j k r`td|t|
D ]\}}|	| rt|ttttfrtd||jj qdq8qd	S )
za
    Does nothing but raising PythranSyntaxError if specs
    references an undefined global
    r   )ArgumentEffectsc                 S   s    i | ]}t |tjr|j|qS r   )r+   r2   r3   r^   )rq   r   r   r   r   
<dictcomp>   s    
z!check_exports.<locals>.<dictcomp>z/Invalid spec: exporting undefined function `{}`z&Too many arguments when exporting `{}`z(Not enough arguments when exporting `{}`zvExporting function '{}' that modifies its {} argument. Beware that this argument won't be modified at Python call siteN)Z!pythran.analyses.argument_effectsr   r4   Zgatherrv   rw   KeyErrorr	   r   lenr   defaults	enumerater+   r   r   r   r   loggerZwarning	__class__r%   )Zpmmodr|   r   Zmod_functionsZargument_effectsr}   r~   ZfnodeZaer.   Z
args_countr   Ztyr   r   r   check_exports   sL   r   )ri   Zpythran.tablesr   Zpythran.intrinsicr   Zpythran.typingr   r   r   r   Zpythran.utilsr   Zgastr2   ZloggingZnumpyrL   Z	getLoggerr   r   r	   ZNodeVisitorr&   rj   r   r   r   r   r   r   <module>   s    
 *