o
    Td,                     @   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 )zUtilities 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   o/home/ncw/WWW/www-new/content/articles/pi-bbp/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   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   	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-   r0   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_resolvei   s   

z:define_attributes.<locals>.StructAttribute.generic_resolveN)r1   r2   r3   keyr:   r   struct_typeclassr   r   StructAttributee   s    r>   c           	      S   s:   t | ||}||}t||}|j| }t| |||S r5   )r   r0   getattrr6   r   impl_ret_borrowed)	r   r   r7   r   r8   utilsr/   ret	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 r5   )
argsr   r0   r6   castr?   r!   increfdecrefsetattr)r   r   sigrE   r8   	inst_typeval_typeinstancer   rA   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>   rD   rQ   r   r<   r   define_attributes^   s   
rR   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_objargsrH   )r7   r   crA   
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)rV   object_getattr_stringr   rT   rU   r   r   r   r   r   r   	_getvaluerH   r   )	r7   objrZ   mi_objr\   r   rA   r[   outr   r   r   unbox_struct_ref   s   
z'define_boxing.<locals>.unbox_struct_refN)r   	StructRef
ValueError_numba_box_r   r   )r   	obj_classrc   rj   r   ra   r   define_boxing   s   
ro   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dictrq   execr   )py_classr=   fieldsparamsindentinit_fields_bufkinit_fieldssourceglbsrr   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   ro   )rx   r=   ry   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)

    rS   )r   rk   rl   r   registerr   StructRefModelrR   )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 r5   )r$   r#   r%   get_abi_sizeofr!   meminfo_alloc_dtorget_constantr   uintpmoduler"   r&   r'   storer   get_null_valuemake_helperr   rf   )
r   r   	signaturerE   r+   r,   
alloc_sizer   data_pointerinst_structr   rK   r   r   codegen-  s   
znew.<locals>.codegen) numba.experimental.jitclass.baser   instance_type)	typingctxr   r   rJ   r   r   r   rq     s
   rq   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__``.
    )_typerd   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   rd   )clstyr   rM   	__class__r   r   rm   R  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 r5   r   )rE   r   r   r   rr   s  s   z$StructRefProxy.__new__.<locals>.ctor)_StructRefProxy__numba_ctorAttributeErrorr   )r   rE   rr   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_)r1   r2   r3   r4   	__slots__classmethodrm   r   propertyr   __classcell__r   r   r   r   r   G  s    r   N)r4   numbar   
numba.corer   r   r   numba.core.datamodelr   r   numba.core.extendingr   r	   r
   r   r   r   r   r   numba.core.typing.templatesr   r   rR   ro   r   r   r   rq   r   r   r   r   r   <module>   s    (
G+9 #
*