diff --git a/include/pocketpy/bindings.h b/include/pocketpy/bindings.h index dd0850cb..713105e7 100644 --- a/include/pocketpy/bindings.h +++ b/include/pocketpy/bindings.h @@ -82,8 +82,20 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){ }, \ [](VM* vm, ArgsView args){ \ T& self = PK_OBJ_GET(T, args[0]); \ - self.REF()->EXPR = CAST(decltype(self.REF()->EXPR), args[1]); \ - return vm->None; \ + self.REF()->EXPR = CAST(decltype(self.REF()->EXPR), args[1]); \ + return vm->None; \ + }); + +#define PY_FIELD_VIRTUAL(T, NAME, REF, EXPR) \ + vm->bind_property(type, NAME, \ + [](VM* vm, ArgsView args){ \ + T& self = *(reinterpret_cast(args[0]->_value_ptr())); \ + return VAR(self.REF()->EXPR); \ + }, \ + [](VM* vm, ArgsView args){ \ + T& self = *(reinterpret_cast(args[0]->_value_ptr())); \ + self.REF()->EXPR = CAST(decltype(self.REF()->EXPR), args[1]); \ + return vm->None; \ }); #define PY_READONLY_FIELD(T, NAME, REF, EXPR) \ @@ -93,6 +105,13 @@ void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){ return VAR(self.REF()->EXPR); \ }); +#define PY_READONLY_FIELD_VIRTUAL(T, NAME, REF, EXPR) \ + vm->bind_property(type, NAME, \ + [](VM* vm, ArgsView args){ \ + T& self = *(reinterpret_cast(args[0]->_value_ptr())); \ + return VAR(self.REF()->EXPR); \ + }); + #define PY_PROPERTY(T, NAME, REF, FGET, FSET) \ vm->bind_property(type, NAME, \ [](VM* vm, ArgsView args){ \ diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 8a073680..3dca8979 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -201,6 +201,10 @@ struct Py_ final: PyObject { if(_value._module != nullptr) PK_OBJ_MARK(_value._module); if(_value._closure != nullptr) gc_mark_namedict(*_value._closure); } + + void* _value_ptr() override { + return &_value; + } }; template<> @@ -215,6 +219,9 @@ struct Py_ final: PyObject { _value.decl->_gc_mark(); } } + void* _value_ptr() override { + return &_value; + } }; template diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index b578fa7e..dab44d1a 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -112,7 +112,9 @@ struct PyObject{ bool is_attr_valid() const noexcept { return _attr != nullptr; } NameDict& attr() noexcept { return *_attr; } PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; } + virtual void _obj_gc_mark() = 0; + virtual void* _value_ptr() = 0; PyObject(Type type) : type(type), _attr(nullptr) {} @@ -128,6 +130,7 @@ struct PySignalObject: PyObject { gc.enabled = false; } void _obj_gc_mark() override {} + void* _value_ptr() override { return nullptr; } }; inline PyObject* const PY_NULL = new PySignalObject(); @@ -172,6 +175,8 @@ struct Py_ final: PyObject { _value._gc_mark(); } } + + void* _value_ptr() override { return &_value; } template Py_(Type type, Args&&... args) : PyObject(type), _value(std::forward(args)...) { } @@ -255,6 +260,7 @@ struct Py_ final: PyObject { i64 _value; Py_(Type type, i64 val): PyObject(type), _value(val) {} void _obj_gc_mark() override {} + void* _value_ptr() override { return &_value; } }; inline bool try_cast_int(PyObject* obj, i64* val) noexcept { @@ -278,6 +284,7 @@ struct Py_ final: PyObject { void _obj_gc_mark() override { for(PyObject* obj: _value) PK_OBJ_MARK(obj); } + void* _value_ptr() override { return &_value; } }; template<> @@ -289,6 +296,7 @@ struct Py_ final: PyObject { void _obj_gc_mark() override { for(PyObject* obj: _value) PK_OBJ_MARK(obj); } + void* _value_ptr() override { return &_value; } }; template<> @@ -298,6 +306,7 @@ struct Py_ final: PyObject { void _obj_gc_mark() override { PK_OBJ_MARK(_value.obj); } + void* _value_ptr() override { return &_value; } }; template<> @@ -308,6 +317,7 @@ struct Py_ final: PyObject { PK_OBJ_MARK(_value.self); PK_OBJ_MARK(_value.func); } + void* _value_ptr() override { return &_value; } }; template<> @@ -317,6 +327,7 @@ struct Py_ final: PyObject { void _obj_gc_mark() override { PK_OBJ_MARK(_value.obj); } + void* _value_ptr() override { return &_value; } }; template<> @@ -327,6 +338,7 @@ struct Py_ final: PyObject { PK_OBJ_MARK(_value.getter); PK_OBJ_MARK(_value.setter); } + void* _value_ptr() override { return &_value; } }; template<> @@ -338,6 +350,7 @@ struct Py_ final: PyObject { PK_OBJ_MARK(_value.stop); PK_OBJ_MARK(_value.step); } + void* _value_ptr() override { return &_value; } }; template<> @@ -348,6 +361,7 @@ struct Py_ final: PyObject { void _obj_gc_mark() override { PK_OBJ_MARK(_value.first); } + void* _value_ptr() override { return &_value; } }; template<> @@ -356,6 +370,7 @@ struct Py_ final: PyObject { enable_instance_dict(); } void _obj_gc_mark() override {} + void* _value_ptr() override { return nullptr; } }; template<> @@ -365,6 +380,7 @@ struct Py_ final: PyObject { enable_instance_dict(kTypeAttrLoadFactor); } void _obj_gc_mark() override {} + void* _value_ptr() override { return &_value; } }; template<> @@ -373,6 +389,7 @@ struct Py_ final: PyObject { enable_instance_dict(kTypeAttrLoadFactor); } void _obj_gc_mark() override {} + void* _value_ptr() override { return nullptr; } }; } // namespace pkpy \ No newline at end of file