U
    ¿|eã,  ã                   @   s¼   d Z ddlmZ ddlmZmZmZ ddlmZm	Z	 ddl
mZmZmZmZmZmZmZmZ ddlmZ G dd„ dƒZd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZG dd„ dƒZdS )z€Utilities for defining a mutable struct.

A mutable struct is passed by reference;
hence, structref (a reference to a struct).

é    )Únjit)ÚtypesÚimputilsÚcgutils)Údefault_managerÚmodels)Úinfer_getattrÚlower_getattr_genericÚlower_setattr_genericÚboxÚunboxÚNativeValueÚ	intrinsicÚoverload)ÚAttributeTemplatec                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú_Utilsz;Internal builder-code utils for structref definitions.
    c                 C   s   || _ || _|| _dS )zÈ
        Parameters
        ----------
        context :
            a numba target context
        builder :
            a llvmlite IRBuilder
        struct_type : numba.core.types.StructRef
        N)ÚcontextÚbuilderÚstruct_type)Úselfr   r   r   © r   úY/var/www/website-v5/atlas_env/lib/python3.8/site-packages/numba/experimental/structref.pyÚ__init__   s    
z_Utils.__init__c                 C   s,   | j }| j}| j}t |¡||ƒ}||_|S )zKEncapsulate the MemInfo from a `StructRefPayload` in a `StructRef`
        )r   r   r   r   Úcreate_struct_proxyÚmeminfo)r   Úmir   r   r   Ústr   r   r   Únew_struct_ref(   s    z_Utils.new_struct_refc                 C   s&   | j }| j}| j}t |¡|||d�S )z6Return a helper for accessing a StructRefType
        )Úvalue)r   r   r   r   r   )r   Úvalr   r   r   r   r   r   Úget_struct_ref3   s      ÿz_Utils.get_struct_refc                 C   s^   | j }| j}| j}|  |¡}|j}|j ||¡}| ¡ }|j| }	|	 	¡ }
| 
||
 ¡ ¡}|S )zDGet the data pointer to the payload from a `StructRefType`.
        )r   r   r   r    r   ÚnrtÚmeminfo_dataÚget_data_typeÚdata_model_managerÚget_value_typeÚbitcastÚ
as_pointer)r   r   r   r   r   Z	structvalr   Údata_ptrÚvaltypeÚmodelÚ
alloc_typer   r   r   Úget_data_pointer>   s    

z_Utils.get_data_pointerc                 C   s<   | j }| j}| j}|  |¡}| ¡ }t |¡|||d�}|S )zFGet a getter/setter helper for accessing a `StructRefPayload`
        )Úref)r   r   r   r,   r#   r   r   )r   r   r   r   r   r(   r)   Údatavalr   r   r   Úget_data_structO   s    
  ÿz_Utils.get_data_structN)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r    r,   r/   r   r   r   r   r      s   r   c                    s<   t G ‡ fdd„dtƒƒ}tˆ ƒdd„ ƒ}tˆ ƒdd„ ƒ}dS )zŽDefine attributes on `struct_typeclass`.

    Defines both setters and getters in jit-code.

    This is called directly in `register()`.
    c                       s   e Zd Z” Zdd„ ZdS )z*define_attributes.<locals>.StructAttributec                 S   s   ||j kr|j | }|S d S ©N)Ú
field_dict)r   ÚtypÚattrÚattrtyr   r   r   Úgeneric_resolvei   s    

z:define_attributes.<locals>.StructAttribute.generic_resolveN)r0   r1   r2   Úkeyr9   r   ©Ústruct_typeclassr   r   ÚStructAttributee   s   r=   c           	      S   s:   t | ||ƒ}| |¡}t||ƒ}|j| }t | |||¡S r4   )r   r/   Úgetattrr5   r   Úimpl_ret_borrowed)	r   r   r6   r   r7   Úutilsr.   ÚretZ	fieldtyper   r   r   Ústruct_getattr_impln   s
    


