o
    8ήcU'                     @   sp  d Z ddlmZ ddlmZmZ ddlmZmZmZ ddlm	Z	m
Z
 ddlmZ ddlm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 eeeedd ZeeG dd dejZeeeeG dd dejZe	ejdd Ze	edd Z dd Z!	d$ddZ"eedd Z#eedd Z$e
eedd  Z%e
ejed!d" Z&d#S )%zeProvides Numba type, FunctionType, that makes functions as
instances of a first-class function type.
    )typeof_impl)modelsregister_model)unboxNativeValuebox)lower_constant
lower_cast)CFunc)cgutils)ir)types)FunctionTypeUndefinedFunctionTypeFunctionPrototypeWrapperAddressProtocol)
Dispatcherc                 C   sF   t | tr| j}t|S t | tr|  }t|S tdt| j )Nzfunction type from )	
isinstancer
   _sigr   	signatureNotImplementedErrortype__name__r   )valcsig r   G/tmp/pip-target-vg8gfxp4/lib/python/numba/experimental/function_type.pytypeof_function_type   s   

r   c                           e Zd ZdZ fddZ  ZS )FunctionProtoModelzIFunctionProtoModel describes the signatures of first-class functions
    c                    s|   t |tr	|j}nt |tr|}ntt| |j } fdd|j	D }t
t
||}tt|  || d S )Nc                    s   g | ]	}  | qS r   )lookupget_value_type).0tdmmr   r   
<listcomp>+   s    z/FunctionProtoModel.__init__.<locals>.<listcomp>)r   r   ftyper   r   r   r!   rtyper"   atypesr   PointerTypesuperr    __init__)selfr&   fe_typer(   rettyargsbe_type	__class__r%   r   r-   #   s   

zFunctionProtoModel.__init__r   
__module____qualname____doc__r-   __classcell__r   r   r3   r   r       s    r    c                       r   )FunctionModelz>FunctionModel holds addresses of function implementations
    c                    s,   dt jfdt jfg}tt| ||| d S )Naddrpyaddr)r   voidptrr,   r:   r-   )r.   r&   r/   membersr3   r   r   r-   5   s   zFunctionModel.__init__r5   r   r   r3   r   r:   0   s    r:   c                 C   s   | j |t|t|jdS )Ninfo)add_dynamic_addridr   r   )contextbuildertyppyvalr   r   r   lower_constant_dispatcher@   s   rG   c                 C   s"  |  }t|tr1|j}t|| |}| j||t|d|_| j|t	|t
|jd|_| S t|trPt|| |}| j|t	|t
|jd|_| S t|tr| }|| sbJ t|| |}| j||t|d|_| j|t	|t
|jd|_| S td| |||)Nr?   z3lower_constant_struct_function_type({}, {}, {}, {}))get_preciser   r
   _wrapper_addressr   create_struct_proxyrA   strr;   rB   r   r   r<   	_getvaluer   r   __wrapper_address__check_signaturer   r   format)rC   rD   rE   rF   r;   sfuncr   r   r   lower_constant_function_typeF   s@   


rQ   c                 C   s   |  sd}n;t| dr|  }n1t| tr!|| jksJ | j}n!t| tr6| |}|j	j
}|j|}ntdt|  d|t|tsQtdt| d|dkri|dkritdt|  d	| d
| d|S )a  Return the address of a compiled cfunc wrapper function of `func`.

    Warning: The compiled function must be compatible with the given
    signature `sig`. If it is not, then result of calling the compiled
    function is undefined. The compatibility is ensured when passing
    in a first-class function to a Numba njit compiled function either
    as an argument or via namespace scoping.

    Parameters
    ----------
    func : object
      A Numba cfunc or jit decoreated function or an object that
      implements the wrapper address protocol (see note below).
    sig : Signature
      The expected function signature.

    Returns
    -------
    addr : int
      An address in memory (pointer value) of the compiled function
      corresponding to the specified signature.

    Note: wrapper address protocol
    ------------------------------

    An object implements the wrapper address protocol iff the object
    provides a callable attribute named __wrapper_address__ that takes
    a Signature instance as the argument, and returns an integer
    representing the address or pointer value of a compiled function
    for the given signature.

    rM   zget wrapper address of z instance with z%wrapper address must be integer, got z	 instancer   zwrapper address of z- instance must be a positive integer but got z [sig=])
is_precisehasattrrM   r   r
   r   addressr   get_compile_resultfndescllvm_cfunc_wrapper_namelibraryget_pointer_to_functionr   r   int	TypeError
ValueError)funcr   r;   creswrapper_namer   r   r   _get_wrapper_addressi   s2   !






rb   
return_excc                 C   s   |  |}| |jt}||}||d}|| |||}	|	|||	f}
|dkro|j
t||
dd, |dkrG| j| n|dkrS||  nt|W d   |
S W d   |
S 1 sjw   Y  |
S )znLow-level call to _get_wrapper_address(func, sig).

    When calling this function, GIL must be acquired.
    rb   ignoreFlikelyrc   return_nullN)get_python_apiinsert_const_stringmoduler   import_module_noblockobject_getattr_stringdecrefunserializeserialize_objectcall_function_objargsif_thenr   is_null	call_convrc   retget_null_objectr   )rC   rD   r_   r   failure_modepyapimodname	numba_mod
numba_funcsig_objr;   r   r   r   lower_get_wrapper_address   s0   




r|   c                 C   sx   |   } t| |j|j}t|j|j|| jdd}|j||_	|j
| |jtj}|j|||_t| S )Nrg   rv   )rH   r   rJ   rC   rD   r|   r   rw   long_as_voidptrr;   rm   r"   r   r=   ptrtointr<   r   rL   )rE   objr   rP   r;   lltyr   r   r   unbox_function_type   s   r   c                 C   s   |   } t| |j|j|d}t|j|jj}|j|j	|jj}|jj
t|j|dd d|  d}|jd| |j|j  W d    n1 sQw   Y  |j|| |j|}|j| |S )N)valueFre   zfirst-class function z parent object not setPyExc_MemoryError)rH   r   rJ   rC   rD   alloca_oncerw   pyobjinttoptrr<   rq   rr   err_set_stringrt   ru   storeloadincref)rE   r   r   rP   
pyaddr_ptrraw_ptrcstrcfuncr   r   r   box_function_type   s   r   c                 C   s   |S )Nr   )rC   rD   fromtytotyr   r   r   r   )lower_cast_function_type_to_function_type   s   r   c           
      C   s   |  }| |}t|| |}| }t| |||jdd}|||_|	| |
| | tj}	|||	|_| S )Nrc   r}   )rH   rh   r   rJ   
gil_ensurer|   r   r~   r;   rm   gil_releaser"   r   r=   r   r<   rL   )
rC   rD   r   r   r   rw   rP   	gil_stater;   r   r   r   r   &lower_cast_dispatcher_to_function_type   s   



r   N)rc   )'r8   numba.extendingr   r   r   r   r   r   numba.core.imputilsr   r	   numba.core.ccallbackr
   
numba.corer   llvmliter   r   numba.core.typesr   r   r   r   numba.core.dispatcherr   registerr   PrimitiveModelr    StructModelr:   rG   rQ   rb   r|   r   r   r   r   r   r   r   r   <module>   sD    

"A
&



