Skip to content

Commit 2da2e0b

Browse files
committed
Unified Type Traits
1 parent fc5c790 commit 2da2e0b

29 files changed

+778
-752
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.15)
22

33
project(
44
mlc
5-
VERSION 0.0.5
6-
DESCRIPTION "PyMLC"
5+
VERSION 0.0.6
6+
DESCRIPTION "MLC-Python"
77
LANGUAGES C CXX
88
)
99

README.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ pip install -U mlc-python
1111

1212
TBA
1313

14-
**Configuration Tool.** PyMLC provides LLVM-style configuration tools for compiling and linking.
15-
16-
```
17-
>>> mlc.config --includedir --libdir
18-
/home/user/Projects/pymlc/.venv/lib/python3.12/site-packages/include;/home/user/Projects/pymlc/.venv/lib/python3.12/site-packages/3rdparty/dlpack/include
19-
/home/user/Projects/pymlc/.venv/lib/python3.12/site-packages/mlc/lib
20-
```
21-
2214
## Development
2315

2416
### Build from Source
@@ -32,7 +24,7 @@ pre-commit install
3224

3325
### Create Wheels
3426

35-
See `.github/workflows/wheels.yml` for more details. PyMLC uses `cibuildwheel` to build cross-platform wheels.
27+
See `.github/workflows/wheels.yml` for more details. This project uses `cibuildwheel` to build cross-platform wheels.
3628

3729
```bash
3830
export CIBW_BUILD_VERBOSITY=3

cpp/c_api.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,5 @@ MLC_API void MLCExtObjDelete(void *objptr) {
172172
::mlc::base::DecRef(ptr);
173173
}
174174
}
175+
delete[] reinterpret_cast<char *>(objptr);
175176
}

cpp/registry.h

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@ struct TypeInfoWrapper {
8181
template <typename T> struct PODGetterSetter {
8282
static int32_t Getter(MLCTypeField *, void *addr, MLCAny *ret) {
8383
using namespace ::mlc::base;
84-
PODTraits<T>::TypeCopyToAny(*static_cast<T *>(addr), ret);
84+
TypeTraits<T>::TypeToAny(*static_cast<T *>(addr), ret);
8585
return 0;
8686
}
8787
static int32_t Setter(MLCTypeField *, void *addr, MLCAny *src) {
8888
using namespace mlc::base;
8989
try {
90-
*static_cast<T *>(addr) = PODTraits<T>::AnyCopyToType(src);
90+
*static_cast<T *>(addr) = TypeTraits<T>::AnyToTypeUnowned(src);
9191
} catch (const TemporaryTypeError &) {
9292
std::ostringstream oss;
93-
oss << "Cannot convert from type `" << TypeIndex2TypeKey(src->type_index) << "` to `" << PODTraits<T>::Type2Str()
93+
oss << "Cannot convert from type `" << TypeIndex2TypeKey(src->type_index) << "` to `" << TypeTraits<T>::type_str
9494
<< "`";
9595
*static_cast<::mlc::Any *>(src) = MLC_MAKE_ERROR_HERE(TypeError, oss.str());
9696
return -2;
@@ -324,24 +324,29 @@ struct TypeTable {
324324
};
325325