z.define_attributes.<locals>.struct_getattr_implc                 S   s|   |j \}}|\}}t| ||ƒ}	|	 |¡}
|j| }|  ||||¡}t|
|ƒ}| j |||¡ | j |||¡ t	|
||ƒ d S r4   )
Úargsr   r/   r5   Úcastr>   r!   ÚincrefÚdecrefÚsetattr)r   r   ÚsigrC   r7   Ú	inst_typeÚval_typeÚinstancer   r@   r.   Ú
field_typeÚcastedÚ	old_valuer   r   r   Ústruct_setattr_implv   s    



z.define_attributes.<locals>.struct_setattr_implN)r   r   r	   r
   )r<   r=   rB   rO   r   r;   r   Údefine_attributes^   s    
rP   c                    sH   | t jkrtdt j› �ƒ‚|j‰ t| ƒ‡ fdd„ƒ}t| ƒdd„ ƒ}dS )a˜  Define the boxing & unboxing logic for `struct_type` to `obj_class`.

    Defines both boxing and unboxing.

    - boxing turns an instance of `struct_type` into a PyObject of `obj_class`
    - unboxing turns an instance of `obj_class` into an instance of
      `struct_type` in jit-code.


    Use this directly instead of `define_proxy()` when the user does not
    want any constructor to be defined.
    úcannot register c                    sš   t |j|j| ƒ}| |¡}|j}t tj¡}| ||¡}|j	 
|j	 ˆ ¡¡}|j	 
|j	 | ¡¡}	|j	 ||	|g¡}
|j	 |¡ |j	 |	¡ |j	 |¡ |
S )z8
        Convert a raw pointer to a Python int.
        )r   r   r   r    r   r   ÚMemInfoPointerÚvoidptrr   ÚpyapiÚunserializeÚserialize_objectÚcall_function_objargsrF   )r6   r   Úcr@   Ú
struct_refr   Úmip_typeÚboxed_meminfoZctor_pyfuncZty_pyobjÚres©Zobj_ctorr   r   Úbox_struct_ref›   s    
 ÿz%define_boxing.<locals>.box_struct_refc           	      S   s^   |j  |d¡}t tj¡}| ||¡j}t|j|j	| ƒ}| 
|¡}| ¡ }|j  |¡ t|ƒS )NÚ_meminfo)rT   Úobject_getattr_stringr   rR   rS   r   r   r   r   r   r   Ú	_getvaluerF   r   )	r6   ÚobjrX   Zmi_objrZ   r   r@   rY   Úoutr   r   r   Úunbox_struct_ref²   s    
z'define_boxing.<locals>.unbox_struct_refN)r   Ú	StructRefÚ
ValueErrorÚ_numba_box_r   r   )r   Z	obj_classr^   rd   r   r]   r   Údefine_boxing‰   s    
rh   c                 C   s˜   d  |¡}d}g }|D ]}| d|› d|› �¡ qd|› �  |¡}d|› dt|ƒ› d|› d	|› d
|› d�}t|td�}	t||	ƒ |	d }
t| ƒ|
ƒ dS )zÙDefine the jit-code constructor for `struct_typeclass` using the
    Python type `py_class` and the required `fields`.

    Use this instead of `define_proxy()` if the user does not want boxing
    logic defined.
    z, z        zst.z = Ú
z

def ctor(z/):
    struct_type = struct_typeclass(list(zip(z, [z])))
    def impl(z)):
        st = new(struct_type)
        z#
        return st
    return impl
)r<   ÚnewÚctorN)ÚjoinÚappendÚlistÚdictrj   Úexecr   )Úpy_classr<   ÚfieldsÚparamsÚindentZinit_fields_bufÚkZinit_fieldsÚsourceÚglbsrk   r   r   r   Údefine_constructorÂ   s*    
ÿþÿÿû

