o
    Y۷i"                     @  s   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	m
Z
mZmZmZ ddlmZ dd	lmZmZmZmZ d
dlmZ d
dlmZmZ edZeefdd	d!d"ddZd#dd ZdS )$a  Helpers for mirroring registered C++ FFI types with Python dataclass syntax.

The :func:`c_class` decorator is the primary entry point.  It inspects the
reflection metadata that the C++ runtime exposes via the TVM FFI registry and
turns it into Python ``dataclass``-style descriptors: annotated attributes become
properties that forward to the underlying C++ object, while an ``__init__``
method is synthesized to call the FFI constructor when requested.
    )annotationsN)Callable)InitVar)ClassVarTypeTypeVar
get_originget_type_hints)dataclass_transform   )	TypeFieldTypeInfo+_lookup_or_register_type_info_from_type_key_set_type_cls   )_utils)KW_ONLYfield_InputClsTypeF)field_specifierskw_only_defaultTtype_keystrinitboolkw_onlyreturn4Callable[[Type[_InputClsType]], Type[_InputClsType]]c                   s   d fdd}|S )a
  (Experimental) Create a dataclass-like proxy for a C++ class registered with TVM FFI.

    The decorator reads the reflection metadata that was registered on the C++
    side using ``tvm::ffi::reflection::ObjectDef`` and binds it to the annotated
    attributes in the decorated Python class. Each field defined in C++ becomes
    a property on the Python class, and optional default values can be provided
    with :func:`tvm_ffi.dataclasses.field` in the same way as Python's native
    ``dataclasses.field``.

    The intent is to offer a familiar dataclass authoring experience while still
    exposing the underlying C++ object.  The ``type_key`` of the C++ class must
    match the string passed to :func:`c_class`, and inheritance relationships are
    preserved-subclasses registered in C++ can subclass the Python proxy defined
    for their parent.

    Parameters
    ----------
    type_key
        The reflection key that identifies the C++ type in the FFI registry,
        e.g. ``"testing.MyClass"`` as registered in
        ``src/ffi/extra/testing.cc``.

    init
        If ``True`` and the Python class does not define ``__init__``, an
        initializer is auto-generated that mirrors the reflected constructor
        signature.  The generated initializer calls the C++ ``__init__``
        function registered with ``ObjectDef`` and invokes ``__post_init__`` if
        it exists on the Python class.

    kw_only
        If ``True``, all fields become keyword-only parameters in the generated
        ``__init__``. Individual fields can override this by setting
        ``kw_only=False`` in :func:`field`. Additionally, a ``KW_ONLY`` sentinel
        annotation can be used to mark all subsequent fields as keyword-only.

    Returns
    -------
    Callable[[type], type]
        A class decorator that materializes the final proxy class.

    Examples
    --------
    Register the C++ type and its fields with TVM FFI:

    .. code-block:: c++

        TVM_FFI_STATIC_INIT_BLOCK() {
          namespace refl = tvm::ffi::reflection;
          refl::ObjectDef<MyClass>()
              .def_static("__init__", [](int64_t v_i64, int32_t v_i32,
                                         double v_f64, float v_f32) -> Any {
                   return ObjectRef(ffi::make_object<MyClass>(
                       v_i64, v_i32, v_f64, v_f32));
               })
              .def_rw("v_i64", &MyClass::v_i64)
              .def_rw("v_i32", &MyClass::v_i32)
              .def_rw("v_f64", &MyClass::v_f64)
              .def_rw("v_f32", &MyClass::v_f32);
        }

    Mirror the same structure in Python using dataclass-style annotations:

    .. code-block:: python

        from tvm_ffi.dataclasses import c_class, field


        @c_class("example.MyClass")
        class MyClass:
            v_i64: int
            v_i32: int
            v_f64: float = field(default=0.0)
            v_f32: float = field(default_factory=lambda: 1.0)


        obj = MyClass(v_i64=4, v_i32=8)
        obj.v_f64 = 3.14  # transparently forwards to the underlying C++ object

    super_type_clsType[_InputClsType]r   c           
        s    od| j v t}|jd usJ t| |\|_}t|jD ]\}}|d uo*||k}tj| ||d q r=t| |nd }tj	|| d|id}t
|| ddlm} tdd |jD }	|||	 |S )N__init__)class_kw_onlykw_only_from_sentinel)	type_infoclsmethodsr   )_setup_copy_methodsc                 s  s    | ]}|j d kV  qdS )__ffi_shallow_copy__Nname).0m r,   Q/home/ubuntu/vllm_env/lib/python3.10/site-packages/tvm_ffi/dataclasses/c_class.py	<genexpr>   s    z-c_class.<locals>.decorator.<locals>.<genexpr>)__dict__r   parent_type_info_inspect_c_class_fieldsfields	enumerater   fill_dataclass_fieldmethod_inittype_info_to_clsr   registryr&   anyr%   )
r   r#   kw_only_start_idxidx
type_fieldr"   fn_inittype_clsr&   has_shallow_copyr   r   r   r,   r-   	decorator~   s.   

zc_class.<locals>.decoratorN)r   r   r   r   r,   )r   r   r   r@   r,   r?   r-   c_class*   s   TrA   r=   typer#   r   "tuple[list[TypeField], int | None]c                   sP  t jdkrt| dd nt|   fddt| di  D }d }d}t| di  D ]+} |}|d u r7q+t|ttfv r@q+|t	u rR|d urOt
d|  |}q+|d	7 }q+ d
d |jD }g }| D ]$\}	}
|	drpqf||	d }|d u rt
d|  d|	 d|| qf|rddd | D }t
d|  d| d||fS )N)   	   T)include_extrasc                   s6   i | ]}t  | ttfvr | tur| | qS r,   )r   r   r   r   )r*   r)   type_hints_resolvedr,   r-   
<dictcomp>   s    
z+_inspect_c_class_fields.<locals>.<dictcomp>__annotations__r   z)KW_ONLY may only be used once per class: r   c                 S  s   i | ]}|j |qS r,   r(   r*   fr,   r,   r-   rI      s    	__tvm_ffizExtraneous field `.z#`. Defined in Python but not in C++z, c                 s  s    | ]
}d |j  d V  qdS )`Nr(   rK   r,   r,   r-   r.      s    z*_inspect_c_class_fields.<locals>.<genexpr>zMissing fields in `z`: z". Defined in C++ but not in Python)sysversion_infor	   getattrkeysgetr   r   r   r   
ValueErrorr2   items
startswithpopappendjoinvalues)r=   r#   type_hints_pyr9   field_countr)   resolved_typetype_fields_cxxtype_fields
field_name_field_ty_pyr;   extra_fieldsr,   rG   r-   r1      sL   




r1   )TF)r   r   r   r   r   r   r   r   )r=   rB   r#   r   r   rC   )__doc__
__future__r   rP   collections.abcr   dataclassesr   typingr   r   r   r   r	   typing_extensionsr
   corer   r   r   r    r   r   r   r   rA   r1   r,   r,   r,   r-   <module>   s   	u