From 825efaecc6314ad86035a689ee1af3defcc92312 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 2 Mar 2024 03:31:07 +0800 Subject: [PATCH] refactor 2 --- include/pocketpy/obj.h | 33 ------- include/pocketpy/vm.h | 198 +++++++++++++++-------------------------- 2 files changed, 74 insertions(+), 157 deletions(-) diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index 6ac99848..85abe4ee 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -209,41 +209,8 @@ inline void gc_mark_namedict(NameDict& t){ } StrName _type_name(VM* vm, Type type); - -template struct is_py_class : std::false_type {}; -template struct is_py_class> : std::true_type {}; - template T to_void_p(VM*, PyObject*); -template -__T py_cast(VM* vm, PyObject* obj) { - using T = std::decay_t<__T>; - if constexpr(std::is_enum_v){ - return (__T)py_cast(vm, obj); - }else if constexpr(std::is_pointer_v){ - return to_void_p(vm, obj); - }else if constexpr(is_py_class::value){ - T::_check_type(vm, obj); - return PK_OBJ_GET(T, obj); - }else { - return Discarded(); - } -} - -template -__T _py_cast(VM* vm, PyObject* obj) { - using T = std::decay_t<__T>; - if constexpr(std::is_enum_v){ - return (__T)_py_cast(vm, obj); - }else if constexpr(std::is_pointer_v<__T>){ - return to_void_p<__T>(vm, obj); - }else if constexpr(is_py_class::value){ - return PK_OBJ_GET(T, obj); - }else { - return Discarded(); - } -} - #define VAR(x) py_var(vm, x) #define CAST(T, x) py_cast(vm, x) #define _CAST(T, x) _py_cast(vm, x) diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 3a9f1cec..8a1f32c9 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -27,23 +27,6 @@ namespace pkpy{ #define POPX() (s_data.popx()) #define STACK_VIEW(n) (s_data.view(n)) -#define DEF_NATIVE_2(ctype, ptype) \ - template<> inline ctype py_cast(VM* vm, PyObject* obj) { \ - vm->check_non_tagged_type(obj, vm->ptype); \ - return PK_OBJ_GET(ctype, obj); \ - } \ - template<> inline ctype _py_cast(VM* vm, PyObject* obj) { \ - return PK_OBJ_GET(ctype, obj); \ - } \ - template<> inline ctype& py_cast(VM* vm, PyObject* obj) { \ - vm->check_non_tagged_type(obj, vm->ptype); \ - return PK_OBJ_GET(ctype, obj); \ - } \ - template<> inline ctype& _py_cast(VM* vm, PyObject* obj) { \ - return PK_OBJ_GET(ctype, obj); \ - } - - typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*); struct PyTypeInfo{ @@ -443,27 +426,23 @@ public: PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind_property(PyObject*, Str, NativeFuncC fget, NativeFuncC fset=nullptr); + + template + Type _find_type_in_cxx_typeid_map(){ + auto it = _cxx_typeid_map.find(&typeid(T)); + if(it == _cxx_typeid_map.end()){ + #if __GNUC__ || __clang__ + throw std::runtime_error(__PRETTY_FUNCTION__ + std::string(" failed: T not found")); + #elif _MSC_VER + throw std::runtime_error(__FUNCSIG__ + std::string(" failed: T not found")); + #else + throw std::runtime_error("py_var() failed: T not found"); + #endif + } + return it->second; + } }; -DEF_NATIVE_2(Str, tp_str) -DEF_NATIVE_2(List, tp_list) -DEF_NATIVE_2(Tuple, tp_tuple) -DEF_NATIVE_2(Function, tp_function) -DEF_NATIVE_2(NativeFunc, tp_native_func) -DEF_NATIVE_2(BoundMethod, tp_bound_method) -DEF_NATIVE_2(Range, tp_range) -DEF_NATIVE_2(Slice, tp_slice) -DEF_NATIVE_2(Exception, tp_exception) -DEF_NATIVE_2(Bytes, tp_bytes) -DEF_NATIVE_2(MappingProxy, tp_mappingproxy) -DEF_NATIVE_2(Dict, tp_dict) -DEF_NATIVE_2(Property, tp_property) -DEF_NATIVE_2(StarWrapper, tp_star_wrapper) -DEF_NATIVE_2(StaticMethod, tp_staticmethod) -DEF_NATIVE_2(ClassMethod, tp_classmethod) - -#undef DEF_NATIVE_2 - constexpr std::pair _const_cxx_typeid_map[] = { {&typeid(Str), VM::tp_str}, {&typeid(List), VM::tp_list}, @@ -523,99 +502,70 @@ PyObject* py_var(VM* vm, __T&& value){ return vm->heap.gcnew(const_type, std::forward<__T>(value)); } } - // dynamic type - auto it = vm->_cxx_typeid_map.find(&typeid(T)); - if(it == vm->_cxx_typeid_map.end()){ -#if __GNUC__ || __clang__ - throw std::runtime_error(__PRETTY_FUNCTION__ + std::string(" failed: T not found")); -#elif _MSC_VER - throw std::runtime_error(__FUNCSIG__ + std::string(" failed: T not found")); -#else - throw std::runtime_error("py_var() failed: T not found"); -#endif + Type type = vm->_find_type_in_cxx_typeid_map(); + return vm->heap.gcnew(type, std::forward<__T>(value)); +} + +template +__T _py_cast__internal(VM* vm, PyObject* obj) { + using T = std::decay_t<__T>; + + if constexpr(std::is_same_v || std::is_same_v){ + // str (shortcuts) + if constexpr(with_check){ + if(obj == vm->None) return nullptr; + vm->check_non_tagged_type(obj, vm->tp_str); + return PK_OBJ_GET(Str, obj).c_str(); + }else{ + return PK_OBJ_GET(Str, obj).c_str(); + } + }else if constexpr(std::is_same_v){ + // bool + if constexpr(with_check){ + if(obj == vm->True) return true; + if(obj == vm->False) return false; + vm->TypeError("expected 'bool', got " + _type_name(vm, vm->_tp(obj)).escape()); + }else{ + return obj == vm->True; + } + }else if constexpr(is_integral_v){ + // int + if constexpr(with_check){ + if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); + if(is_heap_int(obj)) return (T)PK_OBJ_GET(i64, obj); + vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape()); + }else{ + if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); + return (T)PK_OBJ_GET(i64, obj); + } + }else if constexpr(is_floating_point_v){ + // float + if(is_float(obj)) return untag_float(obj); + i64 bits; + if(try_cast_int(obj, &bits)) return (float)bits; + vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape()); + }else if constexpr(std::is_enum_v){ + return (__T)_py_cast__internal(vm, obj); + }else if constexpr(std::is_pointer_v){ + return to_void_p(vm, obj); + }else{ + constexpr Type const_type = _find_type_in_const_cxx_typeid_map(); + if constexpr(const_type.index >= 0){ + if constexpr(with_check) vm->check_non_tagged_type(obj, const_type); + return PK_OBJ_GET(T, obj); + } } - return vm->heap.gcnew(it->second, std::forward<__T>(value)); + Type type = vm->_find_type_in_cxx_typeid_map(); + if constexpr(with_check) vm->check_non_tagged_type(obj, type); + return PK_OBJ_GET(T, obj); } +template +__T py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, true>(vm, obj); } +template +__T _py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, false>(vm, obj); } - - -#define PY_CAST_INT(T) \ -template<> inline T py_cast(VM* vm, PyObject* obj){ \ - if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); \ - if(is_heap_int(obj)) return (T)PK_OBJ_GET(i64, obj); \ - vm->check_type(obj, vm->tp_int); \ - return 0; \ -} \ -template<> inline T _py_cast(VM* vm, PyObject* obj){ \ - if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); \ - return (T)PK_OBJ_GET(i64, obj); \ -} - -PY_CAST_INT(char) -PY_CAST_INT(short) -PY_CAST_INT(int) -PY_CAST_INT(long) -PY_CAST_INT(long long) -PY_CAST_INT(unsigned char) -PY_CAST_INT(unsigned short) -PY_CAST_INT(unsigned int) -PY_CAST_INT(unsigned long) -PY_CAST_INT(unsigned long long) - -template<> inline float py_cast(VM* vm, PyObject* obj){ - if(is_float(obj)) return untag_float(obj); - i64 bits; - if(try_cast_int(obj, &bits)) return (float)bits; - vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape()); - return 0; -} -template<> inline float _py_cast(VM* vm, PyObject* obj){ - return py_cast(vm, obj); -} -template<> inline double py_cast(VM* vm, PyObject* obj){ - if(is_float(obj)) return untag_float(obj); - i64 bits; - if(try_cast_int(obj, &bits)) return (float)bits; - vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape()); - return 0; -} -template<> inline double _py_cast(VM* vm, PyObject* obj){ - return py_cast(vm, obj); -} - -template<> inline bool py_cast(VM* vm, PyObject* obj){ - if(obj == vm->True) return true; - if(obj == vm->False) return false; - vm->check_non_tagged_type(obj, vm->tp_bool); - return false; -} -template<> inline bool _py_cast(VM* vm, PyObject* obj){ - return obj == vm->True; -} - -template<> inline CString py_cast(VM* vm, PyObject* obj){ - vm->check_non_tagged_type(obj, vm->tp_str); - return PK_OBJ_GET(Str, obj).c_str(); -} - -template<> inline CString _py_cast(VM* vm, PyObject* obj){ - return PK_OBJ_GET(Str, obj).c_str(); -} - -template<> -inline const char* py_cast(VM* vm, PyObject* obj){ - if(obj == vm->None) return nullptr; - vm->check_non_tagged_type(obj, vm->tp_str); - return PK_OBJ_GET(Str, obj).c_str(); -} - -template<> -inline const char* _py_cast(VM* vm, PyObject* obj){ - return PK_OBJ_GET(Str, obj).c_str(); -} - template PyObject* VM::bind_method(Type type, Str name, NativeFuncC fn) { PyObject* nf = VAR(NativeFunc(fn, ARGC, true));