B
     \E5                 @   sR  d Z ddlmZmZmZ ddlZddlZddlZddl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 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"d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)d.d,d-Z.dS )/z<
Utilities to simplify the boilerplate for native lowering.
    )print_functionabsolute_importdivisionN   )typingcgutilstypesutils)BaseRegistryLoaderc               @   sX   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S )Registryz?
    A registry of function and attribute implementations.
    c             C   s"   g | _ g | _g | _g | _g | _d S )N)	functionsgetattrssetattrscasts	constants)self r   5lib/python3.7/site-packages/numba/targets/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 )N)r   append)impl)argtysfuncr   r   r   decorate$   s    z Registry.lower.<locals>.decorater   )r   r   r   r   r   )r   r   r   r   lower   s    	zRegistry.lowerc             C   s"   ||||}| |||jf |S )N)r   	signature)r   r   tyattrZ	impl_listZ	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 )N)r   r   _decorate_getattr)r   )r   r   r   r   r   r   6   s    z(Registry.lower_getattr.<locals>.decorater   )r   r   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 )N)r   r   _decorate_setattr)r   )r   r   r   r   r   r   N   s    z(Registry.lower_setattr.<locals>.decorater   )r   r   r   r   r   )r   r   r   r   lower_setattrF   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   r   lower_setattr_genericS   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 )N)r   r   )r   )fromtyr   totyr   r   r   f   s    z%Registry.lower_cast.<locals>.decorater   )r   r&   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 )N)r   r   )r   )r   r   r   r   r   r   s    z)Registry.lower_constant.<locals>.decorater   )r   r   r   r   )r   r   r   lower_constantk   s    zRegistry.lower_constantN)__name__
__module____qualname____doc__r   r   r   r!   r"   r$   r%   r(   r)   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)r*   r+   r,   r-   Zregistry_itemsr   r   r   r   r.   x   s   r.   c                s8   |  |d k	r fdd}n fdd}|f|_ ||_|S )Nc                s    | |||S )Nr   )contextbuildertypvaluer   )r   r   r   res   s    z_decorate_getattr.<locals>.resc                s    | ||||S )Nr   )r/   r0   r1   r2   r   )r   r   r   r3      s    )r   r   )r   r   r   r3   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 )Nr   )r/   r0   sigargsr   )r   r   r   r3      s    z_decorate_setattr.<locals>.resc                s    | ||||S )Nr   )r/   r0   r4   r5   r   )r   r   r   r3      s    )r   ZAnyr   r   )r   r   r   r3   r   )r   r   r#      s    r#   c       	   	   C   st   t |jtjrp|jj}| ||}t||}||	|j
  | |||}||| W d Q R X ||}|S )N)
isinstancereturn_typer   ZOptionaltypeZmake_optional_noner   Zalloca_once_valueif_thennot_Zis_noneZmake_optional_valueZstoreload)	r/   r0   r4   statusretvalZ
value_typeZoptional_noneZ	retvalptrZoptional_valuer   r   r   fix_returning_optional   s    

r>   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 d 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_propagater7   AssertionErrorr>   r8   Zget_value_type	TypeErrorformatimpl_ret_new_ref)r/   r0   r4   r5   r   r<   r=   msg)fndescr   r   imp   s    zuser_function.<locals>.imp)rD   r   tuplelibs)rJ   rM   rK   r   )rJ   r   user_function   s    
rN   c                s    fdd}t ||_|S )zD
    A wrapper inserting code calling Numba-compiled *gendesc*.
    c                s2   |  |j }| j|| j j|\}}||fS )N)r?   r@   rA   rB   rC   rD   )r/   r0   r4   r5   r   r<   r=   )gendescr   r   rK      s    zuser_generator.<locals>.imp)rL   rM   )rO   rM   rK   r   )rO   r   user_generator   s    
