o
    i+/                     @   s   d Z ddlZddlm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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 eej!ej"ej"dd Z#dS )zUtilities for defining a mutable struct.

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

    N)create_struct_proxy)njit)typesimputilscgutils)default_managermodels)	infer_getattrlower_getattr_genericlower_setattr_genericlower_builtin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   Z/home/ubuntu/transcripts/venv/lib/python3.10/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   r   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_ref6   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   	structvalr   data_ptrvaltypemodel
alloc_typer   r   r   get_data_pointerA   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_structR   s   
z_Utils.get_data_structN)	__name__
__module____qualname____doc__r   r   r"   r/   r2   r   r   r   r   r      s    r   c                    s<   t G  fdddt}t dd }t dd }dS )zDefine 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 v r|j | }|S d S N)
field_dict)r   typattrattrtyr   r   r   generic_resolvel   s   

z:define_attributes.<locals>.StructAttribute.generic_resolveN)r3   r4   r5   keyr<   r   struct_typeclassr   r   StructAttributeh   s    r@   c           	      S   s:   t | ||}||}t||}|j| }t| |||S r7   )r   r2   getattrr8   r   impl_ret_borrowed)	r   r   r9   r!   r:   utilsr1   ret	fieldtyper   r   r   struct_getattr_implq   s
   


z.define_attributes.<locals>.struct_getattr_implc                 S   s|   |j \}}|\}}t| ||}	|	|}
|j| }| ||||}t|
|}| j||| | j||| t	|
|| d S r7   )
argsr   r2   r8   castrA   r#   increfdecrefsetattr)r   r   sigrG   r:   	inst_typeval_typeinstancer!   rC   r1   
field_typecasted	old_valuer   r   r   struct_setattr_imply   s   



z.define_attributes.<locals>.struct_setattr_implN)r	   r   r
   r   )r?   r@   rF   rS   r   r>   r   define_attributesa   s   
rT   c                    sH   | t ju 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_objargsrJ   )r9   r!   crC   
struct_refr   mip_typeboxed_meminfoctor_pyfuncty_pyobjres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)rX   object_getattr_stringr   rV   rW   r   r    r   r   r   r   	_getvaluerJ   r   )	r9   objr\   mi_objr^   r   rC   r]   outr   r   r   unbox_struct_ref   s   
z'define_boxing.<locals>.unbox_struct_refN)r   	StructRef
ValueError_numba_box_r   r   )r   	obj_classre   rl   r   rc   r   define_boxing   s   
rq   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 )zDefine 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dictrs   execr   )py_classr?   fieldsparamsindentinit_fields_bufkinit_fieldssourceglbsrt   r   r   r   define_constructor   s*   


r   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)r   rq   )rz   r?   r{   r   r   r   define_proxy   s   r   c                 C   s4   | t ju 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)

    rU   )r   rm   rn   r   registerr   StructRefModelrT   )r   r   r   r   r      s
   
r   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 r7   )r&   r%   r'   get_abi_sizeofr#   meminfo_alloc_dtorget_constantr   uintpmoduler$   r(   r)   storer   get_null_valuemake_helperr   rh   )
r   r   	signaturerG   r-   r.   
alloc_sizer   data_pointerinst_structr   rM   r   r   codegen0  s   
znew.<locals>.codegen) numba.experimental.jitclass.baser   instance_type)	typingctxr   r   rL   r   r   r   rs     s
   rs   c                       s<   e Zd ZdZdZe fddZdd Zedd Z	  Z
S )	StructRefProxyzA PyObject proxy to the Numba allocated structref data structure.

    Notes
    -----

    * Subclasses should not define ``__init__``.
    * Subclasses can override ``__new__``.
    )_typerf   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   rf   )clstyr   rO   	__class__r   r   ro   U  s   zStructRefProxy._numba_box_c                    s@   z j }W || S  ty   t fdd}| _ Y || S w )zConstruct 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 r7   r   )rG   r   r   r   rt   v  s   z$StructRefProxy.__new__.<locals>.ctor)_StructRefProxy__numba_ctorAttributeErrorr   )r   rG   rt   r   r   r   r   k  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_}  s   zStructRefProxy._numba_type_)r3   r4   r5   r6   	__slots__classmethodro   r   propertyr   __classcell__r   r   r   r   r   J  s    r   c           
      C   sH   |\}}|j \}}t|| ||dj}t|| ||dj}	|d||	S )z
    Define the 'is' operator for structrefs by comparing the memory addresses.
    This is the identity check for structref objects.
    r   z==)rG   r   r   icmp_unsigned)
r   r   rL   rG   abatybtya_ptrb_ptrr   r   r   structref_is  s
   
r   )$r6   operatornumba.core.cgutilsr   numbar   
numba.corer   r   r   numba.core.datamodelr   r   numba.core.extendingr	   r
   r   r   r   r   r   r   r   numba.core.typing.templatesr   r   rT   rq   r   r   r   rs   r   is_rm   r   r   r   r   r   <module>   s&    ,G+9 #
*<