diff --git a/src/cffi.h b/src/cffi.h index 08e86b88..c90c0a31 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -72,345 +72,36 @@ auto native_proxy_callable(Ret(T::*func)(Params...)) { return NativeProxyMethod(func); } +struct VoidP{ + PY_CLASS(VoidP, c, void_p) -template -constexpr int type_index() { return 0; } -template<> constexpr int type_index() { return 1; } -template<> constexpr int type_index() { return 2; } -template<> constexpr int type_index() { return 3; } -template<> constexpr int type_index() { return 4; } -template<> constexpr int type_index() { return 5; } -template<> constexpr int type_index() { return 6; } -template<> constexpr int type_index() { return 7; } -template<> constexpr int type_index() { return 8; } -template<> constexpr int type_index() { return 9; } -template<> constexpr int type_index() { return 10; } -template<> constexpr int type_index() { return 11; } -template<> constexpr int type_index() { return 12; } -template<> constexpr int type_index() { return 13; } -template<> constexpr int type_index() { return 14; } - -template -struct TypeId{ inline static int id; }; - -struct TypeInfo; - -struct MemberInfo{ - const TypeInfo* type; - int offset; -}; - -struct TypeInfo{ - const char* name; - int size; - int index; - std::map members; -}; - -struct Vec2 { - float x, y; -}; - -struct TypeDB{ - std::vector _by_index; - std::map _by_name; - - template - void register_type(const char name[], std::map&& members){ - TypeInfo ti; - ti.name = name; - if constexpr(std::is_same_v) ti.size = 1; - else ti.size = sizeof(T); - ti.members = std::move(members); - TypeId::id = ti.index = _by_index.size()+1; // 0 is reserved for NULL - _by_name[name] = ti.index; - _by_index.push_back(ti); - } - - const TypeInfo* get(int index) const { - return index == 0 ? nullptr : &_by_index[index-1]; - } - - const TypeInfo* get(std::string_view name) const { - auto it = _by_name.find(name); - if(it == _by_name.end()) return nullptr; - return get(it->second); - } - - const TypeInfo* get(const Str& s) const { - return get(s.sv()); - } - - template - const TypeInfo* get() const { - return get(TypeId>::id); - } -}; - -static TypeDB _type_db; - - -inline static auto ___x = [](){ - #define REGISTER_BASIC_TYPE(T) _type_db.register_type(#T, {}); - _type_db.register_type("void", {}); - REGISTER_BASIC_TYPE(char); - REGISTER_BASIC_TYPE(short); - REGISTER_BASIC_TYPE(int); - REGISTER_BASIC_TYPE(long); - REGISTER_BASIC_TYPE(long long); - REGISTER_BASIC_TYPE(unsigned char); - REGISTER_BASIC_TYPE(unsigned short); - REGISTER_BASIC_TYPE(unsigned int); - REGISTER_BASIC_TYPE(unsigned long); - REGISTER_BASIC_TYPE(unsigned long long); - REGISTER_BASIC_TYPE(float); - REGISTER_BASIC_TYPE(double); - REGISTER_BASIC_TYPE(bool); - #undef REGISTER_BASIC_TYPE - - _type_db.register_type("Vec2", { - {"x", { _type_db.get(), offsetof(Vec2, x) }}, - {"y", { _type_db.get(), offsetof(Vec2, y) }}, - }); - return 0; -}(); - -struct Pointer{ - PY_CLASS(Pointer, c, _ptr) - - const TypeInfo* ctype; // this is immutable - int level; // level of pointer - char* ptr; - - i64 unit_size() const { - return level == 1 ? ctype->size : sizeof(void*); - } - - Pointer() : ctype(_type_db.get()), level(1), ptr(nullptr) {} - Pointer(const TypeInfo* ctype, int level, char* ptr): ctype(ctype), level(level), ptr(ptr) {} - Pointer(const TypeInfo* ctype, char* ptr): ctype(ctype), level(1), ptr(ptr) {} - - Pointer operator+(i64 offset) const { - return Pointer(ctype, level, ptr+offset*unit_size()); - } - - Pointer operator-(i64 offset) const { - return Pointer(ctype, level, ptr-offset*unit_size()); - } + void* ptr; + VoidP(void* ptr): ptr(ptr){} static void _register(VM* vm, PyObject* mod, PyObject* type){ - vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); + vm->bind_static_method<1>(type, "__new__", CPP_NOT_IMPLEMENTED()); - vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); + vm->bind_static_method<1>(type, "__repr__", [](VM* vm, const Args& args){ + VoidP& self = CAST(VoidP&, args[0]); std::stringstream ss; - ss << "<" << self.ctype->name; - for(int i=0; i"; + ss << ""; return VAR(ss.str()); }); - - vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - return VAR_T(Pointer, self + CAST(i64, args[1])); - }); - - vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - return VAR_T(Pointer, self - CAST(i64, args[1])); - }); - - vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - Pointer& other = CAST(Pointer&, args[1]); - return VAR(self.ptr == other.ptr); - }); - - vm->bind_method<1>(type, "__ne__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - Pointer& other = CAST(Pointer&, args[1]); - return VAR(self.ptr != other.ptr); - }); - - vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - i64 index = CAST(i64, args[1]); - return (self+index).get(vm); - }); - - vm->bind_method<2>(type, "__setitem__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - i64 index = CAST(i64, args[1]); - (self+index).set(vm, args[2]); - return vm->None; - }); - - vm->bind_method<1>(type, "__getattr__", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - const Str& name = CAST(Str&, args[1]); - return VAR_T(Pointer, self._to(vm, name)); - }); - - vm->bind_method<0>(type, "get", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - return self.get(vm); - }); - - vm->bind_method<1>(type, "set", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - self.set(vm, args[1]); - return vm->None; - }); - } - - template - T& ref() noexcept { return *reinterpret_cast(ptr); } - - PyObject* get(VM* vm){ - if(level > 1) return VAR_T(Pointer, ctype, level-1, ref()); - switch(ctype->index){ -#define CASE(T) case type_index(): return VAR(ref()) - case type_index(): vm->ValueError("cannot get void*"); break; - CASE(char); - CASE(short); - CASE(int); - CASE(long); - CASE(long long); - CASE(unsigned char); - CASE(unsigned short); - CASE(unsigned int); - CASE(unsigned long); - CASE(unsigned long long); - CASE(float); - CASE(double); - CASE(bool); -#undef CASE - } - return VAR_T(Pointer, *this); - } - - void set(VM* vm, PyObject* val){ - if(level > 1) { - Pointer& p = CAST(Pointer&, val); - ref() = p.ptr; // We don't check the type, just copy the underlying address - return; - } - switch(ctype->index){ -#define CASE(T1, T2) case type_index(): ref() = CAST(T2, val); break - case type_index(): vm->ValueError("cannot set void*"); break; - CASE(char, i64); - CASE(short, i64); - CASE(int, i64); - CASE(long, i64); - CASE(long long, i64); - CASE(unsigned char, i64); - CASE(unsigned short, i64); - CASE(unsigned int, i64); - CASE(unsigned long, i64); - CASE(unsigned long long, i64); - CASE(float, f64); - CASE(double, f64); - CASE(bool, bool); -#undef CASE - default: FATAL_ERROR(); - } - } - - Pointer _to(VM* vm, StrName name){ - auto it = ctype->members.find(name); - if(it == ctype->members.end()){ - vm->AttributeError(fmt("struct '", ctype->name, "' has no member ", name.escape())); - } - const MemberInfo& info = it->second; - return {info.type, level, ptr+info.offset}; - } -}; - - -struct CType{ - PY_CLASS(CType, c, ctype) - - const TypeInfo* type; - - CType() : type(_type_db.get()) {} - CType(const TypeInfo* type) : type(type) {} - - static void _register(VM* vm, PyObject* mod, PyObject* type){ - vm->bind_static_method<1>(type, "__new__", [](VM* vm, ArgsView args) { - const Str& name = CAST(Str&, args[0]); - const TypeInfo* type = _type_db.get(name); - if(type == nullptr) vm->TypeError("unknown type: " + name.escape()); - return VAR_T(CType, type); - }); } }; inline void add_module_c(VM* vm){ PyObject* mod = vm->new_module("c"); - Pointer::register_class(vm, mod); - CType::register_class(vm, mod); - - vm->setattr(mod, "nullptr", VAR_T(Pointer)); - - vm->bind_func<1>(mod, "malloc", [](VM* vm, ArgsView args) { - i64 size = CAST(i64, args[0]); - return VAR_T(Pointer, _type_db.get(), (char*)malloc(size)); - }); - - vm->bind_func<1>(mod, "free", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - free(self.ptr); - return vm->None; - }); - - vm->bind_func<3>(mod, "memcpy", [](VM* vm, ArgsView args) { - Pointer& dst = CAST(Pointer&, args[0]); - Pointer& src = CAST(Pointer&, args[1]); - i64 size = CAST(i64, args[2]); - memcpy(dst.ptr, src.ptr, size); - return vm->None; - }); - - vm->bind_func<2>(mod, "cast", [](VM* vm, ArgsView args) { - Pointer& self = CAST(Pointer&, args[0]); - const Str& name = CAST(Str&, args[1]); - int level = 0; - for(int i=name.length()-1; i>=0; i--){ - if(name[i] == '*') level++; - else break; - } - if(level == 0) vm->TypeError("expect a pointer type, such as 'int*'"); - Str type_s = name.substr(0, name.length()-level); - const TypeInfo* type = _type_db.get(type_s); - if(type == nullptr) vm->TypeError("unknown type: " + type_s.escape()); - return VAR_T(Pointer, type, level, self.ptr); - }); - - vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args) { - const Str& name = CAST(Str&, args[0]); - if(name.index("*") != -1) return VAR(sizeof(void*)); - const TypeInfo* type = _type_db.get(name); - if(type == nullptr) vm->TypeError("unknown type: " + name.escape()); - return VAR(type->size); - }); - - vm->bind_func<3>(mod, "memset", [](VM* vm, ArgsView args) { - Pointer& dst = CAST(Pointer&, args[0]); - i64 val = CAST(i64, args[1]); - i64 size = CAST(i64, args[2]); - memset(dst.ptr, (int)val, size); - return vm->None; - }); + VoidP::register_class(vm, mod); } inline PyObject* py_var(VM* vm, void* p){ - return VAR_T(Pointer, _type_db.get(), (char*)p); + return VAR_T(VoidP, p); } inline PyObject* py_var(VM* vm, char* p){ - return VAR_T(Pointer, _type_db.get(), (char*)p); + return VAR_T(VoidP, p); } - /***********************************************/ template @@ -434,20 +125,7 @@ struct pointer { template T py_pointer_cast(VM* vm, PyObject* var){ static_assert(std::is_pointer_v); - Pointer& p = CAST(Pointer&, var); - const TypeInfo* type = _type_db.get::baseT>(); - const int level = pointer::level; - if(p.ctype != type || p.level != level){ - vm->TypeError("invalid pointer cast"); - } + VoidP& p = CAST(VoidP&, var); return reinterpret_cast(p.ptr); } - -template -std::enable_if_t>, PyObject*> -py_var(VM* vm, T p){ - const TypeInfo* type = _type_db.get::baseT>(); - if(type == nullptr) type = _type_db.get(); - return VAR_T(Pointer, type, pointer::level, (char*)p); -} } // namespace pkpy \ No newline at end of file diff --git a/src/common.h b/src/common.h index 61f9a581..4a55f012 100644 --- a/src/common.h +++ b/src/common.h @@ -35,7 +35,7 @@ #define DEBUG_NO_BUILTIN_MODULES 0 #define DEBUG_EXTRA_CHECK 1 #define DEBUG_DIS_EXEC 1 -#define DEBUG_CEVAL_STEP 1 +#define DEBUG_CEVAL_STEP 0 #define DEBUG_CEVAL_STEP_MIN 0 #define DEBUG_FULL_EXCEPTION 0 #define DEBUG_MEMORY_POOL 0 diff --git a/src/obj.h b/src/obj.h index b502b991..4438ec09 100644 --- a/src/obj.h +++ b/src/obj.h @@ -198,7 +198,6 @@ template struct is_py_class> : s template void _check_py_class(VM*, PyObject*); template T py_pointer_cast(VM*, PyObject*); -template T py_value_cast(VM*, PyObject*); template __T py_cast(VM* vm, PyObject* obj) { @@ -208,9 +207,7 @@ __T py_cast(VM* vm, PyObject* obj) { }else if constexpr(is_py_class::value){ _check_py_class(vm, obj); return OBJ_GET(T, obj); - }else if constexpr(std::is_pod_v){ - return py_value_cast(vm, obj); - }else{ + }else { return Discarded(); } } diff --git a/src/pocketpy.h b/src/pocketpy.h index ff5264db..c1cbb3d9 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -772,7 +772,7 @@ inline void VM::post_init(){ add_module_random(this); add_module_io(this); add_module_os(this); - // add_module_c(this); + add_module_c(this); add_module_gc(this); for(const char* name: {"this", "functools", "collections", "heapq", "bisect"}){