blueloveTH 1 yıl önce
ebeveyn
işleme
348bb2b7a5

+ 1 - 0
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();
 

+ 3 - 2
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;
 }
 
 /****************************************/

+ 1 - 2
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;
 }
 

+ 73 - 1
src/public/modules.c

@@ -326,6 +326,35 @@ static bool builtins__eval(int argc, py_Ref argv) {
     return py_exec(py_tostr(argv), "<eval>", 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;
-}
+}
+
+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;
+}

+ 0 - 8
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('<void* at')
-
 if 1:
     class TrueClass:
         pass