326326
struct _POD_REG {
327-
inline static const int32_t _none = base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCNone))
328-
.MemFn("__str__", &base::PODTraits<std::nullptr_t>::__str__);
329-
inline static const int32_t _int = base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCInt))
330-
.MemFn("__str__", &base::PODTraits<int64_t>::__str__);
331-
inline static const int32_t _float = base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCFloat))
332-
.MemFn("__str__", &base::PODTraits<double>::__str__);
333-
inline static const int32_t _ptr = base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCPtr))
334-
.MemFn("__str__", &base::PODTraits<void *>::__str__);
335-
inline static const int32_t _device =
336-
base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCDevice))
327+
inline static const int32_t _none = //
328+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCNone))
329+
.MemFn("__str__", &::mlc::base::TypeTraits<std::nullptr_t>::__str__);
330+
inline static const int32_t _int = //
331+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCInt))
332+
.MemFn("__str__", &::mlc::base::TypeTraits<int64_t>::__str__);
333+
inline static const int32_t _float = //
334+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCFloat))
335+
.MemFn("__str__", &::mlc::base::TypeTraits<double>::__str__);
336+
inline static const int32_t _ptr = //
337+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCPtr))
338+
.MemFn("__str__", &::mlc::base::TypeTraits<void *>::__str__);
339+
inline static const int32_t _device = //
340+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCDevice))
337341
.StaticFn("__init__", [](AnyView device) { return device.operator DLDevice(); })
338-
.MemFn("__str__", &base::PODTraits<DLDevice>::__str__);
339-
inline static const int32_t _dtype =
340-
base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCDataType))
342+
.MemFn("__str__", &::mlc::base::TypeTraits<DLDevice>::__str__);
343+
inline static const int32_t _dtype = //
344+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCDataType))
341345
.StaticFn("__init__", [](AnyView dtype) { return dtype.operator DLDataType(); })
342-
.MemFn("__str__", &base::PODTraits<DLDataType>::__str__);
343-
inline static const int32_t _str = base::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCRawStr))
344-
.MemFn("__str__", &base::PODTraits<const char *>::__str__);
346+
.MemFn("__str__", &::mlc::base::TypeTraits<DLDataType>::__str__);
347+
inline static const int32_t _str = //
348+
::mlc::core::ReflectionHelper(static_cast<int32_t>(MLCTypeIndex::kMLCRawStr))
349+
.MemFn("__str__", &::mlc::base::TypeTraits<const char *>::__str__);
345350
};
346351

