mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
...
This commit is contained in:
parent
f0ca29a30a
commit
26fe69da28
@ -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);
|
||||
|
@ -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){ \
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -1190,14 +1190,20 @@ 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]);
|
||||
return VAR(func.decl->docstring);
|
||||
|
10
src/vm.cpp
10
src/vm.cpp
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user