rx   c                 C   s   t | ||ƒ t|| ƒ dS )aû  Defines a PyObject proxy for a structref.

    This makes `py_class` a valid constructor for creating a instance of
    `struct_typeclass` that contains the members as defined by `fields`.

    Parameters
    ----------
    py_class : type
        The Python class for constructing an instance of `struct_typeclass`.
    struct_typeclass : numba.core.types.Type
        The structref type class to bind to.
    fields : Sequence[str]
        A sequence of field names.

    Returns
    -------
    None
    N)rx   rh   )rq   r<   rr   r   r   r   Údefine_proxyâ   s    ry   c                 C   s4   | t jkrtdt j› �ƒ‚t | tj¡ t| ƒ | S )a˜  Register a `numba.core.types.StructRef` for use in jit-code.

    This defines the data-model for lowering an instance of `struct_type`.
    This defines attributes accessor and mutator for an instance of
    `struct_type`.

    Parameters
    ----------
    struct_type : type
        A subclass of `numba.core.types.StructRef`.

    Returns
    -------
    struct_type : type
        Returns the input argument so this can act like a decorator.

    Examples
    --------

    .. code-block::

        class MyStruct(numba.core.types.StructRef):
            ...  # the simplest subclass can be empty

        numba.experimental.structref.register(MyStruct)

    rQ   )r   re   rf   r   Úregisterr   ÚStructRefModelrP   )r   r   r   r   rz   ù   s
    
rz   c                    s0   ddl m‰  |j‰‡ ‡fdd„}ˆ|ƒ}||fS )a  new(struct_type)

    A jit-code only intrinsic. Used to allocate an **empty** mutable struct.
    The fields are zero-initialized and must be set manually after calling
    the function.

    Example:

        instance = new(MyStruct)
        instance.field = field_value
    r   )Úimp_dtorc           
         sŽ   | j ˆ ¡  }| ¡ }|  |¡}| j ||  tj|¡ˆ | |j	ˆƒ¡}| j 
||¡}| || ¡ ¡}| t |¡|¡ |  |ˆ¡}	||	_|	 ¡ S r4   )r$   r#   r%   Úget_abi_sizeofr!   Úmeminfo_alloc_dtorÚget_constantr   ÚuintpÚmoduler"   r&   r'   Ústorer   Úget_null_valueÚmake_helperr   ra   )
r   r   Ú	signaturerC   r*   r+   Ú
alloc_sizer   Údata_pointerÚinst_struct©r|   rI   r   r   Úcodegen-  s    
ýznew.<locals>.codegen)Ú numba.experimental.jitclass.baser|   Úinstance_type)Ú	typingctxr   rŠ   rH   r   r‰   r   rj     s
    rj   c                       s<   e Zd ZdZdZe‡ fdd„ƒZdd„ Zedd„ ƒZ	‡  Z
S )	ÚStructRefProxyz¸A PyObject proxy to the Numba allocated structref data structure.

    Notes
    -----

    * Subclasses should not define ``__init__``.
    * Subclasses can override ``__new__``.
    )Ú_typer_   c                    s   t ƒ  | ¡}||_||_|S )aO  Called by boxing logic, the conversion of Numba internal
        representation into a PyObject.

        Parameters
        ----------
        ty :
            a Numba type instance.
        mi :
            a wrapped MemInfoPointer.

        Returns
        -------
        instance :
             a StructRefProxy instance.
        )ÚsuperÚ__new__r�   r_   )ÚclsÚtyr   rK   ©Ú	__class__r   r   rg   R  s    zStructRefProxy._numba_box_c                    s>   z
ˆ j }W n* tk
r4   t‡ fdd„ƒ}|ˆ _ Y nX ||Ž S )zÄConstruct a new instance of the structref.

        This takes positional-arguments only due to limitation of the compiler.
        The arguments are mapped to ``cls(*args)`` in jit-code.
        c                     s   ˆ | Ž S r4   r   )rC   ©r’   r   r   rk   s  s    z$StructRefProxy.__new__.<locals>.ctor)Z_StructRefProxy__numba_ctorÚAttributeErrorr   )r’   rC   rk   r   r–   r   r‘   h  s    
zStructRefProxy.__new__c                 C   s   | j S )znReturns the Numba type instance for this structref instance.

        Subclasses should NOT override.
        )r�   )r   r   r   r   Ú_numba_type_z  s    zStructRefProxy._numba_type_)r0   r1   r2   r3   Ú	__slots__Úclassmethodrg   r‘   Úpropertyr˜   Ú__classcell__r   r   r”   r   rŽ   G  s   rŽ   N)r3   Únumbar   Ú
numba.corer   r   r   Únumba.core.datamodelr   r   Únumba.core.extendingr   r	   r
   r   r   r   r   r   Únumba.core.typing.templatesr   r   rP   rh   rx   ry   rz   rj   rŽ   r   r   r   r   Ú<module>   s   (
G+9 #
*