Преглед изворни кода

allow hook getunboundmethod

blueloveTH пре 7 месеци
родитељ
комит
5799af3fd7

+ 4 - 3
include/pocketpy/interpreter/typeinfo.h

@@ -16,9 +16,10 @@ typedef struct py_TypeInfo {
     bool is_python;  // is it a python class? (not derived from c object)
     bool is_sealed;  // can it be subclassed?
 
-    bool (*getattribute)(py_Ref self, py_Name name);
-    bool (*setattribute)(py_Ref self, py_Name name, py_Ref val);
-    bool (*delattribute)(py_Ref self, py_Name name);
+    bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN;
+    bool (*setattribute)(py_Ref self, py_Name name, py_Ref val) PY_RAISE PY_RETURN;
+    bool (*delattribute)(py_Ref self, py_Name name) PY_RAISE;
+    bool (*getunboundmethod)(py_Ref self, py_Name name) PY_RETURN;
 
     py_TValue annotations;
     py_Dtor dtor;  // destructor for this type, NULL if no dtor

+ 6 - 3
include/pocketpy/pocketpy.h

@@ -33,6 +33,7 @@ typedef struct py_TValue {
     py_Type type;
     bool is_ptr;
     int extra;
+
     union {
         int64_t _i64;
         char _chars[16];
@@ -372,9 +373,11 @@ PK_API bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
 
 /// Set attribute hooks for the given type.
 PK_API void py_tphookattributes(py_Type type,
-                                bool (*getattribute)(py_Ref self, py_Name name),
-                                bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
-                                bool (*delattribute)(py_Ref self, py_Name name));
+                                bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN,
+                                bool (*setattribute)(py_Ref self, py_Name name, py_Ref val)
+                                    PY_RAISE PY_RETURN,
+                                bool (*delattribute)(py_Ref self, py_Name name) PY_RAISE,
+                                bool (*getunboundmethod)(py_Ref self, py_Name name) PY_RETURN);
 
 /// Check if the object is an instance of the given type exactly.
 /// Raise `TypeError` if the check fails.

+ 3 - 1
src/interpreter/typeinfo.c

@@ -159,10 +159,12 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
 void py_tphookattributes(py_Type type,
                          bool (*getattribute)(py_Ref self, py_Name name),
                          bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
-                         bool (*delattribute)(py_Ref self, py_Name name)) {
+                         bool (*delattribute)(py_Ref self, py_Name name),
+                         bool (*getunboundmethod)(py_Ref self, py_Name name)) {
     assert(type);
     py_TypeInfo* ti = pk_typeinfo(type);
     ti->getattribute = getattribute;
     ti->setattribute = setattribute;
     ti->delattribute = delattribute;
+    ti->getunboundmethod = getunboundmethod;
 }

+ 18 - 11
src/public/internal.c

@@ -45,17 +45,11 @@ void py_initialize() {
     pk_initialized = true;
 }
 
-void* py_malloc(size_t size) {
-    return PK_MALLOC(size);
-}
+void* py_malloc(size_t size) { return PK_MALLOC(size); }
 
-void* py_realloc(void* ptr, size_t size) {
-    return PK_REALLOC(ptr, size);
-}
+void* py_realloc(void* ptr, size_t size) { return PK_REALLOC(ptr, size); }
 
-void py_free(void* ptr) {
-    PK_FREE(ptr);
-}
+void py_free(void* ptr) { PK_FREE(ptr); }
 
 py_GlobalRef py_True() { return &_True; }
 
@@ -233,7 +227,20 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
         self_bak = *self;
     }
 
-    py_Ref cls_var = py_tpfindname(type, name);
+    py_TypeInfo* ti = pk_typeinfo(type);
+
+    if(ti->getunboundmethod) {
+        bool ok = ti->getunboundmethod(self, name);
+        if(ok) {
+            self[0] = *py_retval();
+            self[1] = self_bak;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    py_Ref cls_var = pk_tpfindname(ti, name);
     if(cls_var != NULL) {
         switch(cls_var->type) {
             case tp_function:
@@ -248,7 +255,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
                 break;
             case tp_classmethod:
                 self[0] = *py_getslot(cls_var, 0);
-                self[1] = pk_typeinfo(type)->self;
+                self[1] = ti->self;
                 break;
             default: c11__unreachable();
         }