U
    ,d):                     @   sf  d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
mZ ddlmZ G dd deZG dd	 d	eZed
ZejZejZejZejZejZejZejZdd Zdd Zdd Zdd Zdd Zdd ZG dd deZ G dd deZ!d2ddZ"dd Z#dd  Z$d!d" Z%e&d#d$Z'ej(d%d& Z)d'd( Z*d)d* Z+d+d, Z,ej(d3d.d/Z-d0d1 Z.dS )4z<
Utilities to simplify the boilerplate for native lowering.
    N)Enum)typingtypesutilscgutils)BaseRegistryLoaderc                   @   sb   e Zd ZdZd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 )Registryz?
    A registry of function and attribute implementations.
    unspecifiedc                 C   s(   || _ g | _g | _g | _g | _g | _d S N)name	functionsgetattrssetattrscasts	constants)selfr    r   7/tmp/pip-unpacked-wheel-eu7e0c37/numba/core/imputils.py__init__   s    zRegistry.__init__c                    s    fdd}|S )a1  
        Decorate an implementation of *func* for the given argument types.
        *func* may be an actual global function object, or any
        pseudo-function supported by Numba, such as "getitem".

        The decorated implementation has the signature
        (context, builder, sig, args).
        c                    s   j |  f | S r
   )r   appendimplargtysfuncr   r   r   decorate%   s    z Registry.lower.<locals>.decorater   )r   r   r   r   r   r   r   lower   s    	zRegistry.lowerc                 C   s"   ||||}| |||jf |S r
   )r   	signature)r   r   tyattrZ	impl_list	decorator	real_implr   r   r   _decorate_attr*   s    zRegistry._decorate_attrc                    s    fdd}|S )z
        Decorate an implementation of __getattr__ for type *ty* and
        the attribute *attr*.

        The decorated implementation will have the signature
        (context, builder, typ, val).
        c                    s    |  jtS r
   )r"   r   _decorate_getattrr   r   r   r   r   r   r   7   s    z(Registry.lower_getattr.<locals>.decorater   r   r   r   r   r   r$   r   lower_getattr/   s    zRegistry.lower_getattrc                 C   s   |  |dS )a:  
        Decorate the fallback implementation of __getattr__ for type *ty*.

        The decorated implementation will have the signature
        (context, builder, typ, val, attr).  The implementation is
        called for attributes which haven't been explicitly registered
        with lower_getattr().
        N)r&   r   r   r   r   r   lower_getattr_generic<   s    	zRegistry.lower_getattr_genericc                    s    fdd}|S )z
        Decorate an implementation of __setattr__ for type *ty* and
        the attribute *attr*.

        The decorated implementation will have the signature
        (context, builder, sig, args).
        c                    s    |  jtS r
   )r"   r   _decorate_setattrr   r$   r   r   r   O   s    z(Registry.lower_setattr.<locals>.decorater   r%   r   r$   r   lower_setattrG   s    zRegistry.lower_setattrc                 C   s   |  |dS )a;  
        Decorate the fallback implementation of __setattr__ for type *ty*.

        The decorated implementation will have the signature
        (context, builder, sig, args, attr).  The implementation is
        called for attributes which haven't been explicitly registered
        with lower_setattr().
        N)r*   r'   r   r   r   lower_setattr_genericT   s    	zRegistry.lower_setattr_genericc                    s    fdd}|S )z
        Decorate the implementation of implicit conversion between
        *fromty* and *toty*.

        The decorated implementation will have the signature
        (context, builder, fromty, toty, val).
        c                    s   j |  ff | S r
   )r   r   r   fromtyr   totyr   r   r   g   s    z%Registry.lower_cast.<locals>.decorater   )r   r-   r.   r   r   r,   r   
lower_cast_   s    zRegistry.lower_castc                    s    fdd}|S )z
        Decorate the implementation for creating a constant of type *ty*.

        The decorated implementation will have the signature
        (context, builder, ty, pyval).
        c                    s    j | ff | S r
   )r   r   r   r'   r   r   r   s   s    z)Registry.lower_constant.<locals>.decorater   )r   r   r   r   r'   r   lower_constantl   s    zRegistry.lower_constantc                 C   s   d| j  dS )NzLowering Registry<>)r   r   r   r   r   __repr__x   s    zRegistry.__repr__N)r	   )__name__
