diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 1a93bdee..36e90a29 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -142,14 +142,9 @@ public: stack_no_copy s_view; } _c; - PyObject* None; - PyObject* True; - PyObject* False; - PyObject* NotImplemented; // unused - PyObject* Ellipsis; - PyObject* builtins; // builtins module - PyObject* StopIteration; - PyObject* _main; // __main__ module + PyObject *None, *True, *False, *NotImplemented; + PyObject *StopIteration, *Ellipsis; + PyObject *builtins, *_main; // typeid -> Type std::map _cxx_typeid_map; @@ -311,6 +306,8 @@ 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*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr); + template + PyObject* bind_field(PyObject*, const char*, F T::*); template PyObject* bind_constructor(__T&& type, NativeFuncC fn) { @@ -585,4 +582,32 @@ PyObject* VM::bind_func(PyObject* obj, StrName name, NativeFuncC fn, UserData us return nf; } +template +PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field){ + static_assert(!std::is_reference_v); + std::string_view name_sv(name); int pos = name_sv.find(':'); + if(pos > 0) name_sv = name_sv.substr(0, pos); + auto fget = [](VM* vm, ArgsView args) -> PyObject*{ + T& self = PK_OBJ_GET(T, args[0]); + F T::*field = lambda_get_userdata(args.begin()); + return VAR(self.*field); + }; + PyObject* _0 = heap.gcnew(tp_native_func, fget, 1, false); + PK_OBJ_GET(NativeFunc, _0).set_userdata(field); + PyObject* _1 = vm->None; + if constexpr (!ReadOnly){ + auto fset = [](VM* vm, ArgsView args){ + T& self = PK_OBJ_GET(T, args[0]); + F T::*field = lambda_get_userdata(args.begin()); + self.*field = py_cast(vm, args[1]); + return vm->None; + }; + _1 = heap.gcnew(tp_native_func, fset, 2, false); + PK_OBJ_GET(NativeFunc, _1).set_userdata(field); + } + PyObject* prop = VAR(Property(_0, _1)); + obj->attr().set(StrName(name_sv), prop); + return prop; +} + } // namespace pkpy \ No newline at end of file diff --git a/src/linalg.cpp b/src/linalg.cpp index 499e49ea..fd10127c 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -327,15 +327,15 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s self.m[i][j] = CAST_F(value); }); - PY_FIELD(Mat3x3, "_11", _11) - PY_FIELD(Mat3x3, "_12", _12) - PY_FIELD(Mat3x3, "_13", _13) - PY_FIELD(Mat3x3, "_21", _21) - PY_FIELD(Mat3x3, "_22", _22) - PY_FIELD(Mat3x3, "_23", _23) - PY_FIELD(Mat3x3, "_31", _31) - PY_FIELD(Mat3x3, "_32", _32) - PY_FIELD(Mat3x3, "_33", _33) + vm->bind_field(type, "_11", &Mat3x3::_11); + vm->bind_field(type, "_12", &Mat3x3::_12); + vm->bind_field(type, "_13", &Mat3x3::_13); + vm->bind_field(type, "_21", &Mat3x3::_21); + vm->bind_field(type, "_22", &Mat3x3::_22); + vm->bind_field(type, "_23", &Mat3x3::_23); + vm->bind_field(type, "_31", &Mat3x3::_31); + vm->bind_field(type, "_32", &Mat3x3::_32); + vm->bind_field(type, "_33", &Mat3x3::_33); vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ Mat3x3& self = _CAST(Mat3x3&, _0); diff --git a/src/vm.cpp b/src/vm.cpp index eff8d802..35c37436 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1257,12 +1257,11 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native } PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, NativeFuncC fset){ + std::string_view name_sv(name); int pos = name_sv.find(':'); + if(pos > 0) name_sv = name_sv.substr(0, pos); PyObject* _0 = heap.gcnew(tp_native_func, fget, 1, false); PyObject* _1 = vm->None; if(fset != nullptr) _1 = heap.gcnew(tp_native_func, fset, 2, false); - std::string_view name_sv(name); - int pos = name_sv.find(':'); - if(pos > 0) name_sv = name_sv.substr(0, pos); PyObject* prop = VAR(Property(_0, _1)); obj->attr().set(StrName(name_sv), prop); return prop;