diff --git a/include/pocketpy/common.h b/include/pocketpy/common.h index 7d1421a1..335ef742 100644 --- a/include/pocketpy/common.h +++ b/include/pocketpy/common.h @@ -99,7 +99,7 @@ struct Discarded { }; struct Type { int index; constexpr Type(): index(-1) {} - constexpr Type(int index): index(index) {} + explicit constexpr Type(int index): index(index) {} bool operator==(Type other) const { return this->index == other.index; } bool operator!=(Type other) const { return this->index != other.index; } operator int() const { return this->index; } diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 9f68f76f..85e32946 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -27,6 +27,7 @@ namespace pkpy{ #define STACK_VIEW(n) (s_data.view(n)) typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*); +typedef void (*RegisterFunc)(VM*, PyObject*, PyObject*); #if PK_ENABLE_PROFILER struct NextBreakpoint{ @@ -169,14 +170,14 @@ public: unsigned char* (*_import_handler)(const char*, int, int*); // for quick access - static constexpr Type tp_object=0, tp_type=1; - static constexpr Type tp_int=kTpIntIndex, tp_float=kTpFloatIndex, tp_bool=4, tp_str=5; - static constexpr Type tp_list=6, tp_tuple=7; - static constexpr Type tp_slice=8, tp_range=9, tp_module=10; - static constexpr Type tp_function=11, tp_native_func=12, tp_bound_method=13; - static constexpr Type tp_super=14, tp_exception=15, tp_bytes=16, tp_mappingproxy=17; - static constexpr Type tp_dict=18, tp_property=19, tp_star_wrapper=20; - static constexpr Type tp_staticmethod=21, tp_classmethod=22; + static constexpr Type tp_object=Type(0), tp_type=Type(1); + static constexpr Type tp_int=Type(kTpIntIndex), tp_float=Type(kTpFloatIndex), tp_bool=Type(4), tp_str=Type(5); + static constexpr Type tp_list=Type(6), tp_tuple=Type(7); + static constexpr Type tp_slice=Type(8), tp_range=Type(9), tp_module=Type(10); + static constexpr Type tp_function=Type(11), tp_native_func=Type(12), tp_bound_method=Type(13); + static constexpr Type tp_super=Type(14), tp_exception=Type(15), tp_bytes=Type(16), tp_mappingproxy=Type(17); + static constexpr Type tp_dict=Type(18), tp_property=Type(19), tp_star_wrapper=Type(20); + static constexpr Type tp_staticmethod=Type(21), tp_classmethod=Type(22); const bool enable_os; VM(bool enable_os=true); @@ -353,8 +354,11 @@ public: Type _tp_user(){ return _find_type_in_cxx_typeid_map(); } template bool is_user_type(PyObject* obj){ return _tp(obj) == _tp_user(); } + template - PyObject* register_user_class(PyObject* mod, StrName name, bool subclass_enabled=false); + PyObject* register_user_class(PyObject*, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false); + template + PyObject* register_user_class(PyObject*, StrName, Type base=tp_object, bool subclass_enabled=false); template PyObject* new_user_object(Args&&... args){ @@ -413,7 +417,7 @@ inline constexpr bool is_immutable_v = is_integral_v || is_floating_point_v || std::is_same_v || std::is_pointer_v || std::is_enum_v; -template constexpr Type _find_type_in_const_cxx_typeid_map(){ return -1; } +template constexpr Type _find_type_in_const_cxx_typeid_map(){ return Type(-1); } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_str; } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_list; } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_tuple; } @@ -542,11 +546,11 @@ template __T _py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, false>(vm, obj); } template -PyObject* VM::register_user_class(PyObject* mod, StrName name, bool subclass_enabled){ - PyObject* type = new_type_object(mod, name, 0, subclass_enabled); +PyObject* VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled){ + PyObject* type = new_type_object(mod, name, base, subclass_enabled); mod->attr().set(name, type); _cxx_typeid_map[typeid(T)] = PK_OBJ_GET(Type, type); - T::_register(vm, mod, type); + _register(this, mod, type); // check if T is trivially constructible if constexpr(!std::is_default_constructible_v){ if(!type->attr().contains(__new__)){ @@ -559,4 +563,9 @@ PyObject* VM::register_user_class(PyObject* mod, StrName name, bool subclass_ena return type; } +template +PyObject* VM::register_user_class(PyObject* mod, StrName name, Type base, bool subclass_enabled){ + return register_user_class(mod, name, &T::_register, base, subclass_enabled); +} + } // namespace pkpy \ No newline at end of file diff --git a/src/array2d.cpp b/src/array2d.cpp index 41b2c0f1..98beb5a2 100644 --- a/src/array2d.cpp +++ b/src/array2d.cpp @@ -369,7 +369,7 @@ struct Array2dIter{ void add_module_array2d(VM* vm){ PyObject* mod = vm->new_module("array2d"); - vm->register_user_class(mod, "array2d", true); + vm->register_user_class(mod, "array2d", VM::tp_object, true); vm->register_user_class(mod, "_array2d_iter"); vm->bind__iter__(vm->_tp_user(), [](VM* vm, PyObject* _0){ diff --git a/src/cffi.cpp b/src/cffi.cpp index c96b183e..d76f25c4 100644 --- a/src/cffi.cpp +++ b/src/cffi.cpp @@ -161,8 +161,8 @@ void add_module_c(VM* vm){ return vm->None; }); - vm->register_user_class(mod, "void_p", true); - vm->register_user_class(mod, "struct", true); + vm->register_user_class(mod, "void_p", VM::tp_object, true); + vm->register_user_class(mod, "struct", VM::tp_object, true); mod->attr().set("NULL", vm->new_user_object(nullptr)); @@ -188,7 +188,7 @@ void add_module_c(VM* vm){ }); PyObject* type; - Type type_t = -1; + Type type_t; #define BIND_PRIMITIVE(T, CNAME) \ vm->bind_func(mod, CNAME "_", 1, [](VM* vm, ArgsView args){ \ diff --git a/src/codeobject.cpp b/src/codeobject.cpp index c4e738a8..528ed366 100644 --- a/src/codeobject.cpp +++ b/src/codeobject.cpp @@ -25,7 +25,7 @@ namespace pkpy{ } struct PySignalObject: PyObject { - PySignalObject() : PyObject(0) { gc_enabled = false; } + PySignalObject() : PyObject(Type(0)) { gc_enabled = false; } void _obj_gc_mark() override {} }; diff --git a/src/collections.cpp b/src/collections.cpp index 989fe8ca..9fe2c823 100644 --- a/src/collections.cpp +++ b/src/collections.cpp @@ -541,7 +541,7 @@ namespace pkpy void add_module_collections(VM *vm) { PyObject *mod = vm->new_module("collections"); - vm->register_user_class(mod, "deque", true); + vm->register_user_class(mod, "deque", VM::tp_object, true); vm->register_user_class(mod, "_deque_iter"); CodeObject_ code = vm->compile(kPythonLibs_collections, "collections.py", EXEC_MODE); vm->_exec(code, mod); diff --git a/src/linalg.cpp b/src/linalg.cpp index a7abeaa6..f3d57dc4 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -541,10 +541,10 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s void add_module_linalg(VM* vm){ PyObject* linalg = vm->new_module("linalg"); - vm->register_user_class(linalg, "vec2", true); - vm->register_user_class(linalg, "vec3", true); - vm->register_user_class(linalg, "vec4", true); - vm->register_user_class(linalg, "mat3x3", true); + vm->register_user_class(linalg, "vec2", VM::tp_object, true); + vm->register_user_class(linalg, "vec3", VM::tp_object, true); + vm->register_user_class(linalg, "vec4", VM::tp_object, true); + vm->register_user_class(linalg, "mat3x3", VM::tp_object, true); PyObject* float_p = vm->_modules["c"]->attr("float_p"); linalg->attr().set("vec2_p", float_p); diff --git a/src/vm.cpp b/src/vm.cpp index 5d5b1b20..8793e307 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -195,7 +195,7 @@ namespace pkpy{ } PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){ - PyObject* obj = heap._new(tp_type, _all_types.size()); + PyObject* obj = heap._new(tp_type, Type(_all_types.size())); const PyTypeInfo& base_info = _all_types[base]; if(!base_info.subclass_enabled){ Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`"); @@ -735,10 +735,10 @@ void VM::__log_s_data(const char* title) { #endif void VM::__init_builtin_types(){ - _all_types.push_back({heap._new(Type(1), Type(0)), -1, nullptr, "object", true}); - _all_types.push_back({heap._new(Type(1), Type(1)), 0, nullptr, "type", false}); + _all_types.push_back({heap._new(Type(1), Type(0)), Type(-1), nullptr, "object", true}); + _all_types.push_back({heap._new(Type(1), Type(1)), Type(0), nullptr, "type", false}); - auto _new_type = [this](const char* name, Type base=0, bool subclass_enabled=false){ + auto _new_type = [this](const char* name, Type base=Type(0), bool subclass_enabled=false){ PyObject* obj = new_type_object(nullptr, name, base, subclass_enabled); return PK_OBJ_GET(Type, obj); }; @@ -759,10 +759,10 @@ void VM::__init_builtin_types(){ if(tp_bound_method != _new_type("bound_method")) exit(-3); if(tp_super != _new_type("super")) exit(-3); - if(tp_exception != _new_type("Exception", 0, true)) exit(-3); + if(tp_exception != _new_type("Exception", Type(0), true)) exit(-3); if(tp_bytes != _new_type("bytes")) exit(-3); if(tp_mappingproxy != _new_type("mappingproxy")) exit(-3); - if(tp_dict != _new_type("dict", 0, true)) exit(-3); // dict can be subclassed + if(tp_dict != _new_type("dict", Type(0), true)) exit(-3); // dict can be subclassed if(tp_property != _new_type("property")) exit(-3); if(tp_star_wrapper != _new_type("_star_wrapper")) exit(-3);