347352
inline TypeTable *TypeTable::New() {
@@ -351,12 +356,11 @@ inline TypeTable *TypeTable::New() {
351356
self->num_types = static_cast<int32_t>(MLCTypeIndex::kMLCDynObjectBegin);
352357
#define MLC_TYPE_TABLE_INIT_TYPE(UnderlyingType, Self) \
353358
{ \
354-
MLCTypeInfo *info = Self->TypeRegister(-1, ::mlc::base::PODTraits<UnderlyingType>::default_type_index, \
355-
::mlc::base::PODTraits<UnderlyingType>::Type2Str()); \
359+
MLCTypeInfo *info = Self->TypeRegister(-1, ::mlc::base::TypeTraits<UnderlyingType>::default_type_index, \
360+
::mlc::base::TypeTraits<UnderlyingType>::type_str); \
356361
info->setter = PODGetterSetter<UnderlyingType>::Setter; \
357362
info->getter = PODGetterSetter<UnderlyingType>::Getter; \
358363
}
359-
360364
MLC_TYPE_TABLE_INIT_TYPE(std::nullptr_t, self);
361365
MLC_TYPE_TABLE_INIT_TYPE(int64_t, self);
362366
MLC_TYPE_TABLE_INIT_TYPE(double, self);

include/mlc/base/all.h

Lines changed: 93 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,23 @@
99
#include "./traits_scalar.h"
1010
#include "./traits_str.h"
1111
#include <cstring>
12-
#include <vector>
13-
14-
/*********** AnyView ***********/
1512

1613
namespace mlc {
14+
15+
/*********** Section 1. Any <=> Any View ***********/
1716
MLC_INLINE AnyView::AnyView(const Any &src) : MLCAny(static_cast<const MLCAny &>(src)) {}
1817
MLC_INLINE AnyView::AnyView(Any &&src) : MLCAny(static_cast<const MLCAny &>(src)) {}
18+
MLC_INLINE Any::Any(const Any &src) : MLCAny(static_cast<const MLCAny &>(src)) { this->IncRef(); }
19+
MLC_INLINE Any::Any(Any &&src) : MLCAny(static_cast<const MLCAny &>(src)) { *static_cast<MLCAny *>(&src) = MLCAny(); }
20+
MLC_INLINE Any::Any(const AnyView &src) : MLCAny(static_cast<const MLCAny &>(src)) {
21+
this->SwitchFromRawStr();
22+
this->IncRef();
23+
}
24+
MLC_INLINE Any::Any(AnyView &&src) : MLCAny(static_cast<const MLCAny &>(src)) {
25+
*static_cast<MLCAny *>(&src) = MLCAny();
26+
this->SwitchFromRawStr();
27+
this->IncRef();
28+
}
1929
MLC_INLINE AnyView &AnyView::operator=(const Any &src) {
2030
*static_cast<MLCAny *>(this) = static_cast<const MLCAny &>(src);
2131
return *this;
@@ -24,149 +34,109 @@ MLC_INLINE AnyView &AnyView::operator=(Any &&src) {
2434
*static_cast<MLCAny *>(this) = static_cast<const MLCAny &>(src);
2535
return *this;
2636
}
27-
MLC_INLINE AnyView::AnyView(::mlc::base::tag::ObjPtr, const MLCObjPtr &src) : MLCAny() {
28-
if (src.ptr != nullptr) {
29-
this->type_index = src.ptr->type_index;
30-
this->v_obj = src.ptr;
31-
}
32-
}
33-
MLC_INLINE AnyView::AnyView(::mlc::base::tag::ObjPtr, MLCObjPtr &&src) : MLCAny() {
34-
if (src.ptr != nullptr) {
35-
this->type_index = src.ptr->type_index;
36-
this->v_obj = src.ptr;
37-
}
37+
MLC_INLINE Any &Any::operator=(const Any &src) {
38+
Any(src).Swap(*this);
39+
return *this;
3840
}
39-
template <typename T> MLC_INLINE AnyView::AnyView(::mlc::base::tag::POD, const T &src) : MLCAny() {
40-
::mlc::base::PODTraits<::mlc::base::RemoveCR<T>>::TypeCopyToAny(src, this);
41+
MLC_INLINE Any &Any::operator=(Any &&src) {
42+
Any(std::move(src)).Swap(*this);
43+
return *this;
4144
}
42-
template <typename T> MLC_INLINE AnyView::AnyView(::mlc::base::tag::POD, T &&src) : MLCAny() {
43-
::mlc::base::PODTraits<::mlc::base::RemoveCR<T>>::TypeCopyToAny(src, this);
45+
MLC_INLINE Any &Any::operator=(const AnyView &src) {
46+
Any(src).Swap(*this);
47+
return *this;
4448
}
45-
template <typename T> MLC_INLINE AnyView::AnyView(::mlc::base::tag::RawObjPtr, T *src) : MLCAny() {
46-
::mlc::base::PtrToAnyView<T>(src, this);
49+
MLC_INLINE Any &Any::operator=(AnyView &&src) {
50+
Any(std::move(src)).Swap(*this);
51+
return *this;
4752
}
48-
template <typename T> MLC_INLINE T AnyView::Cast(::mlc::base::tag::ObjPtr) const {
49-
if constexpr (::mlc::base::IsObjRef<T>) {
50-
if (this->type_index == static_cast<int32_t>(MLCTypeIndex::kMLCNone)) {
51-
using RefT = Ref<typename T::TObj>;
52-
MLC_THROW(TypeError) << "Cannot convert from type `None` to non-nullable `" << ::mlc::base::Type2Str<RefT>::Run()
53-
<< "`";
54-
}
55-
}
56-
using TObj = typename T::TObj;
57-
return T([this]() -> TObj * {
58-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<TObj>::AnyToOwnedPtr(this), this->type_index,
59-
::mlc::base::Type2Str<TObj *>::Run());
60-
}());
61-
}
62-
template <typename T> MLC_INLINE T AnyView::Cast() const {
63-
if constexpr (std::is_same_v<T, Any> || std::is_same_v<T, AnyView>) {
64-
return *this;
53+
54+
/*********** Section 2. Conversion between Any/AnyView <=> POD ***********/
55+
56+
template <typename T> MLC_INLINE AnyView::AnyView(const T &src) : MLCAny() {
57+
using namespace ::mlc::base;
58+
if constexpr (HasTypeTraits<T>) {
59+
TypeTraits<T>::TypeToAny(src, this);
6560
} else {
66-
return this->operator T();
61+
(src.operator AnyView()).Swap(*this);
6762
}
6863
}
69-
template <typename T> MLC_INLINE_NO_MSVC T AnyView::Cast(::mlc::base::tag::POD) const {
70-
MLC_TRY_CONVERT(::mlc::base::PODTraits<::mlc::base::RemoveCR<T>>::AnyCopyToType(this), this->type_index,
71-
::mlc::base::Type2Str<T>::Run());
72-
}
73-
template <typename _T> MLC_INLINE_NO_MSVC _T AnyView::Cast(::mlc::base::tag::RawObjPtr) const {
74-
using T = std::remove_pointer_t<_T>;
75-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<::mlc::base::RemoveCR<T>>::AnyToUnownedPtr(this), this->type_index,
76-
::mlc::base::Type2Str<T *>::Run());
77-
}
78-
template <typename T> MLC_INLINE_NO_MSVC T *AnyView::CastWithStorage(Any *storage) const {
79-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<T>::AnyToOwnedPtrWithStorage(this, storage), this->type_index,
80-
::mlc::base::Type2Str<T *>::Run());
81-
}
82-
} // namespace mlc
8364

84-
/*********** Any ***********/
85-
86-
namespace mlc {
87-
MLC_INLINE Any::Any(::mlc::base::tag::ObjPtr, const MLCObjPtr &src) : MLCAny() {
88-
if (src.ptr != nullptr) {
89-
this->type_index = src.ptr->type_index;
90-
this->v_obj = src.ptr;
65+
template <typename T> MLC_INLINE Any::Any(const T &src) : MLCAny() {
66+
using namespace ::mlc::base;
67+
if constexpr (HasTypeTraits<RemoveCR<T>>) {
68+
TypeTraits<RemoveCR<T>>::TypeToAny(src, this);
69+
this->SwitchFromRawStr();
9170
this->IncRef();
71+
} else {
72+
(src.operator Any()).Swap(*this);
9273
}
9374
}
94-
MLC_INLINE Any::Any(::mlc::base::tag::ObjPtr, MLCObjPtr &&src) : MLCAny() {
95-
if (src.ptr != nullptr) {
96-
this->type_index = src.ptr->type_index;
97-
this->v_obj = src.ptr;
98-
src.ptr = nullptr;
99-
}
100-
}
101-
template <typename T> MLC_INLINE Any::Any(::mlc::base::tag::RawObjPtr, T *src) : MLCAny() {
102-
::mlc::base::PtrToAnyView<T>(src, this);
103-
this->IncRef();
104-
}
105-
template <typename T> MLC_INLINE T Any::Cast() const {
106-
if constexpr (std::is_same_v<T, Any> || std::is_same_v<T, AnyView>) {
107-
return *this;
75+
76+
template <typename T> MLC_INLINE_NO_MSVC T AnyView::Cast() const {
77+
using namespace ::mlc::base;
78+
if constexpr (HasTypeTraits<T>) {
79+
MLC_TRY_CONVERT(TypeTraits<T>::AnyToTypeUnowned(this), this->type_index, Type2Str<T>::Run());
10880
} else {
109-
return this->operator T();
81+
return T(*this);
11082
}
11183
}
112-
template <typename T> MLC_INLINE T Any::Cast(::mlc::base::tag::ObjPtr) const {
113-
if constexpr (::mlc::base::IsObjRef<T>) {
114-
if (this->type_index == static_cast<int32_t>(MLCTypeIndex::kMLCNone)) {
115-
using RefT = Ref<typename T::TObj>;
116-
MLC_THROW(TypeError) << "Cannot convert from type `None` to non-nullable `" << ::mlc::base::Type2Str<RefT>::Run()
117-
<< "`";
118-
}
84+
85+
template <typename T> MLC_INLINE_NO_MSVC T Any::Cast() const {
86+
using namespace ::mlc::base;
87+
if constexpr (HasTypeTraits<T>) {
88+
MLC_TRY_CONVERT(TypeTraits<T>::AnyToTypeUnowned(this), this->type_index, Type2Str<T>::Run());
89+
} else {
90+
return T(*this);
11991
}
120-
using TObj = typename T::TObj;
121-
return T([this]() -> TObj * {
122-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<TObj>::AnyToOwnedPtr(this), this->type_index,
123-
::mlc::base::Type2Str<TObj *>::Run());
124-
}());
12592
}
126-
template <typename T> MLC_INLINE_NO_MSVC T Any::Cast(::mlc::base::tag::POD) const {
127-
MLC_TRY_CONVERT(::mlc::base::PODTraits<::mlc::base::RemoveCR<T>>::AnyCopyToType(this), this->type_index,
128-
::mlc::base::Type2Str<T>::Run());
129-
}
130-
template <typename _T> MLC_INLINE_NO_MSVC _T Any::Cast(::mlc::base::tag::RawObjPtr) const {
131-
using T = std::remove_pointer_t<_T>;
132-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<::mlc::base::RemoveCR<T>>::AnyToUnownedPtr(this), this->type_index,
133-
::mlc::base::Type2Str<T *>::Run());
93+
94+
template <typename T> MLC_INLINE_NO_MSVC T AnyView::CastWithStorage(Any *storage) const {
95+
using namespace ::mlc::base;
96+
MLC_TRY_CONVERT(TypeTraits<T>::AnyToTypeWithStorage(this, storage), this->type_index, Type2Str<T>::Run());
13497
}
135-
template <typename T> MLC_INLINE_NO_MSVC T *Any::CastWithStorage(Any *storage) const {
136-
MLC_TRY_CONVERT(::mlc::base::ObjPtrTraits<T>::AnyToOwnedPtrWithStorage(this, storage), this->type_index,
137-
::mlc::base::Type2Str<T *>::Run());
98+
99+
template <typename T> MLC_INLINE_NO_MSVC T Any::CastWithStorage(Any *storage) const {
100+
using namespace ::mlc::base;
101+
MLC_TRY_CONVERT(TypeTraits<T>::AnyToTypeWithStorage(this, storage), this->type_index, Type2Str<T>::Run());
138102
}
139-
} // namespace mlc
140103

141-
namespace mlc {
142-
namespace base {
143-
struct ReflectionHelper {
144-
explicit ReflectionHelper(int32_t type_index);
145-
template <typename Super, typename FieldType>
146-
ReflectionHelper &FieldReadOnly(const char *name, FieldType Super::*field);
147-
template <typename Super, typename FieldType> ReflectionHelper &Field(const char *name, FieldType Super::*field);
148-
template <typename Callable> ReflectionHelper &MemFn(const char *name, Callable &&method);
149-
template <typename Callable> ReflectionHelper &StaticFn(const char *name, Callable &&method);
150-
operator int32_t();
151-
static std::string DefaultStrMethod(AnyView any);
104+
/*********** Section 3. Conversion between Any/AnyView <=> Ref ***********/
152105

153-
private:
154-
template <typename Cls, typename FieldType> constexpr std::ptrdiff_t ReflectOffset(FieldType Cls::*member) {
155-
return reinterpret_cast<std::ptrdiff_t>(&((Cls *)(nullptr)->*member));
106+
template <typename T> MLC_INLINE Ref<T>::Ref(const AnyView &src) : TBase() { TBase::_Init<T>(src); }
107+
template <typename T> MLC_INLINE Ref<T>::Ref(const Any &src) : TBase() { TBase::_Init<T>(src); }
108+
template <typename T> MLC_INLINE Ref<T>::operator AnyView() const {
109+
if (this->ptr != nullptr) {
110+
AnyView ret;
111+
ret.type_index = this->ptr->type_index;
112+
ret.v_obj = this->ptr;
113+
return ret;
156114
}
157-
template <typename Super, typename FieldType> MLCTypeField PrepareField(const char *name, FieldType Super::*field);
158-
template <typename Callable> MLCTypeMethod PrepareMethod(const char *name, Callable &&method);
115+
return AnyView();
116+
}
117+
template <typename T> MLC_INLINE Ref<T>::operator Any() const & {
118+
if (this->ptr != nullptr) {
119+
Any ret;
120+
ret.type_index = this->ptr->type_index;
121+
ret.v_obj = this->ptr;
122+
::mlc::base::IncRef(this->ptr);
123+
return ret;
124+
}
125+
return Any();
126+
}
127+
template <typename T> MLC_INLINE Ref<T>::operator Any() && {
128+
if (this->ptr != nullptr) {
129+
Any ret;
130+
ret.type_index = this->ptr->type_index;
131+
ret.v_obj = this->ptr;
132+
this->ptr = nullptr;
133+
return ret;
134+
}
135+
return Any();
136+
}
159137

160-
int32_t type_index;
161-
std::vector<MLCTypeField> fields;
162-
std::vector<MLCTypeMethod> methods;
163-
std::vector<Any> method_pool;
164-
std::vector<std::vector<MLCTypeInfo *>> type_annotation_pool;
165-
};
166-
} // namespace base
167-
} // namespace mlc
138+
/*********** Section 4. AnyViewArray ***********/
168139

169-
namespace mlc {
170140
template <std::size_t N> template <typename... Args> MLC_INLINE void AnyViewArray<N>::Fill(Args &&...args) {
171141
static_assert(sizeof...(args) == N, "Invalid number of arguments");
172142
if constexpr (N > 0) {

0 commit comments

Comments
 (0)