__module____qualname____doc__r   r   r"   r&   r(   r*   r+   r/   r0   r3   r   r   r   r   r      s   
r   c                   @   s   e Zd ZdZdZdS )RegistryLoaderz6
    An incremental loader for a target registry.
    )r   r   r   r   r   N)r4   r5   r6   r7   Zregistry_itemsr   r   r   r   r8   |   s   r8   builtin_registryc                    s8   |  |d k	r fdd}n fdd}|f|_ ||_|S )Nc                    s    | |||S r
   r   contextbuildertypvaluer   r!   r   r   res   s    z_decorate_getattr.<locals>.resc                    s    | ||||S r
   r   r:   r?   r   r   r@      s    )r   r   r   r   r   r@   r   r?   r   r#      s    r#   c                    s<   |  |d k	r fdd}n fdd}|t jf|_||_|S )Nc                    s    | |||S r
   r   r;   r<   sigargsr   r?   r   r   r@      s    z_decorate_setattr.<locals>.resc                    s    | ||||S r
   r   rB   r?   r   r   r@      s    )r   Anyr   r   rA   r   r?   r   r)      s    r)   c           	   	   C   st   t |jtjrp|jj}| ||}t||}||	|j
  | |||}||| W 5 Q R X ||}|S r
   )
isinstancereturn_typer   OptionaltypeZmake_optional_noner   Zalloca_once_valueif_thennot_Zis_noneZmake_optional_valuestoreload)	r;   r<   rC   statusretvalZ
value_typeZoptional_noneZ	retvalptrZoptional_valuer   r   r   fix_returning_optional   s      
rP   c                    s"    fdd} j |_t||_|S )zC
    A wrapper inserting code calling Numba-compiled *fndesc*.
    c              	      s   |  |j }| j|| j j|\}}t||j | j	|| W 5 Q R X |j
 jksbtt| ||||}|j| |j
krd}t||j|j
t| | j|S )Nz$function returned {0} but expect {1})declare_functionmodule	call_convcall_functionrestypeargtypesr   Zif_unlikelyZis_errorZreturn_status_propagaterG   AssertionErrorrP   rI   Zget_value_type	TypeErrorformatimpl_ret_new_ref)r;   r<   rC   rD   r   rN   rO   msgfndescr   r   imp   s         zuser_function.<locals>.imp)rV   r   tuplelibs)r]   r`   r^   r   r\   r   user_function   s    
ra   c                    s    fdd}t ||_|S )zD
    A wrapper inserting code calling Numba-compiled *gendesc*.
    c                    s2   |  |j }| j|| j j|\}}||fS r
   )rQ   rR   rS   rT   rU   rV   )r;   r<   rC   rD   r   rN   rO   gendescr   r   r^      s        zuser_generator.<locals>.imp)r_   r`   )rc   r`   r^   r   rb   r   user_generator   s    
rd   c                    s    fdd}|S )zl
    Decorator a given class as implementing *iterator_type*
    (by providing an `iternext()` method).
    c                    s0    j ttj fdd}td|  S )Nc                    s    |\} | ||}|| ||S r
   r   )r;   r<   rC   rD   resultr>   Ziterobjclsiternextr   r   iternext_wrapper   s    z8iterator_impl.<locals>.wrapper.<locals>.iternext_wrapperrh   )rh   iternext_implRefTypeBORROWEDlower_builtin)rg   ri   iterator_typerf   r   wrapper   s
    ziterator_impl.<locals>.wrapperr   )iterable_typero   rp   r   rn   r   iterator_impl   s    rr   c                   @   sF   e Zd ZdZdZdd Zdd Zddd	Zd
d Zdd Z	dd Z
dS )_IternextResultzb
    A result wrapper for iteration, passed by iternext_impl() into the
    wrapped function.
    _context_builder_pairobjc                 C   s   || _ || _|| _d S r
   rt   )r   r;   r<   pairobjr   r   r   r     s    z_IternextResult.__init__c                 C   s   | j tjd| j_dS )z1
        Mark the iterator as exhausted.
        FNru   Zget_constantr   booleanrw   secondr2   r   r   r   set_exhausted	  s    z_IternextResult.set_exhaustedTc                 C   s$   |dkr| j tj|}|| j_dS )z
        Mark the iterator as valid according to *is_valid* (which must
        be either a Python boolean or a LLVM inst).
        )FTNry   )r   is_validr   r   r   	set_valid  s    z_IternextResult.set_validc                 C   s   || j _dS )zP
        Mark the iterator as yielding the given *value* (a LLVM inst).
        Nrw   first)r   r>   r   r   r   yield_  s    z_IternextResult.yield_c                 C   s   | j | jtj| jjS )z>
        Return whether the iterator is marked valid.
        )ru   Zget_argument_valuerv   r   rz   rw   r{   r2   r   r   r   r}     s    
z_IternextResult.is_validc                 C   s   | j jS )z>
        Return the iterator's yielded value, if any.
        r   r2   r   r   r   yielded_value&  s    z_IternextResult.yielded_valueN)T)r4   r5   r6   r7   	__slots__r   r|   r~   r   r}   r   r   r   r   r   rs      s   
	rs   c                   @   s   e Zd ZdZdZdZdZdS )rk   z&
    Enumerate the reference type
             N)r4   r5   r6   r7   NEWrl   	UNTRACKEDr   r   r   r   rk   ,  s   rk   c                    s*    dd t D krtd fdd}|S )a  
    Wrap the given iternext() implementation so that it gets passed
    an _IternextResult() object easing the returning of the iternext()
    result pair.

    ref_type: a numba.targets.imputils.RefType value, the reference type used is
    that specified through the RefType enum.

    The wrapped function will be called with the following signature:
        (context, builder, sig, args, iternext_result)
    c                 S   s   g | ]}|qS r   r   ).0xr   r   r   
<listcomp>I  s     z!iternext_impl.<locals>.<listcomp>z3ref_type must be an enum member of imputils.RefTypec                    s    fdd}|S )Nc              	      st   |j }| ||} | |||t| || tjkr:t}n(tjkrJt}ntjkrZt	}nt
d|| ||| S )NzUnknown ref_type encountered)rG   make_helperrs   rk   r   rZ   rl   impl_ret_borrowedr   impl_ret_untracked
ValueErrorZ	_getvalue)r;   r<   rC   rD   	pair_typerx   Zimpl_ret)r   ref_typer   r   rp   M  s     




 z-iternext_impl.<locals>.outer.<locals>.wrapperr   )r   rp   r   )r   r   outerL  s    ziternext_impl.<locals>.outer)rk   r   )r   r   r   r   r   rj   =  s    rj   c                 C   s&   t |j|}| d|}|||fS )z
    Call the `getiter()` implementation for the given *iterable_type*
    of value *val*, and return the corresponding LLVM inst.
    Zgetiter)r   r   ro   get_function)r;   r<   rq   valZgetiter_sigZgetiter_implr   r   r   call_getiter`  s    r   c           	      C   sR   |j }t|tj}t||}| d|}|||f}| |||}t| ||S )z
    Call the `iternext()` implementation for the given *iterator_type*
    of value *val*, and return a convenience _IternextResult() object
    reflecting the results.
    rh   )	Z