rP   c                s    fdd}|S )zl
    Decorator a given class as implementing *iterator_type*
    (by providing an `iternext()` method).
    c                s*    j t fdd}td|  S )Nc                s    |\} | ||}|| ||S )Nr   )r/   r0   r4   r5   resultr2   Ziterobj)clsiternextr   r   iternext_wrapper   s    z8iterator_impl.<locals>.wrapper.<locals>.iternext_wrapperrS   )rS   iternext_impllower_builtin)rR   rT   )iterator_type)rR   rS   r   wrapper   s    ziterator_impl.<locals>.wrapperr   )iterable_typerW   rX   r   )rW   r   iterator_impl   s    rZ   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 )N)r\   r]   r^   )r   r/   r0   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)r\   get_constantr   booleanr^   second)r   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).
        )FTN)r\   r`   r   ra   r^   rb   )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)r^   first)r   r2   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.
        )r\   Zget_argument_valuer]   r   ra   r^   rb   )r   r   r   r   rd     s    
z_IternextResult.is_validc             C   s   | j jS )z>
        Return the iterator's yielded value, if any.
        )r^   rf   )r   r   r   r   yielded_value"  s    z_IternextResult.yielded_valueN)T)r*   r+   r,   r-   	__slots__r   rc   re   rg   rd   rh   r   r   r   r   r[      s   
	r[   c                s    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.

    The wrapped function will be called with the following signature:
        (context, builder, sig, args, iternext_result)
    c          	      s<   |j }| ||} | |||t| || t| ||| S )N)r7   make_helperr[   impl_ret_borrowedZ	_getvalue)r/   r0   r4   r5   	pair_typer_   )r   r   r   rX   3  s    
ziternext_impl.<locals>.wrapperr   )r   rX   r   )r   r   rU   )  s    
rU   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   rW   get_function)r/   r0   rY   valZgetiter_sigZgetiter_implr   r   r   call_getiter=  s    ro   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.
    rS   )	Z
yield_typer   ZPairra   r   r   rm   rj   r[   )	r/   r0   rW   rn   Zitemtyrl   Ziternext_sigrU   r_   r   r   r   call_iternextG  s    rp   c             C   s@   y|  tttj|}W n tk
r.   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)rm   lenr   r   r   ZintpNotImplementedError)r/   r0   r   rn   Zlen_implr   r   r   call_lenV  s
    rs   _ForIterLoop)r2   do_breakc       	   
   #   s   |j }t| ||}d}d  fdd}| |\ t| ||}j| dd   W dQ R X t	|
 |V  | W d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 )N)branchr   )bb_endr0   r   r   ru   u  s    zfor_iter.<locals>.do_breakF)ZlikelyN)rW   ro   Zappend_basic_blockrv   Z
goto_blockrp   r9   r:   rd   rt   rh   Zposition_at_end
enable_nrtnrtZdecref)	r/   r0   rY   rn   rW   ZitervalZbb_bodyru   r3   r   )rw   r0   r   for_iterg  s    



rz   c             C   s   |S )z5
    The implementation returns a new reference.
    r   )ctxr0   rettyretr   r   r   rH     s    rH   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.
    )rx   ry   Zincref)r{   r0   r|   r}   r   r   r   rk     s    rk   c             C   s   |S )z.
    The return type is not a NRT object.
    r   )r{   r0   r|   r}   r   r   r   impl_ret_untracked  s    r~   numpyc             c   s8   ddl m} | j}||| | _z
dV  W d|| _X dS )z7
    Temporarily change the context's error model.
       )callconvN) r   Zerror_modelZcreate_error_model)r/   Z
model_namer   Zold_error_modelr   r   r   force_error_model  s    
r   )r   )/r-   Z
__future__r   r   r   collections
contextlibinspect	functoolsr   r   r   r   r	   Ztyping.templatesr
   objectr   r.   Zbuiltin_registryr   rV   r!   r"   r$   r%   r(   r)   r    r#   r>   rN   rP   rZ   r[   rU   ro   rp   rs   
namedtuplert   contextmanagerrz   rH   rk   r~   r   r   r   r   r   <module>   sH   h	0
