mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-31 00:40:16 +00:00 
			
		
		
		
	* add some clang-format offs. * add formats. * format the world. * AllowShortIfStatementsOnASingleLine * off REGION. * Rollback vm.hpp * Disable insert.
		
			
				
	
	
		
			146 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include "kernel.h"
 | |
| 
 | |
| namespace pybind11 {
 | |
| struct type_info {
 | |
|     const char* name;
 | |
|     std::size_t size;
 | |
|     std::size_t alignment;
 | |
|     void (*destructor)(void*);
 | |
|     void (*copy)(void*, const void*);
 | |
|     void (*move)(void*, void*);
 | |
|     const std::type_info* type;
 | |
| 
 | |
|     template <typename T>
 | |
|     static type_info& of() {
 | |
|         static_assert(!std::is_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>,
 | |
|                       "T must not be a reference type or const type.");
 | |
|         static type_info info = {
 | |
|             typeid(T).name(),
 | |
|             sizeof(T),
 | |
|             alignof(T),
 | |
|             [](void* ptr) {
 | |
|                 ((T*)ptr)->~T();
 | |
|                 operator delete (ptr);
 | |
|             },
 | |
|             [](void* dst, const void* src) {
 | |
|                 new (dst) T(*(const T*)src);
 | |
|             },
 | |
|             [](void* dst, void* src) {
 | |
|                 new (dst) T(std::move(*(T*)src));
 | |
|             },
 | |
|             &typeid(T),
 | |
|         };
 | |
|         return info;
 | |
|     }
 | |
| };
 | |
| 
 | |
| // all registered C++ class will be ensured as instance type.
 | |
| class instance {
 | |
| public:
 | |
|     // use to record the type information of C++ class.
 | |
| 
 | |
| private:
 | |
|     enum Flag {
 | |
|         None = 0,
 | |
|         Own = 1 << 0,  // if the instance is owned by C++ side.
 | |
|         Ref = 1 << 1,  // need to mark the parent object.
 | |
|     };
 | |
| 
 | |
|     Flag flag;
 | |
|     void* data;
 | |
|     const type_info* type;
 | |
|     pkpy::PyVar parent;
 | |
|     // pkpy::PyVar
 | |
| 
 | |
| public:
 | |
|     instance() noexcept : flag(Flag::None), data(nullptr), type(nullptr), parent(nullptr) {}
 | |
| 
 | |
|     instance(const instance&) = delete;
 | |
| 
 | |
|     instance(instance&& other) noexcept : flag(other.flag), data(other.data), type(other.type), parent(other.parent) {
 | |
|         other.flag = Flag::None;
 | |
|         other.data = nullptr;
 | |
|         other.type = nullptr;
 | |
|         other.parent = nullptr;
 | |
|     }
 | |
| 
 | |
|     template <typename T>
 | |
|     static pkpy::PyVar create(pkpy::Type type) {
 | |
|         instance instance;
 | |
|         instance.type = &type_info::of<T>();
 | |
|         instance.data = operator new (sizeof(T));
 | |
|         instance.flag = Flag::Own;
 | |
|         return vm->new_object<pybind11::instance>(type, std::move(instance));
 | |
|     }
 | |
| 
 | |
|     template <typename T>
 | |
|     static pkpy::PyVar create(T&& value,
 | |
|                               pkpy::Type type,
 | |
|                               return_value_policy policy = return_value_policy::automatic_reference,
 | |
|                               pkpy::PyVar parent = nullptr) noexcept {
 | |
|         using underlying_type = std::remove_cv_t<std::remove_reference_t<T>>;
 | |
| 
 | |
|         // resolve for automatic policy.
 | |
|         if(policy == return_value_policy::automatic) {
 | |
|             policy = std::is_pointer_v<underlying_type> ? return_value_policy::take_ownership
 | |
|                      : std::is_lvalue_reference_v<T&&>  ? return_value_policy::copy
 | |
|                                                         : return_value_policy::move;
 | |
|         } else if(policy == return_value_policy::automatic_reference) {
 | |
|             policy = std::is_pointer_v<underlying_type> ? return_value_policy::reference
 | |
|                      : std::is_lvalue_reference_v<T&&>  ? return_value_policy::copy
 | |
|                                                         : return_value_policy::move;
 | |
|         }
 | |
| 
 | |
|         auto& _value = [&]() -> auto& {
 | |
|             /**
 | |
|              * note that, pybind11 will ignore the const qualifier.
 | |
|              * in fact, try to modify a const value will result in undefined behavior.
 | |
|              */
 | |
|             if constexpr(std::is_pointer_v<underlying_type>) {
 | |
|                 return *reinterpret_cast<underlying_type*>(value);
 | |
|             } else {
 | |
|                 return const_cast<underlying_type&>(value);
 | |
|             }
 | |
|         }();
 | |
| 
 | |
|         instance instance;
 | |
|         instance.type = &type_info::of<underlying_type>();
 | |
| 
 | |
|         if(policy == return_value_policy::take_ownership) {
 | |
|             instance.data = &_value;
 | |
|             instance.flag = Flag::Own;
 | |
|         } else if(policy == return_value_policy::copy) {
 | |
|             instance.data = ::new auto(_value);
 | |
|             instance.flag = Flag::Own;
 | |
|         } else if(policy == return_value_policy::move) {
 | |
|             instance.data = ::new auto(std::move(_value));
 | |
|             instance.flag = Flag::Own;
 | |
|         } else if(policy == return_value_policy::reference) {
 | |
|             instance.data = &_value;
 | |
|             instance.flag = Flag::None;
 | |
|         } else if(policy == return_value_policy::reference_internal) {
 | |
|             instance.data = &_value;
 | |
|             instance.flag = Flag::Ref;
 | |
|             instance.parent = parent;
 | |
|         }
 | |
| 
 | |
|         return vm->new_object<pybind11::instance>(type, std::move(instance));
 | |
|     }
 | |
| 
 | |
|     ~instance() {
 | |
|         if(flag & Flag::Own) { type->destructor(data); }
 | |
|     }
 | |
| 
 | |
|     void _gc_mark(pkpy::VM* vm) const noexcept {
 | |
|         if(parent && (flag & Flag::Ref)) { PK_OBJ_MARK(parent); }
 | |
|     }
 | |
| 
 | |
|     template <typename T>
 | |
|     T& cast() noexcept {
 | |
|         return *static_cast<T*>(data);
 | |
|     }
 | |
| };
 | |
| }  // namespace pybind11
 |