mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-24 13:30:18 +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 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
|
```cpp
|
||||||
struct Point {
|
struct Point {
|
||||||
PY_CLASS(Point, test, 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); \
|
return VAR(self->NAME); \
|
||||||
}));
|
}));
|
||||||
|
|
||||||
#define PK_REGISTER_PROPERTY(T, NAME) \
|
#define PK_REGISTER_PROPERTY(T, NAME, __tp) \
|
||||||
type->attr().set(#NAME, vm->property( \
|
type->attr().set(#NAME, vm->property( \
|
||||||
[](VM* vm, ArgsView args){ \
|
[](VM* vm, ArgsView args){ \
|
||||||
T& self = _CAST(T&, args[0]); \
|
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()); \
|
using __NT = decltype(self->get_##NAME()); \
|
||||||
self->set_##NAME(CAST(__NT, args[1])); \
|
self->set_##NAME(CAST(__NT, args[1])); \
|
||||||
return vm->None; \
|
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( \
|
type->attr().set(#NAME, vm->property( \
|
||||||
[](VM* vm, ArgsView args){ \
|
[](VM* vm, ArgsView args){ \
|
||||||
T& self = _CAST(T&, args[0]); \
|
T& self = _CAST(T&, args[0]); \
|
||||||
return VAR(self->get_##NAME()); \
|
return VAR(self->get_##NAME()); \
|
||||||
}));
|
}, nullptr, #__tp));
|
||||||
|
|
||||||
#define PK_REGISTER_CONSTRUCTOR(T, T0) \
|
#define PK_REGISTER_CONSTRUCTOR(T, T0) \
|
||||||
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){ \
|
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){ \
|
||||||
|
|||||||
@ -31,7 +31,8 @@ struct BoundMethod {
|
|||||||
struct Property{
|
struct Property{
|
||||||
PyObject* getter;
|
PyObject* getter;
|
||||||
PyObject* setter;
|
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 {
|
struct Range {
|
||||||
|
|||||||
@ -201,7 +201,7 @@ public:
|
|||||||
return call_method(self, callable, args...);
|
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);
|
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
|
||||||
Type _new_type_object(StrName name, Type base=0);
|
Type _new_type_object(StrName name, Type base=0);
|
||||||
PyObject* _find_type_object(const Str& type);
|
PyObject* _find_type_object(const Str& type);
|
||||||
@ -460,6 +460,7 @@ public:
|
|||||||
// new style binding api
|
// new style binding api
|
||||||
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={});
|
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={});
|
||||||
PyObject* bind(PyObject*, 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)
|
DEF_NATIVE_2(Str, tp_str)
|
||||||
|
|||||||
@ -1190,14 +1190,20 @@ void init_builtins(VM* _vm) {
|
|||||||
/************ property ************/
|
/************ property ************/
|
||||||
_vm->bind_constructor<-1>("property", [](VM* vm, ArgsView args) {
|
_vm->bind_constructor<-1>("property", [](VM* vm, ArgsView args) {
|
||||||
if(args.size() == 1+1){
|
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){
|
}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");
|
vm->TypeError("property() takes at most 2 arguments");
|
||||||
return vm->None;
|
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) {
|
_vm->_t(_vm->tp_function)->attr().set("__doc__", _vm->property([](VM* vm, ArgsView args) {
|
||||||
Function& func = _CAST(Function&, args[0]);
|
Function& func = _CAST(Function&, args[0]);
|
||||||
return VAR(func.decl->docstring);
|
return VAR(func.decl->docstring);
|
||||||
|
|||||||
10
src/vm.cpp
10
src/vm.cpp
@ -113,11 +113,11 @@ namespace pkpy{
|
|||||||
return nullptr;
|
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* _0 = heap.gcnew(tp_native_func, NativeFunc(fget, 1, false));
|
||||||
PyObject* _1 = vm->None;
|
PyObject* _1 = vm->None;
|
||||||
if(fset != nullptr) _1 = heap.gcnew(tp_native_func, NativeFunc(fset, 2, false));
|
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){
|
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;
|
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){
|
void VM::_error(Exception e){
|
||||||
if(callstack.empty()){
|
if(callstack.empty()){
|
||||||
e.is_re = false;
|
e.is_re = false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user