This commit is contained in:
blueloveTH 2024-04-16 23:31:12 +08:00
parent 4083d16a38
commit c4b3d2bb5f
8 changed files with 114 additions and 86 deletions

View File

@ -44,7 +44,6 @@ The features marked with `YES` are supported, and the features marked with `NO`
+ `__iter__`
+ `__next__`
+ `__neg__`
+ `__bool__` (unused)
#### Logical operators

View File

@ -176,12 +176,11 @@ struct CString{
// unary operators
const StrName __repr__ = StrName::get("__repr__");
const StrName __str__ = StrName::get("__str__");
const StrName __hash__ = StrName::get("__hash__"); // unused
const StrName __hash__ = StrName::get("__hash__");
const StrName __len__ = StrName::get("__len__");
const StrName __iter__ = StrName::get("__iter__");
const StrName __next__ = StrName::get("__next__"); // unused
const StrName __neg__ = StrName::get("__neg__"); // unused
const StrName __bool__ = StrName::get("__bool__"); // unused
const StrName __next__ = StrName::get("__next__");
const StrName __neg__ = StrName::get("__neg__");
// logical operators
const StrName __eq__ = StrName::get("__eq__");
const StrName __lt__ = StrName::get("__lt__");

View File

@ -57,7 +57,6 @@ struct PyTypeInfo{
PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__next__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__bool__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__invert__)(VM* vm, PyObject*) = nullptr;
BinaryFuncC m__eq__ = nullptr;
@ -244,60 +243,37 @@ public:
Type _new_type_object(StrName name, Type base=0, bool subclass_enabled=false);
const PyTypeInfo* _inst_type_info(PyObject* obj);
#define BIND_UNARY_SPECIAL(name) \
void bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \
_all_types[type].m##name = f; \
PyObject* nf = bind_method<0>(_t(type), #name, [](VM* vm, ArgsView args){ \
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);\
}); \
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
BIND_UNARY_SPECIAL(__repr__)
BIND_UNARY_SPECIAL(__str__)
BIND_UNARY_SPECIAL(__iter__)
BIND_UNARY_SPECIAL(__next__)
BIND_UNARY_SPECIAL(__neg__)
BIND_UNARY_SPECIAL(__bool__)
BIND_UNARY_SPECIAL(__invert__)
void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__next__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__neg__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__invert__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*));
void bind__len__(Type type, i64 (*f)(VM* vm, PyObject*));
#undef BIND_UNARY_SPECIAL
#define BIND_BINARY_SPECIAL(name) \
void bind##name(Type type, BinaryFuncC f){ \
_all_types[type].m##name = f; \
PyObject* nf = bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
return lambda_get_userdata<BinaryFuncC>(args.begin())(vm, args[0], args[1]);\
}); \
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
void bind__eq__(Type type, BinaryFuncC f);
void bind__lt__(Type type, BinaryFuncC f);
void bind__le__(Type type, BinaryFuncC f);
void bind__gt__(Type type, BinaryFuncC f);
void bind__ge__(Type type, BinaryFuncC f);
void bind__contains__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__eq__)
BIND_BINARY_SPECIAL(__lt__)
BIND_BINARY_SPECIAL(__le__)
BIND_BINARY_SPECIAL(__gt__)
BIND_BINARY_SPECIAL(__ge__)
BIND_BINARY_SPECIAL(__contains__)
void bind__add__(Type type, BinaryFuncC f);
void bind__sub__(Type type, BinaryFuncC f);
void bind__mul__(Type type, BinaryFuncC f);
void bind__truediv__(Type type, BinaryFuncC f);
void bind__floordiv__(Type type, BinaryFuncC f);
void bind__mod__(Type type, BinaryFuncC f);
void bind__pow__(Type type, BinaryFuncC f);
void bind__matmul__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__add__)
BIND_BINARY_SPECIAL(__sub__)
BIND_BINARY_SPECIAL(__mul__)
BIND_BINARY_SPECIAL(__truediv__)
BIND_BINARY_SPECIAL(__floordiv__)
BIND_BINARY_SPECIAL(__mod__)
BIND_BINARY_SPECIAL(__pow__)
BIND_BINARY_SPECIAL(__matmul__)
BIND_BINARY_SPECIAL(__lshift__)
BIND_BINARY_SPECIAL(__rshift__)
BIND_BINARY_SPECIAL(__and__)
BIND_BINARY_SPECIAL(__or__)
BIND_BINARY_SPECIAL(__xor__)
#undef BIND_BINARY_SPECIAL
void bind__lshift__(Type type, BinaryFuncC f);
void bind__rshift__(Type type, BinaryFuncC f);
void bind__and__(Type type, BinaryFuncC f);
void bind__or__(Type type, BinaryFuncC f);
void bind__xor__(Type type, BinaryFuncC f);
void bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*));
void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*));
@ -314,19 +290,12 @@ public:
template<int ARGC, typename __T>
PyObject* bind_constructor(__T&& type, NativeFuncC fn) {
static_assert(ARGC==-1 || ARGC>=1);
return bind_func<ARGC>(std::forward<__T>(type), "__new__", fn);
}
template<typename T, typename __T>
PyObject* bind_default_constructor(__T&& type) {
return bind_constructor<1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
return vm->heap.gcnew<T>(PK_OBJ_GET(Type, args[0]), T());
});
return bind_func<ARGC>(std::forward<__T>(type), __new__, fn);
}
template<typename T, typename __T>
PyObject* bind_notimplemented_constructor(__T&& type) {
return bind_constructor<-1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
return bind_func<-1>(std::forward<__T>(type), __new__, [](VM* vm, ArgsView args){
vm->NotImplementedError();
return vm->None;
});
@ -357,19 +326,8 @@ public:
void KeyError(PyObject* obj){ _builtin_error("KeyError", obj); }
void ImportError(const Str& msg){ _builtin_error("ImportError", msg); }
void BinaryOptError(const char* op, PyObject* _0, PyObject* _1) {
StrName name_0 = _type_name(vm, _tp(_0));
StrName name_1 = _type_name(vm, _tp(_1));
TypeError(_S("unsupported operand type(s) for ", op, ": ", name_0.escape(), " and ", name_1.escape()));
}
void AttributeError(PyObject* obj, StrName name){
if(isinstance(obj, vm->tp_type)){
_builtin_error("AttributeError", _S("type object ", _type_name(vm, PK_OBJ_GET(Type, obj)).escape(), " has no attribute ", name.escape()));
}else{
_builtin_error("AttributeError", _S(_type_name(vm, _tp(obj)).escape(), " object has no attribute ", name.escape()));
}
}
void BinaryOptError(const char* op, PyObject* _0, PyObject* _1);
void AttributeError(PyObject* obj, StrName name);
void AttributeError(const Str& msg){ _builtin_error("AttributeError", msg); }
void check_type(PyObject* obj, Type type){
@ -447,11 +405,11 @@ public:
PyObject* _format_string(Str, PyObject*);
void setattr(PyObject* obj, StrName name, PyObject* value);
template<int ARGC>
PyObject* bind_method(Type, Str, NativeFuncC);
PyObject* bind_method(Type, StrName, NativeFuncC);
template<int ARGC>
PyObject* bind_method(PyObject*, Str, NativeFuncC);
PyObject* bind_method(PyObject*, StrName, NativeFuncC);
template<int ARGC>
PyObject* bind_func(PyObject*, Str, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
PyObject* bind_func(PyObject*, StrName, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
void _error(PyObject*);
PyObject* _run_top_frame();
void post_init();
@ -615,20 +573,20 @@ __T _py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, false>(vm,
template<int ARGC>
PyObject* VM::bind_method(Type type, Str name, NativeFuncC fn) {
PyObject* VM::bind_method(Type type, StrName name, NativeFuncC fn) {
PyObject* nf = VAR(NativeFunc(fn, ARGC, true));
_t(type)->attr().set(name, nf);
return nf;
}
template<int ARGC>
PyObject* VM::bind_method(PyObject* obj, Str name, NativeFuncC fn) {
PyObject* VM::bind_method(PyObject* obj, StrName name, NativeFuncC fn) {
check_type(obj, tp_type);
return bind_method<ARGC>(PK_OBJ_GET(Type, obj), name, fn);
}
template<int ARGC>
PyObject* VM::bind_func(PyObject* obj, Str name, NativeFuncC fn, UserData userdata, BindType bt) {
PyObject* VM::bind_func(PyObject* obj, StrName name, NativeFuncC fn, UserData userdata, BindType bt) {
PyObject* nf = VAR(NativeFunc(fn, ARGC, false));
PK_OBJ_GET(NativeFunc, nf).set_userdata(userdata);
switch(bt){

View File

@ -3,7 +3,7 @@
namespace pkpy{
void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
vm->bind_func<2>(type, __new__, [](VM* vm, ArgsView args){
Type cls = PK_OBJ_GET(Type, args[0]);
i64 addr = CAST(i64, args[1]);
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr));

View File

@ -264,7 +264,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
PY_STRUCT_LIKE(Mat3x3)
vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
vm->bind_func<-1>(type, __new__, [](VM* vm, ArgsView args){
if(args.size() == 1+0) return vm->heap.gcnew<Mat3x3>(PK_OBJ_GET(Type, args[0]), Mat3x3::zeros());
if(args.size() == 1+1){
const List& list = CAST(List&, args[1]);

View File

@ -266,7 +266,10 @@ struct LineProfilerW{
LineProfiler profiler;
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_default_constructor<LineProfilerW>(type);
vm->bind_func<1>(type, __new__, [](VM* vm, ArgsView args){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->heap.gcnew<LineProfilerW>(cls);
});
vm->bind(type, "add_function(self, func)", [](VM* vm, ArgsView args){
LineProfilerW& self = PK_OBJ_GET(LineProfilerW, args[0]);

View File

@ -11,7 +11,10 @@ struct Random{
}
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_default_constructor<Random>(type);
vm->bind_func<1>(type, __new__, [](VM* vm, ArgsView args){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->heap.gcnew<Random>(cls);
});
vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) {
Random& self = _CAST(Random&, args[0]);

View File

@ -1220,6 +1220,20 @@ void VM::_builtin_error(StrName type){ _error(call(builtins->attr(type))); }
void VM::_builtin_error(StrName type, PyObject* arg){ _error(call(builtins->attr(type), arg)); }
void VM::_builtin_error(StrName type, const Str& msg){ _builtin_error(type, VAR(msg)); }
void VM::BinaryOptError(const char* op, PyObject* _0, PyObject* _1) {
StrName name_0 = _type_name(vm, _tp(_0));
StrName name_1 = _type_name(vm, _tp(_1));
TypeError(_S("unsupported operand type(s) for ", op, ": ", name_0.escape(), " and ", name_1.escape()));
}
void VM::AttributeError(PyObject* obj, StrName name){
if(isinstance(obj, vm->tp_type)){
_builtin_error("AttributeError", _S("type object ", _type_name(vm, PK_OBJ_GET(Type, obj)).escape(), " has no attribute ", name.escape()));
}else{
_builtin_error("AttributeError", _S(_type_name(vm, _tp(obj)).escape(), " object has no attribute ", name.escape()));
}
}
void VM::_error(PyObject* e_obj){
PK_ASSERT(isinstance(e_obj, tp_exception))
Exception& e = PK_OBJ_GET(Exception, e_obj);
@ -1293,6 +1307,23 @@ void VM::bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)){
PK_OBJ_GET(NativeFunc, nf).set_userdata(f);
}
#define BIND_UNARY_SPECIAL(name) \
void VM::bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \
_all_types[type].m##name = f; \
PyObject* nf = bind_method<0>(_t(type), #name, [](VM* vm, ArgsView args){ \
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);\
}); \
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
BIND_UNARY_SPECIAL(__repr__)
BIND_UNARY_SPECIAL(__str__)
BIND_UNARY_SPECIAL(__iter__)
BIND_UNARY_SPECIAL(__next__)
BIND_UNARY_SPECIAL(__neg__)
BIND_UNARY_SPECIAL(__invert__)
#undef BIND_UNARY_SPECIAL
void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
PyObject* obj = _t(type);
_all_types[type].m__hash__ = f;
@ -1313,6 +1344,41 @@ void VM::bind__len__(Type type, i64 (*f)(VM*, PyObject*)){
PK_OBJ_GET(NativeFunc, nf).set_userdata(f);
}
#define BIND_BINARY_SPECIAL(name) \
void VM::bind##name(Type type, BinaryFuncC f){ \
_all_types[type].m##name = f; \
PyObject* nf = bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
return lambda_get_userdata<BinaryFuncC>(args.begin())(vm, args[0], args[1]);\
}); \
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
BIND_BINARY_SPECIAL(__eq__)
BIND_BINARY_SPECIAL(__lt__)
BIND_BINARY_SPECIAL(__le__)
BIND_BINARY_SPECIAL(__gt__)
BIND_BINARY_SPECIAL(__ge__)
BIND_BINARY_SPECIAL(__contains__)
BIND_BINARY_SPECIAL(__add__)
BIND_BINARY_SPECIAL(__sub__)
BIND_BINARY_SPECIAL(__mul__)
BIND_BINARY_SPECIAL(__truediv__)
BIND_BINARY_SPECIAL(__floordiv__)
BIND_BINARY_SPECIAL(__mod__)
BIND_BINARY_SPECIAL(__pow__)
BIND_BINARY_SPECIAL(__matmul__)
BIND_BINARY_SPECIAL(__lshift__)
BIND_BINARY_SPECIAL(__rshift__)
BIND_BINARY_SPECIAL(__and__)
BIND_BINARY_SPECIAL(__or__)
BIND_BINARY_SPECIAL(__xor__)
#undef BIND_BINARY_SPECIAL
void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
ok = false;
i64 hash = vm->py_hash(key);