diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 44aa5ec7..13e945de 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -122,6 +122,7 @@ py_Type pk_range__register(); py_Type pk_range_iterator__register(); py_Type pk_BaseException__register(); py_Type pk_Exception__register(); +py_Type pk_super__register(); py_TValue pk_builtins__register(); diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 5ad9e6af..73f8a45f 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -107,7 +107,7 @@ void VM__ctor(VM* self) { validate(tp_nativefunc, pk_nativefunc__register()); validate(tp_boundmethod, pk_newtype("boundmethod", tp_object, NULL, NULL, false, true)); - validate(tp_super, pk_newtype("super", tp_object, NULL, NULL, false, true)); + validate(tp_super, pk_super__register()); validate(tp_BaseException, pk_BaseException__register()); validate(tp_Exception, pk_Exception__register()); validate(tp_bytes, pk_bytes__register()); @@ -147,6 +147,7 @@ void VM__ctor(VM* self) { tp_bytes, tp_dict, tp_property, + tp_super, tp_BaseException, tp_Exception, tp_StopIteration, @@ -504,7 +505,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall } TypeError("'%t' object is not callable", p0->type); - c11__unreachedable(); + return RES_ERROR; } /****************************************/ diff --git a/src/public/internal.c b/src/public/internal.c index a2f32d9b..18208369 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -238,8 +238,8 @@ bool pk_pushmethod(py_StackRef self, py_Name name) { py_Type type; // handle super() proxy if(py_istype(self, tp_super)) { - self = py_getslot(self, 0); type = *(py_Type*)py_touserdata(self); + *self = *py_getslot(self, 0); } else { type = self->type; } @@ -268,7 +268,6 @@ bool pk_pushmethod(py_StackRef self, py_Name name) { } return true; } - // TODO: __getattr__ fallback return false; } diff --git a/src/public/modules.c b/src/public/modules.c index 732f84c1..5d50a846 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -326,6 +326,35 @@ static bool builtins__eval(int argc, py_Ref argv) { return py_exec(py_tostr(argv), "", EVAL_MODE, NULL); } +static bool builtins__isinstance(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + if(py_istuple(py_arg(1))) { + int length = py_tuple__len(py_arg(1)); + for(int i = 0; i < length; i++) { + py_Ref item = py_tuple__getitem(py_arg(1), i); + if(!py_checktype(item, tp_type)) return false; + if(py_isinstance(py_arg(0), py_totype(item))) { + py_newbool(py_retval(), true); + return true; + } + } + py_newbool(py_retval(), false); + return true; + } + + if(!py_checktype(py_arg(1), tp_type)) return false; + py_newbool(py_retval(), py_isinstance(py_arg(0), py_totype(py_arg(1)))); + return true; +} + +static bool builtins__issubclass(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + if(!py_checktype(py_arg(0), tp_type)) return false; + if(!py_checktype(py_arg(1), tp_type)) return false; + py_newbool(py_retval(), py_issubclass(py_totype(py_arg(0)), py_totype(py_arg(1)))); + return true; +} + py_TValue pk_builtins__register() { py_Ref builtins = py_newmodule("builtins"); py_bindfunc(builtins, "repr", builtins__repr); @@ -345,6 +374,9 @@ py_TValue pk_builtins__register() { py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print); py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted); + py_bindfunc(builtins, "isinstance", builtins__isinstance); + py_bindfunc(builtins, "issubclass", builtins__issubclass); + // None __repr__ py_bindmagic(tp_NoneType, __repr__, NoneType__repr__); return *builtins; @@ -366,4 +398,44 @@ py_Type pk_nativefunc__register() { py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true); py_bindmagic(type, __repr__, nativefunc__repr); return type; -} \ No newline at end of file +} + +static bool super__new__(int argc, py_Ref argv) { + py_Type* class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type)); + Frame* frame = pk_current_vm->top_frame; + *class_arg = 0; + py_Ref self_arg = NULL; + if(argc == 1) { + // super() + if(frame->function) { + // class_arg = PK_OBJ_GET(Function, frame->_callable)._class; + Function* func = PyObject__userdata(frame->function); + *class_arg = *(py_Type*)PyObject__userdata(func->clazz); + if(frame->locals_co->nlocals > 0) self_arg = &frame->locals[0]; + } + if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments"); + } else if(argc == 3) { + // super(type, obj) + PY_CHECK_ARG_TYPE(1, tp_type); + *class_arg = py_totype(py_arg(1)); + self_arg = py_arg(2); + if(!py_isinstance(self_arg, *class_arg)) { + return TypeError("super(type, obj): obj must be an instance of type"); + } + } else { + return TypeError("super() takes 0 or 2 arguments"); + } + + py_TypeInfo* types = pk_current_vm->types.data; + *class_arg = types[*class_arg].base; + if(*class_arg == 0) return RuntimeError("super(): base class is invalid"); + + py_setslot(py_retval(), 0, self_arg); + return true; +} + +py_Type pk_super__register() { + py_Type type = pk_newtype("super", tp_object, NULL, NULL, false, true); + py_bindmagic(type, __new__, super__new__); + return type; +} diff --git a/tests/41_class_ex.py b/tests/41_class_ex.py index 63c84b51..9a3b6304 100644 --- a/tests/41_class_ex.py +++ b/tests/41_class_ex.py @@ -110,14 +110,6 @@ class B(A): assert B.b == 3 assert B.c == 4 -import c - -class A(c.void_p): - pass - -a = A(0) -assert repr(a).startswith('