U
    {hz*                     @   s   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
mZmZ d dlmZ d dl mZ G dd	 d	eZd
d ZG dd dZG dd dZdd Zdd Zdd ZdS )   )Nodes	ExprNodes	FusedNodeNaming)error)
PyrexTypes)CythonUtilityCode)TempitaUtilityCodeUtilityCode)TreeVisitor)Symtabc                   @   s,   e Zd ZdZdZdd Zdd Zdd ZdS )	_FindCFuncDefNodezf
    Finds the CFuncDefNode in the tree

    The assumption is that there's only one CFuncDefNode
    Nc                 C   s   | j r
d S | | d S N)
found_nodeZvisitchildrenselfnode r   :/tmp/pip-unpacked-wheel-fhl22ezh/Cython/Compiler/UFuncs.py
visit_Node   s    z_FindCFuncDefNode.visit_Nodec                 C   s
   || _ d S r   )r   r   r   r   r   visit_CFuncDefNode   s    z$_FindCFuncDefNode.visit_CFuncDefNodec                 C   s   |  | | jS r   )visitr   )r   treer   r   r   __call__!   s    
z_FindCFuncDefNode.__call__)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r      s
   r   c                 C   s
   t  | S r   )r   )r   r   r   r   get_cfunc_from_tree&   s    r   c                   @   s   e Zd ZdZdd ZdS )_ArgumentInfoa/  
    Everything related to defining an input/output argument for a ufunc

    type  - PyrexType
    type_constant  - str such as "NPY_INT8" representing numpy dtype constants
    injected_typename - str representing a name that can be used to look up the type
                        in Cython code
    c                 C   s   || _ || _|| _d S r   )typetype_constantinjected_typename)r   r    r!   r"   r   r   r   __init__4   s    z_ArgumentInfo.__init__N)r   r   r   r   r#   r   r   r   r   r   *   s   	r   c                   @   sD   e 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S )UFuncConversionc                 C   sX   || _ |j | _d| _| j jj| jr:|  jd7  _qg | _|  | _	| 
 | _d S )NZufunc_typename_)r   local_scopeglobal_scoper"   entrycname
startswithinjected_typesget_in_type_infoin_definitionsget_out_type_infoout_definitionsr   r   r   r   r#   ;   s    
zUFuncConversion.__init__c                 C   sP   |  }| dddd}t|||d}| jtjdd|d d| S )	Nr%   __ )Ztype_substituted_cname
macro_nameZ
type_cnameZUFuncTypedef
UFuncs_C.ccontextZ__Pyx_typedef_ufunc_)Zempty_declaration_codestripreplacedictr'   use_utility_coder	   load)r   type_r2   declZsubstituted_cnamer5   r   r   r   _handle_typedef_type_constantF   s    z-UFuncConversion._handle_typedef_type_constantc                 C   s   |}|j r|j}t|}|tjkr6t|d|  d S |jrH| |dS |jrd}|j	tj
krdd}n|j	tjkrtd}| |d| dS |jr| |dS |jrd	S t|d|  d S )
Nz,Type '%s' cannot be used as a ufunc argumentZ__PYX_GET_NPY_COMPLEX_TYPE SUZ__PYX_GET_NPY_ZINT_TYPEZ__PYX_GET_NPY_FLOAT_TYPEZ
NPY_OBJECT)Z
is_typedefZtypedef_base_typer   Zremove_cv_refZc_bint_typer   Z
is_complexr=   Zis_intsignedZSIGNEDZUNSIGNEDZis_floatis_pyobject)r   posr;   Z	base_typerA   r   r   r   _get_type_constantV   s<    


z"UFuncConversion._get_type_constantc                 C   s`   g }t | jjD ]J\}}| j d| }| j| | | jj|j}|t	|j|| q|S )NZ_in_)
	enumerater   argsr"   r+   appendrD   rC   r    r   )r   definitionsnargr"   
type_constr   r   r   r,   v   s    z UFuncConversion.get_in_type_infoc                 C   sx   | j jjr| j jj}n
| j jg}g }t|D ]F\}}| j d| }| j| | | j j	|}|t
||| q,|S )NZ_out_)r   return_typeZ	is_ctuple
componentsrE   r"   r+   rG   rD   rC   r   )r   rM   rH   rI   r    r"   rK   r   r   r   r.      s    


z!UFuncConversion.get_out_type_infoc           
   	   C   s   dd | j D }dd | jD }t|| }d| jj_| j| jjjd }t	dd |D pnt	dd |D  }tf |||| jjj
