U
    hâËdã,  ã                   @   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   úU/home/sam/Atlas/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ÚattrZattrtyr   r   r   Úgeneric_resolvei   s    

z:define_attributes.<locals>.StructAttribute.generic_resolveN)r0   r1   r2   Úkeyr8   r   ©Ústruct_typeclassr   r   ÚStructAttributee   s   r<   c           	      S   s:   t | ||ƒ}| |¡}t||ƒ}|j| }t | |||¡S r4   )r   r/   Úgetattrr5   r   Z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!   ZincrefÚdecrefÚsetattr)r   r   ÚsigrA   r7   Ú	inst_typeZval_typeÚinstancer   r>   r.   Z
field_typeZcastedÚ	old_valuer   r   r   Ústruct_setattr_implv   s    



z.define_attributes.<locals>.struct_setattr_implN)r   r   r	   r
   )r;   r<   r@   rI   r   r:   r   Údefine_attributes^   s    
rJ   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   ÚpyapiZunserializeZserialize_objectZcall_function_objargsrC   )r6   r   Úcr>   Ú
struct_refr   Úmip_typeZ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)rN   Zobject_getattr_stringr   rL   rM   r   r   r   r   r   r   Ú	_getvaluerC   r   )	r6   ÚobjrO   Zmi_objrQ   r   r>   rP   Úoutr   r   r   Úunbox_struct_ref²   s    
z'define_boxing.<locals>.unbox_struct_refN)r   Ú	StructRefÚ
ValueErrorÚ_numba_box_r   r   )r   Z	obj_classrT   rY   r   rS   r   Údefine_boxing‰   s    
r]   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Údictr_   Úexecr   )Úpy_classr;   ÚfieldsÚparamsÚindentZinit_fields_bufÚkZinit_fieldsÚsourceZglbsr`   r   r   r   Údefine_constructorÂ   s*    
ÿþÿÿû

rl   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)rl   r]   )rf   r;   rg   r   r   r   Údefine_proxyâ   s    rm   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)

    rK   )r   rZ   r[   r   Úregisterr   ZStructRefModelrJ   )r   r   r   r   rn   ù   s
    
rn   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%   Zget_abi_sizeofr!   Zmeminfo_alloc_dtorZget_constantr   ZuintpÚmoduler"   r&   r'   Ústorer   Zget_null_valueZmake_helperr   rV   )
r   r   Ú	signaturerA   r*   r+   Z
alloc_sizer   Zdata_pointerZinst_struct©ro   rF   r   r   Úcodegen-  s    
ýznew.<locals>.codegen)Z numba.experimental.jitclass.basero   Zinstance_type)Z	typingctxr   rt   rE   r   rs   r   r_     s
    r_   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__``.
    )Ú_typerU   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__rv   rU   )ÚclsÚtyr   rG   ©Ú	__class__r   r   r\   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   )rA   ©ry   r   r   r`   s  s    z$StructRefProxy.__new__.<locals>.ctor)Z_StructRefProxy__numba_ctorÚAttributeErrorr   )ry   rA   r`   r   r}   r   rx   h  s    
zStructRefProxy.__new__c                 C   s   | j S )znReturns the Numba type instance for this structref instance.

        Subclasses should NOT override.
        )rv   )r   r   r   r   Ú_numba_type_z  s    zStructRefProxy._numba_type_)r0   r1   r2   r3   Ú	__slots__Úclassmethodr\   rx   Úpropertyr   Ú__classcell__r   r   r{   r   ru   G  s   ru   N)r3   Znumbar   Z
numba.corer   r   r   Znumba.core.datamodelr   r   Znumba.core.extendingr   r	   r
   r   r   r   r   r   Znumba.core.typing.templatesr   r   rJ   r]   rl   rm   rn   r_   ru   r   r   r   r   Ú<module>   s   (
G+9 #
*