This commit is contained in:
blueloveTH 2024-03-02 02:56:48 +08:00
parent 39fe442575
commit ba33b69240
3 changed files with 102 additions and 58 deletions

View File

@ -7,7 +7,7 @@
namespace pkpy {
#define PY_CLASS(T, mod, name) \
static Type _type(VM* vm) { return vm->_cxx_typeid_map[typeid(T)]; } \
static Type _type(VM* vm) { return vm->_cxx_typeid_map[&typeid(T)]; } \
static void _check_type(VM* vm, PyObject* val){ \
if(!vm->isinstance(val, T::_type(vm))){ \
vm->TypeError("expected '" #mod "." #name "', got " + _type_name(vm, vm->_tp(val)).escape()); \
@ -21,7 +21,7 @@ namespace pkpy {
} \
PyObject* type = vm->new_type_object(mod, #name, base); \
mod->attr().set(#name, type); \
vm->_cxx_typeid_map[typeid(T)] = PK_OBJ_GET(Type, type); \
vm->_cxx_typeid_map[&typeid(T)] = PK_OBJ_GET(Type, type); \
T::_register(vm, mod, type); \
return type; \
}
@ -54,6 +54,10 @@ struct VoidP{
static void _register(VM* vm, PyObject* mod, PyObject* type);
};
inline PyObject* py_var(VM* vm, void* p){
return VAR_T(VoidP, p);
}
inline PyObject* py_var(VM* vm, const void* p){
return VAR_T(VoidP, p);
}

View File

@ -18,7 +18,7 @@
#include <type_traits>
#include <random>
#include <deque>
#include <typeindex>
#include <typeinfo>
#include <initializer_list>
#define PK_VERSION "1.4.2"
@ -238,4 +238,19 @@ inline const char* kPlatformStrings[] = {
#define PK_SLICE_LOOP(i, start, stop, step) for(int i=start; step>0?i<stop:i>stop; i+=step)
template<typename T>
inline constexpr bool is_integral_v = std::is_same_v<T, char>
|| std::is_same_v<T, short>
|| std::is_same_v<T, int>
|| std::is_same_v<T, long>
|| std::is_same_v<T, long long>
|| std::is_same_v<T, unsigned char>
|| std::is_same_v<T, unsigned short>
|| std::is_same_v<T, unsigned int>
|| std::is_same_v<T, unsigned long>
|| std::is_same_v<T, unsigned long long>;
template<typename T>
inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_same_v<T, double>;
} // namespace pkpy

View File

@ -12,6 +12,7 @@
#include "dict.h"
#include "profiler.h"
namespace pkpy{
/* Stack manipulation macros */
@ -40,9 +41,7 @@ namespace pkpy{
} \
template<> inline ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) { \
return PK_OBJ_GET(ctype, obj); \
} \
inline PyObject* py_var(VM* vm, const ctype& value) { return vm->heap.gcnew<ctype>(vm->ptype, value);} \
inline PyObject* py_var(VM* vm, ctype&& value) { return vm->heap.gcnew<ctype>(vm->ptype, std::move(value));}
}
typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*);
@ -142,7 +141,7 @@ public:
std::map<std::string_view, CodeObject_> _cached_codes;
// typeid -> Type
std::map<std::type_index, Type> _cxx_typeid_map;
std::map<const std::type_info*, Type> _cxx_typeid_map;
void (*_ceval_on_step)(VM*, Frame*, Bytecode bc) = nullptr;
@ -465,6 +464,83 @@ DEF_NATIVE_2(ClassMethod, tp_classmethod)
#undef DEF_NATIVE_2
constexpr std::pair<const std::type_info*, Type> _const_cxx_typeid_map[] = {
{&typeid(Str), VM::tp_str},
{&typeid(List), VM::tp_list},
{&typeid(Tuple), VM::tp_tuple},
{&typeid(Function), VM::tp_function},
{&typeid(NativeFunc), VM::tp_native_func},
{&typeid(BoundMethod), VM::tp_bound_method},
{&typeid(Range), VM::tp_range},
{&typeid(Slice), VM::tp_slice},
{&typeid(Exception), VM::tp_exception},
{&typeid(Bytes), VM::tp_bytes},
{&typeid(MappingProxy), VM::tp_mappingproxy},
{&typeid(Dict), VM::tp_dict},
{&typeid(Property), VM::tp_property},
{&typeid(StarWrapper), VM::tp_star_wrapper},
{&typeid(StaticMethod), VM::tp_staticmethod},
{&typeid(ClassMethod), VM::tp_classmethod},
/***************************************/
};
template<typename T>
constexpr Type _find_type_in_const_cxx_typeid_map(){
for(auto& p : _const_cxx_typeid_map) if(p.first == &typeid(T)) return p.second;
return -1;
}
template<typename __T>
PyObject* py_var(VM* vm, __T&& value){
using T = std::decay_t<__T>;
static_assert(!std::is_same_v<T, PyObject*>, "py_var(VM*, PyObject*) is not allowed");
if constexpr(std::is_same_v<T, const char*> || std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>){
// str (shortcuts)
return VAR(Str(std::forward<__T>(value)));
}else if constexpr(std::is_same_v<T, NoReturn>){
// NoneType
return vm->None;
}else if constexpr(std::is_same_v<T, bool>){
// bool
return value ? vm->True : vm->False;
}else if constexpr(is_integral_v<T>){
// int
i64 val = static_cast<i64>(std::forward<__T>(value));
if(val >= Number::kMinSmallInt && val <= Number::kMaxSmallInt){
val = (val << 2) | 0b10;
return reinterpret_cast<PyObject*>(val);
}else{
return vm->heap.gcnew<i64>(vm->tp_int, val);
}
}else if constexpr(is_floating_point_v<T>){
// float
return tag_float(static_cast<f64>(std::forward<__T>(value)));
}else{
constexpr Type const_type = _find_type_in_const_cxx_typeid_map<T>();
if constexpr(const_type.index >= 0){
return vm->heap.gcnew<T>(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
}
return vm->heap.gcnew<T>(it->second, std::forward<__T>(value));
}
#define PY_CAST_INT(T) \
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); \
@ -509,41 +585,6 @@ template<> inline double _py_cast<double>(VM* vm, PyObject* obj){
return py_cast<double>(vm, obj);
}
#define PY_VAR_INT(T) \
inline PyObject* py_var(VM* vm, T _val){ \
i64 val = static_cast<i64>(_val); \
if(val >= Number::kMinSmallInt && val <= Number::kMaxSmallInt){ \
val = (val << 2) | 0b10; \
return reinterpret_cast<PyObject*>(val); \
}else{ \
return vm->heap.gcnew<i64>(vm->tp_int, val); \
} \
}
PY_VAR_INT(char)
PY_VAR_INT(short)
PY_VAR_INT(int)
PY_VAR_INT(long)
PY_VAR_INT(long long)
PY_VAR_INT(unsigned char)
PY_VAR_INT(unsigned short)
PY_VAR_INT(unsigned int)
PY_VAR_INT(unsigned long)
PY_VAR_INT(unsigned long long)
#undef PY_VAR_INT
inline PyObject* py_var(VM* vm, float _val){
return tag_float(static_cast<f64>(_val));
}
inline PyObject* py_var(VM* vm, double _val){
return tag_float(static_cast<f64>(_val));
}
inline PyObject* py_var(VM* vm, bool val){
return val ? vm->True : vm->False;
}
template<> inline bool py_cast<bool>(VM* vm, PyObject* obj){
if(obj == vm->True) return true;
if(obj == vm->False) return false;
@ -563,10 +604,6 @@ template<> inline CString _py_cast<CString>(VM* vm, PyObject* obj){
return PK_OBJ_GET(Str, obj).c_str();
}
inline PyObject* py_var(VM* vm, const char* val){
return VAR(Str(val));
}
template<>
inline const char* py_cast<const char*>(VM* vm, PyObject* obj){
if(obj == vm->None) return nullptr;
@ -579,18 +616,6 @@ inline const char* _py_cast<const char*>(VM* vm, PyObject* obj){
return PK_OBJ_GET(Str, obj).c_str();
}
inline PyObject* py_var(VM* vm, std::string val){
return VAR(Str(val));
}
inline PyObject* py_var(VM* vm, std::string_view val){
return VAR(Str(val));
}
inline PyObject* py_var(VM* vm, NoReturn val){
return vm->None;
}
template<int ARGC>
PyObject* VM::bind_method(Type type, Str name, NativeFuncC fn) {
PyObject* nf = VAR(NativeFunc(fn, ARGC, true));