mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 04:50:17 +00:00
refactor
This commit is contained in:
parent
39fe442575
commit
ba33b69240
@ -7,7 +7,7 @@
|
|||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
#define PY_CLASS(T, mod, name) \
|
#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){ \
|
static void _check_type(VM* vm, PyObject* val){ \
|
||||||
if(!vm->isinstance(val, T::_type(vm))){ \
|
if(!vm->isinstance(val, T::_type(vm))){ \
|
||||||
vm->TypeError("expected '" #mod "." #name "', got " + _type_name(vm, vm->_tp(val)).escape()); \
|
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); \
|
PyObject* type = vm->new_type_object(mod, #name, base); \
|
||||||
mod->attr().set(#name, type); \
|
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); \
|
T::_register(vm, mod, type); \
|
||||||
return type; \
|
return type; \
|
||||||
}
|
}
|
||||||
@ -54,6 +54,10 @@ struct VoidP{
|
|||||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
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){
|
inline PyObject* py_var(VM* vm, const void* p){
|
||||||
return VAR_T(VoidP, p);
|
return VAR_T(VoidP, p);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <typeindex>
|
#include <typeinfo>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
#define PK_VERSION "1.4.2"
|
#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)
|
#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
|
} // namespace pkpy
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
|
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
/* Stack manipulation macros */
|
/* Stack manipulation macros */
|
||||||
@ -40,9 +41,7 @@ namespace pkpy{
|
|||||||
} \
|
} \
|
||||||
template<> inline ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) { \
|
template<> inline ctype& _py_cast<ctype&>(VM* vm, PyObject* obj) { \
|
||||||
return PK_OBJ_GET(ctype, 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*);
|
typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*);
|
||||||
@ -142,7 +141,7 @@ public:
|
|||||||
std::map<std::string_view, CodeObject_> _cached_codes;
|
std::map<std::string_view, CodeObject_> _cached_codes;
|
||||||
|
|
||||||
// typeid -> Type
|
// 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;
|
void (*_ceval_on_step)(VM*, Frame*, Bytecode bc) = nullptr;
|
||||||
|
|
||||||
@ -465,6 +464,83 @@ DEF_NATIVE_2(ClassMethod, tp_classmethod)
|
|||||||
|
|
||||||
#undef DEF_NATIVE_2
|
#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) \
|
#define PY_CAST_INT(T) \
|
||||||
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
|
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
|
||||||
if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); \
|
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);
|
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){
|
template<> inline bool py_cast<bool>(VM* vm, PyObject* obj){
|
||||||
if(obj == vm->True) return true;
|
if(obj == vm->True) return true;
|
||||||
if(obj == vm->False) return false;
|
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();
|
return PK_OBJ_GET(Str, obj).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* py_var(VM* vm, const char* val){
|
|
||||||
return VAR(Str(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline const char* py_cast<const char*>(VM* vm, PyObject* obj){
|
inline const char* py_cast<const char*>(VM* vm, PyObject* obj){
|
||||||
if(obj == vm->None) return nullptr;
|
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();
|
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>
|
template<int ARGC>
|
||||||
PyObject* VM::bind_method(Type type, Str name, NativeFuncC fn) {
|
PyObject* VM::bind_method(Type type, Str name, NativeFuncC fn) {
|
||||||
PyObject* nf = VAR(NativeFunc(fn, ARGC, true));
|
PyObject* nf = VAR(NativeFunc(fn, ARGC, true));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user