yield_typer   ZPairrz   r   r   r   r   rs   )	r;   r<   ro   r   Zitemtyr   Ziternext_sigrj   rx   r   r   r   call_iternextj  s    r   c                 C   sB   z|  tttj|}W n tk
r0   Y dS X |||fS dS )z^
    Call len() on the given value.  Return None if len() isn't defined on
    this type.
    N)r   lenr   r   r   ZintpNotImplementedError)r;   r<   r   r   Zlen_implr   r   r   call_leny  s
    r   _ForIterLoop)r>   do_breakc           	   
   #   s   |j }t| ||}d}d  fdd}| |\ t| ||}j| dd   W 5 Q R X t	|
 |V  | W 5 Q R X   | jr| j|| dS )z
    Simulate a for loop on the given iterable.  Yields a namedtuple with
    the given members:
    - `value` is the value being yielded
    - `do_break` is a callable to early out of the loop
    zfor_iter.bodyzfor_iter.endc                      s      d S r
   )branchr   Zbb_endr<   r   r   r     s    zfor_iter.<locals>.do_breakF)ZlikelyN)ro   r   Zappend_basic_blockr   Z
goto_blockr   rJ   rK   r}   r   r   Zposition_at_end
enable_nrtnrtZdecref)	r;   r<   rq   r   ro   ZitervalZbb_bodyr   r@   r   r   r   for_iter  s    



r   c                 C   s   |S )z5
    The implementation returns a new reference.
    r   ctxr<   Zrettyretr   r   r   rZ     s    rZ   c                 C   s   | j r| j||| |S )z
    The implementation returns a borrowed reference.
    This function automatically incref so that the implementation is
    returning a new reference.
    )r   r   Zincrefr   r   r   r   r     s    r   c                 C   s   |S )z.
    The return type is not a NRT object.
    r   r   r   r   r   r     s    r   numpyc                 c   s8   ddl m} | j}||| | _z
dV  W 5 || _X dS )z7
    Temporarily change the context's error model.
    r   )callconvN)
numba.corer   Zerror_modelZcreate_error_model)r;   Z
model_namer   Zold_error_modelr   r   r   force_error_model  s    
r   c                  O   s   t ddS )zPA stub for use internally by Numba when a call is emitted
    on a TypeRef.
    z%This function should not be executed.N)r   )rD   kwargsr   r   r   numba_typeref_ctor  s    r   )N)r   )/r7   collections
contextlibinspect	functoolsenumr   r   r   r   r   r   Znumba.core.typing.templatesr   objectr   r8   r9   r   rm   r&   r(   r*   r+   r/   r0   r#   r)   rP   ra   rd   rr   rs   rk   rj   r   r   r   
namedtupler   contextmanagerr   rZ   r   r   r   r   r   r   r   r   <module>   sP   l	/
#

