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__` + `__iter__`
+ `__next__` + `__next__`
+ `__neg__` + `__neg__`
+ `__bool__` (unused)
#### Logical operators #### Logical operators

View File

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

View File

@ -57,7 +57,6 @@ struct PyTypeInfo{
PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__next__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__next__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__neg__)(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; PyObject* (*m__invert__)(VM* vm, PyObject*) = nullptr;
BinaryFuncC m__eq__ = nullptr; BinaryFuncC m__eq__ = nullptr;
@ -244,60 +243,37 @@ public:
Type _new_type_object(StrName name, Type base=0, bool subclass_enabled=false); Type _new_type_object(StrName name, Type base=0, bool subclass_enabled=false);
const PyTypeInfo* _inst_type_info(PyObject* obj); const PyTypeInfo* _inst_type_info(PyObject* obj);
#define BIND_UNARY_SPECIAL(name) \ void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \ void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*));
_all_types[type].m##name = f; \ void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
PyObject* nf = bind_method<0>(_t(type), #name, [](VM* vm, ArgsView args){ \ void bind__next__(Type type, PyObject* (*f)(VM*, PyObject*));
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);\ void bind__neg__(Type type, PyObject* (*f)(VM*, PyObject*));
}); \ void bind__invert__(Type type, PyObject* (*f)(VM*, PyObject*));
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__hash__(Type type, i64 (*f)(VM* vm, PyObject*)); void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*));
void bind__len__(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__eq__(Type type, BinaryFuncC f);
void bind##name(Type type, BinaryFuncC f){ \ void bind__lt__(Type type, BinaryFuncC f);
_all_types[type].m##name = f; \ void bind__le__(Type type, BinaryFuncC f);
PyObject* nf = bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \ void bind__gt__(Type type, BinaryFuncC f);
return lambda_get_userdata<BinaryFuncC>(args.begin())(vm, args[0], args[1]);\ void bind__ge__(Type type, BinaryFuncC f);
}); \ void bind__contains__(Type type, BinaryFuncC f);
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
BIND_BINARY_SPECIAL(__eq__) void bind__add__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__lt__) void bind__sub__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__le__) void bind__mul__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__gt__) void bind__truediv__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__ge__) void bind__floordiv__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__contains__) 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__) void bind__lshift__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__sub__) void bind__rshift__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__mul__) void bind__and__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__truediv__) void bind__or__(Type type, BinaryFuncC f);
BIND_BINARY_SPECIAL(__floordiv__) void bind__xor__(Type type, BinaryFuncC f);
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__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*)); void bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*));
void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*)); void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*));
@ -314,19 +290,12 @@ public:
template<int ARGC, typename __T> template<int ARGC, typename __T>
PyObject* bind_constructor(__T&& type, NativeFuncC fn) { PyObject* bind_constructor(__T&& type, NativeFuncC fn) {
static_assert(ARGC==-1 || ARGC>=1); static_assert(ARGC==-1 || ARGC>=1);
return bind_func<ARGC>(std::forward<__T>(type), "__new__", fn); 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());
});
} }
template<typename T, typename __T> template<typename T, typename __T>
PyObject* bind_notimplemented_constructor(__T&& type) { 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(); vm->NotImplementedError();
return vm->None; return vm->None;
}); });
@ -357,19 +326,8 @@ public:
void KeyError(PyObject* obj){ _builtin_error("KeyError", obj); } void KeyError(PyObject* obj){ _builtin_error("KeyError", obj); }
void ImportError(const Str& msg){ _builtin_error("ImportError", msg); } void ImportError(const Str& msg){ _builtin_error("ImportError", msg); }
void BinaryOptError(const char* op, PyObject* _0, PyObject* _1) { void BinaryOptError(const char* op, PyObject* _0, PyObject* _1);
StrName name_0 = _type_name(vm, _tp(_0)); void AttributeError(PyObject* obj, StrName name);
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 AttributeError(const Str& msg){ _builtin_error("AttributeError", msg); } void AttributeError(const Str& msg){ _builtin_error("AttributeError", msg); }
void check_type(PyObject* obj, Type type){ void check_type(PyObject* obj, Type type){
@ -447,11 +405,11 @@ public:
PyObject* _format_string(Str, PyObject*); PyObject* _format_string(Str, PyObject*);
void setattr(PyObject* obj, StrName name, PyObject* value); void setattr(PyObject* obj, StrName name, PyObject* value);
template<int ARGC> template<int ARGC>
PyObject* bind_method(Type, Str, NativeFuncC); PyObject* bind_method(Type, StrName, NativeFuncC);
template<int ARGC> template<int ARGC>
PyObject* bind_method(PyObject*, Str, NativeFuncC); PyObject* bind_method(PyObject*, StrName, NativeFuncC);
template<int ARGC> 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*); void _error(PyObject*);
PyObject* _run_top_frame(); PyObject* _run_top_frame();
void post_init(); void post_init();
@ -615,20 +573,20 @@ __T _py_cast(VM* vm, PyObject* obj) { return _py_cast__internal<__T, false>(vm,
template<int ARGC> 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)); PyObject* nf = VAR(NativeFunc(fn, ARGC, true));
_t(type)->attr().set(name, nf); _t(type)->attr().set(name, nf);
return nf; return nf;
} }
template<int ARGC> 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); check_type(obj, tp_type);
return bind_method<ARGC>(PK_OBJ_GET(Type, obj), name, fn); return bind_method<ARGC>(PK_OBJ_GET(Type, obj), name, fn);
} }
template<int ARGC> 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)); PyObject* nf = VAR(NativeFunc(fn, ARGC, false));
PK_OBJ_GET(NativeFunc, nf).set_userdata(userdata); PK_OBJ_GET(NativeFunc, nf).set_userdata(userdata);
switch(bt){ switch(bt){

View File

@ -3,7 +3,7 @@
namespace pkpy{ namespace pkpy{
void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){ 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]); Type cls = PK_OBJ_GET(Type, args[0]);
i64 addr = CAST(i64, args[1]); i64 addr = CAST(i64, args[1]);
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr)); 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){ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
PY_STRUCT_LIKE(Mat3x3) 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+0) return vm->heap.gcnew<Mat3x3>(PK_OBJ_GET(Type, args[0]), Mat3x3::zeros());
if(args.size() == 1+1){ if(args.size() == 1+1){
const List& list = CAST(List&, args[1]); const List& list = CAST(List&, args[1]);

View File

@ -266,7 +266,10 @@ struct LineProfilerW{
LineProfiler profiler; LineProfiler profiler;
static void _register(VM* vm, PyObject* mod, PyObject* type){ 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){ vm->bind(type, "add_function(self, func)", [](VM* vm, ArgsView args){
LineProfilerW& self = PK_OBJ_GET(LineProfilerW, args[0]); 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){ 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) { vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) {
Random& self = _CAST(Random&, args[0]); 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, PyObject* arg){ _error(call(builtins->attr(type), arg)); }
void VM::_builtin_error(StrName type, const Str& msg){ _builtin_error(type, VAR(msg)); } 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){ void VM::_error(PyObject* e_obj){
PK_ASSERT(isinstance(e_obj, tp_exception)) PK_ASSERT(isinstance(e_obj, tp_exception))
Exception& e = PK_OBJ_GET(Exception, e_obj); 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); 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*)){ void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
PyObject* obj = _t(type); PyObject* obj = _t(type);
_all_types[type].m__hash__ = f; _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); 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{ void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
ok = false; ok = false;
i64 hash = vm->py_hash(key); i64 hash = vm->py_hash(key);