| jjjj|d	|}td
d | jj}|j| jjj
| jjj
| jjj| jjdd tjdd||d}|jdd}	|	S )Nc                 S   s   g | ]}|j |jfqS r   r"   r    .0ar   r   r   
<listcomp>   s     z<UFuncConversion.generate_cy_utility_code.<locals>.<listcomp>c                 S   s   g | ]}|j |jfqS r   rN   rO   r   r   r   rR      s     TZ
_ufunc_defc                 s   s   | ]\}}|j V  qd S r   rB   rP   r%   tr   r   r   	<genexpr>   s     z;UFuncConversion.generate_cy_utility_code.<locals>.<genexpr>c                 s   s   | ]\}}|j V  qd S r   rS   rT   r   r   r   rV      s     )Z
func_cnameZin_types	out_typesZinline_func_callnogilwill_be_called_without_gilZufunc_moduleextern)namer)   r    rC   Z
visibilityZUFuncDefinitionz
UFuncs.pyx)r5   Z
from_scope)Zentries_only)r-   r/   r8   r   r(   usedr'   next_idr[   anyr)   r    rX   r   ZModuleScoper5   Zdeclare_cfunctionrC   r   r:   Zget_tree)
r   Z	arg_typesrW   Zcontext_typesZufunc_cnamerY   r5   Zufunc_global_scopecoder   r   r   r   generate_cy_utility_code   sL    


  z(UFuncConversion.generate_cy_utility_codec                 C   s@   | j tdd | j tdd | j tdd d S )NZ
UFuncsInitr3   ZUFuncTypeHandlingZNumpyImportUFunczNumpyImportArray.c)r'   r9   r
   Zload_cached)r   r   r   r   use_generic_utility_code   s    


z(UFuncConversion.use_generic_utility_codeN)
r   r   r   r#   r=   rD   r,   r.   r`   ra   r   r   r   r   r$   :   s    	+r$   c                 C   s   t | tjr6| jjjr&t| jd | S t| g}| }n^t | t	j
rt | jtjr| jjjjrlt| jd | S dd | jD }| j}nt| jd | S |sd S |d jj|jj= |d   | gt|| S )Nz0Methods cannot currently be converted to a ufuncc                 S   s   g | ]}t |qS r   )r$   )rP   rI   r   r   r   rR      s     z$convert_to_ufunc.<locals>.<listcomp>z,Only C functions can be converted to a ufunc    )
isinstancer   ZCFuncDefNoder&   Zparent_scopeZis_c_class_scoper   rC   r$   r   ZFusedCFuncDefNoder   Znodesr'   entriesr(   r[   ra   _generate_stats_from_converters)r   
convertersoriginal_noder   r   r   convert_to_ufunc   s,    

 rh   c                 C   s  | d j }|tjd }|tjd }|tjd }g }d }d }	| D ]|}
dd |
jD }|d k	rx|t|kstnt|}|| dd |
jD }|	d k	r|	t|kstnt|}	|| qJdd |D }t	|||||d	}|
tjd
d|d |j}|jj}|j}d|||t|||	||r4| ndf }tj|dttjtdtjd gtj|tj|dgd}||tj|}tj|tj||tj|d|d}|S )Nrb   funcstypesdatac                 S   s   g | ]
}|j qS r   r!   rP   dr   r   r   rR      s     z1generate_ufunc_initialization.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   rl   rm   r   r   r   rR      s     c                 S   s   g | ]}|j jqS r   )r(   r)   )rP   Zcfnoder   r   r   rR      s     )ufunc_funcs_namefunc_cnamesufunc_types_nametype_constantsufunc_data_nameZUFuncConstsr3   r4   z5%s(), %s, %s(), %s, %s, %s, PyUFunc_None, "%s", %s, 0ZNULLZPyUFunc_FromFuncAndDatadummy)r    value)Zfunction_nameZ	func_typerF   )r[   r    r(   )lhsrhs)r'   r]   r   Zpyrex_prefixr-   lenAssertionErrorextendr/   r8   r9   r	   r:   rC   r(   r[   docZas_c_string_literalr   ZPythonCapiCallNoder   Z	CFuncTypeZpy_object_typeZCFuncTypeArgZc_void_ptr_typeZ	ConstNodeZdeclare_varr   ZSingleAssignmentNodeZNameNode)rf   Zcfunc_nodesrg   r'   ro   rq   rs   rr   Znarg_inZnarg_outcZin_constZ	out_constrp   r5   rC   	func_nameZdocstrZargs_to_funcZ	call_nodeZ	lhs_entryZ
assgn_noder   r   r   generate_ufunc_initialization   s    

     r~   c                 C   sP   g }| D ]0}|  }t|}|jj|jj || q|t| || |S r   )r`   r   r'   Zutility_code_listrz   ZscoperG   r~   )rf   r   stats	converterr   Z
ufunc_noder   r   r   re   -  s    re   N)r>   r   r   r   r   ZErrorsr   r   r
   r   ZCoder	   ZVisitorr   r   r   r   r   r$   rh   r~   re   r   r   r   r   <module>   s    K