fix super()

This commit is contained in:
blueloveTH 2024-12-05 00:04:41 +08:00
parent c7935564c3
commit 72e88892e5
5 changed files with 22 additions and 27 deletions

View File

@ -7,7 +7,7 @@ class TValue[T]:
@property @property
def value(self) -> T: ... def value(self) -> T: ...
TValue_int = TValue[int] # TValue_int = TValue[int]
TValue_float = TValue[float] # TValue_float = TValue[float]
TValue_vec2i = TValue[vec2i] # TValue_vec2i = TValue[vec2i]
TValue_vec2 = TValue[vec2] # TValue_vec2 = TValue[vec2]

View File

@ -167,9 +167,6 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
if(py_istype(self, tp_type)) { if(py_istype(self, tp_type)) {
// T.__new__(...) // T.__new__(...)
type = py_totype(self); type = py_totype(self);
} else if(py_istype(self, tp_super)) {
// super().__new__(...)
type = *(py_Type*)py_touserdata(self);
} else { } else {
// invalid usage of `__new__` // invalid usage of `__new__`
return false; return false;

View File

@ -756,9 +756,8 @@ py_Type pk_nativefunc__register() {
} }
static bool super__new__(int argc, py_Ref argv) { static bool super__new__(int argc, py_Ref argv) {
py_Type* class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type)); py_Type class_arg = 0;
Frame* frame = pk_current_vm->top_frame; Frame* frame = pk_current_vm->top_frame;
*class_arg = 0;
py_Ref self_arg = NULL; py_Ref self_arg = NULL;
if(argc == 1) { if(argc == 1) {
// super() // super()
@ -768,27 +767,36 @@ static bool super__new__(int argc, py_Ref argv) {
if(callable->type == tp_function) { if(callable->type == tp_function) {
Function* func = py_touserdata(callable); Function* func = py_touserdata(callable);
if(func->clazz != NULL) { if(func->clazz != NULL) {
*class_arg = *(py_Type*)PyObject__userdata(func->clazz); class_arg = *(py_Type*)PyObject__userdata(func->clazz);
if(frame->co->nlocals > 0) self_arg = &frame->locals[0]; if(frame->co->nlocals > 0) self_arg = &frame->locals[0];
} }
} }
} }
if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments"); if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments");
if(self_arg->type == tp_type) {
// f(cls, ...)
class_arg = pk__type_info(class_arg)->base;
if(class_arg == 0) return RuntimeError("super(): base class is invalid");
py_assign(py_retval(), py_tpobject(class_arg));
return true;
}
} else if(argc == 3) { } else if(argc == 3) {
// super(type, obj) // super(type[T], obj)
PY_CHECK_ARG_TYPE(1, tp_type); PY_CHECK_ARG_TYPE(1, tp_type);
*class_arg = py_totype(py_arg(1)); class_arg = py_totype(py_arg(1));
self_arg = py_arg(2); self_arg = py_arg(2);
if(!py_isinstance(self_arg, *class_arg)) { if(!py_isinstance(self_arg, class_arg)) {
return TypeError("super(type, obj): obj must be an instance of type"); return TypeError("super(type, obj): obj must be an instance of type");
} }
} else { } else {
return TypeError("super() takes 0 or 2 arguments"); return TypeError("super() takes 0 or 2 arguments");
} }
*class_arg = pk__type_info(*class_arg)->base; class_arg = pk__type_info(class_arg)->base;
if(*class_arg == 0) return RuntimeError("super(): base class is invalid"); if(class_arg == 0) return RuntimeError("super(): base class is invalid");
py_Type* p_class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type));
*p_class_arg = class_arg;
py_setslot(py_retval(), 0, self_arg); py_setslot(py_retval(), 0, self_arg);
return true; return true;
} }

View File

@ -87,12 +87,6 @@ int py_next(py_Ref val) {
bool py_getattr(py_Ref self, py_Name name) { bool py_getattr(py_Ref self, py_Name name) {
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
py_Type type = self->type; py_Type type = self->type;
// handle super() proxy (disabled)
// if(py_istype(self, tp_super)) {
// self = py_getslot(self, 0);
// type = *(py_Type*)py_touserdata(self);
// }
py_Ref cls_var = py_tpfindname(type, name); py_Ref cls_var = py_tpfindname(type, name);
if(cls_var) { if(cls_var) {
// handle descriptor // handle descriptor
@ -183,12 +177,6 @@ bool py_getattr(py_Ref self, py_Name name) {
bool py_setattr(py_Ref self, py_Name name, py_Ref val) { bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
py_Type type = self->type; py_Type type = self->type;
// handle super() proxy (disabled)
// if(py_istype(self, tp_super)) {
// self = py_getslot(self, 0);
// type = *(py_Type*)py_touserdata(self);
// }
py_Ref cls_var = py_tpfindname(type, name); py_Ref cls_var = py_tpfindname(type, name);
if(cls_var) { if(cls_var) {
// handle descriptor // handle descriptor

View File

@ -78,6 +78,7 @@ class Z:
class B(Z): class B(Z):
def __new__(cls, x): def __new__(cls, x):
assert super() is Z
return super().__new__(cls, x) return super().__new__(cls, x)
assert Z(1) == (Z, 1) assert Z(1) == (Z, 1)
@ -87,6 +88,7 @@ from pkpy import TValue
class fixed(TValue[int]): class fixed(TValue[int]):
def __new__(cls, value: str): def __new__(cls, value: str):
assert super() is TValue[int]
return super().__new__(cls, int(value)) return super().__new__(cls, int(value))
assert fixed('123').value == 123 assert fixed('123').value == 123