瀏覽代碼

add `bind_field<>`

blueloveTH 1 年之前
父節點
當前提交
dd5a5e096f
共有 3 個文件被更改,包括 44 次插入20 次删除
  1. 33 8
      include/pocketpy/vm.h
  2. 9 9
      src/linalg.cpp
  3. 2 3
      src/vm.cpp

+ 33 - 8
include/pocketpy/vm.h

@@ -142,14 +142,9 @@ public:
         stack_no_copy<ArgsView> s_view;
         stack_no_copy<ArgsView> s_view;
     } _c;
     } _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
     // typeid -> Type
     std::map<const std::type_index, Type> _cxx_typeid_map;
     std::map<const std::type_index, Type> _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*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
     PyObject* bind(PyObject*, 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);
     PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
+    template<typename T, typename F, bool ReadOnly=false>
+    PyObject* bind_field(PyObject*, const char*, F T::*);
 
 
     template<int ARGC, typename __T>
     template<int ARGC, typename __T>
     PyObject* bind_constructor(__T&& type, NativeFuncC fn) {
     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;
     return nf;
 }
 }
 
 
+template<typename T, typename F, bool ReadOnly>
+PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field){
+    static_assert(!std::is_reference_v<F>);
+    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<F T::*>(args.begin());
+        return VAR(self.*field);
+    };
+    PyObject* _0 = heap.gcnew<NativeFunc>(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<F T::*>(args.begin());
+            self.*field = py_cast<F>(vm, args[1]);
+            return vm->None;
+        };
+        _1 = heap.gcnew<NativeFunc>(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
 }   // namespace pkpy

+ 9 - 9
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);
             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){
         vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
             Mat3x3& self = _CAST(Mat3x3&, _0);
             Mat3x3& self = _CAST(Mat3x3&, _0);

+ 2 - 3
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){
 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<NativeFunc>(tp_native_func, fget, 1, false);
     PyObject* _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1, false);
     PyObject* _1 = vm->None;
     PyObject* _1 = vm->None;
     if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2, false);
     if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(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));
     PyObject* prop = VAR(Property(_0, _1));
     obj->attr().set(StrName(name_sv), prop);
     obj->attr().set(StrName(name_sv), prop);
     return prop;
     return prop;