This commit is contained in:
BLUELOVETH 2023-08-02 14:38:00 +08:00
parent f0ca29a30a
commit 26fe69da28
6 changed files with 26 additions and 10 deletions

View File

@ -67,6 +67,8 @@ a property is a python's `property` that attached to a type instance with a gett
You can use `@property` to create python property or use `vm->property` to create native property.
You can also use `vm->bind_property()`, the new style property binding function.
```cpp
struct Point {
PY_CLASS(Point, test, Point);

View File

@ -134,7 +134,7 @@ void _bind_opaque(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params..
return VAR(self->NAME); \
}));
#define PK_REGISTER_PROPERTY(T, NAME) \
#define PK_REGISTER_PROPERTY(T, NAME, __tp) \
type->attr().set(#NAME, vm->property( \
[](VM* vm, ArgsView args){ \
T& self = _CAST(T&, args[0]); \
@ -145,14 +145,14 @@ void _bind_opaque(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params..
using __NT = decltype(self->get_##NAME()); \
self->set_##NAME(CAST(__NT, args[1])); \
return vm->None; \
}));
}, #__tp));
#define PK_REGISTER_READONLY_PROPERTY(T, NAME) \
#define PK_REGISTER_READONLY_PROPERTY(T, NAME, __tp) \
type->attr().set(#NAME, vm->property( \
[](VM* vm, ArgsView args){ \
T& self = _CAST(T&, args[0]); \
return VAR(self->get_##NAME()); \
}));
}, nullptr, #__tp));
#define PK_REGISTER_CONSTRUCTOR(T, T0) \
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){ \

View File

@ -31,7 +31,8 @@ struct BoundMethod {
struct Property{
PyObject* getter;
PyObject* setter;
Property(PyObject* getter, PyObject* setter) : getter(getter), setter(setter) {}
const char* type_hint;
Property(PyObject* getter, PyObject* setter, const char* type_hint) : getter(getter), setter(setter), type_hint(type_hint) {}
};
struct Range {

View File

@ -201,7 +201,7 @@ public:
return call_method(self, callable, args...);
}
PyObject* property(NativeFuncC fget, NativeFuncC fset=nullptr);
PyObject* property(NativeFuncC fget, NativeFuncC fset=nullptr, const char* type_hint=nullptr);
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
Type _new_type_object(StrName name, Type base=0);
PyObject* _find_type_object(const Str& type);
@ -460,6 +460,7 @@ public:
// new style binding api
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={});
PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={});
PyObject* bind_property(PyObject*, StrName name, const char* type_hint, NativeFuncC fget, NativeFuncC fset=nullptr);
};
DEF_NATIVE_2(Str, tp_str)

View File

@ -1190,13 +1190,19 @@ void init_builtins(VM* _vm) {
/************ property ************/
_vm->bind_constructor<-1>("property", [](VM* vm, ArgsView args) {
if(args.size() == 1+1){
return VAR(Property(args[1], vm->None));
return VAR(Property(args[1], vm->None, nullptr));
}else if(args.size() == 1+2){
return VAR(Property(args[1], args[2]));
return VAR(Property(args[1], args[2], nullptr));
}
vm->TypeError("property() takes at most 2 arguments");
return vm->None;
});
_vm->bind_property(_vm->_t(_vm->tp_property), "type_hint", "str", [](VM* vm, ArgsView args){
Property& self = _CAST(Property&, args[0]);
if(self.type_hint == nullptr) return vm->None;
return VAR(self.type_hint);
});
_vm->_t(_vm->tp_function)->attr().set("__doc__", _vm->property([](VM* vm, ArgsView args) {
Function& func = _CAST(Function&, args[0]);

View File

@ -113,11 +113,11 @@ namespace pkpy{
return nullptr;
}
PyObject* VM::property(NativeFuncC fget, NativeFuncC fset){
PyObject* VM::property(NativeFuncC fget, NativeFuncC fset, const char* type_hint){
PyObject* _0 = heap.gcnew(tp_native_func, NativeFunc(fget, 1, false));
PyObject* _1 = vm->None;
if(fset != nullptr) _1 = heap.gcnew(tp_native_func, NativeFunc(fset, 2, false));
return call(_t(tp_property), _0, _1);
return VAR(Property(_0, _1, type_hint));
}
PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
@ -979,6 +979,12 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
return f_obj;
}
PyObject* VM::bind_property(PyObject* obj, StrName name, const char* type_hint, NativeFuncC fget, NativeFuncC fset){
PyObject* prop = property(fget, fset, type_hint);
obj->attr().set(name, prop);
return prop;
}
void VM::_error(Exception e){
if(callstack.empty()){
e.is_re = false;