فهرست منبع

add `py_tpclassattrs` and `py_tpbase`

blueloveTH 8 ماه پیش
والد
کامیت
141f187705

+ 2 - 5
include/pocketpy/interpreter/typeinfo.h

@@ -18,12 +18,10 @@ typedef struct py_TypeInfo {
 
     void (*dtor)(void*);
 
-    py_TValue annotations;  // type annotations
+    py_TValue annotations;
+    c11_vector /*T=py_Name*/ ordered_attrs;
 
     void (*on_end_subclass)(struct py_TypeInfo*);  // backdoor for enum module
-
-    /* Magic Slots */
-    // (deleted)
 } py_TypeInfo;
 
 typedef struct TypeList {
@@ -36,4 +34,3 @@ void TypeList__dtor(TypeList* self);
 py_TypeInfo* TypeList__get(TypeList* self, py_Type index);
 py_TypeInfo* TypeList__emplace(TypeList* self);
 void TypeList__apply(TypeList* self, void (*f)(py_TypeInfo*, void*), void* ctx);
-

+ 6 - 1
include/pocketpy/pocketpy.h

@@ -325,7 +325,7 @@ PK_API bool py_isinstance(py_Ref obj, py_Type type);
 PK_API bool py_issubclass(py_Type derived, py_Type base);
 
 /// Get the magic method from the given type only.
-/// The returned reference is always valid. However, its value may be `nil`.
+/// Return `nil` if not found.
 PK_API PK_DEPRECATED py_GlobalRef py_tpgetmagic(py_Type type, py_Name name);
 /// Search the magic method from the given type to the base type.
 /// Return `NULL` if not found.
@@ -333,6 +333,11 @@ PK_API py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
 /// Search the name from the given type to the base type.
 /// Return `NULL` if not found.
 PK_API py_ItemRef py_tpfindname(py_Type, py_Name name);
+/// Get ordered attributes of the type.
+// These attributes must be defined under `class` statement.
+PK_API py_Name* py_tpclassattrs(py_Type, int* out_length);
+/// Get the base type of the given type.
+PK_API py_Type py_tpbase(py_Type type);
 
 /// Get the type object of the given type.
 PK_API py_GlobalRef py_tpobject(py_Type type);

+ 3 - 0
src/interpreter/ceval.c

@@ -1079,6 +1079,8 @@ FrameResult VM__run_top_frame(VM* self) {
             }
             case OP_STORE_CLASS_ATTR: {
                 assert(self->curr_class);
+                py_Type type = py_totype(self->curr_class);
+                py_TypeInfo* ti = TypeList__get(&self->types, type);
                 py_Name name = co_names[byte.arg];
                 // TOP() can be a function, classmethod or custom decorator
                 py_Ref actual_func = TOP();
@@ -1090,6 +1092,7 @@ FrameResult VM__run_top_frame(VM* self) {
                     ud->clazz = self->curr_class->_obj;
                 }
                 py_setdict(self->curr_class, name, TOP());
+                c11_vector__push(py_Name, &ti->ordered_attrs, name);
                 POP();
                 DISPATCH();
             }

+ 1 - 1
src/interpreter/typeinfo.c

@@ -12,7 +12,7 @@ void TypeList__ctor(TypeList* self) {
 void TypeList__dtor(TypeList* self) {
     for(py_Type t = 0; t < self->length; t++) {
         py_TypeInfo* info = TypeList__get(self, t);
-        (void)info;
+        c11_vector__dtor(&info->ordered_attrs);
     }
     for(int i = 0; i < PK_MAX_CHUNK_LENGTH; i++) {
         if(self->chunks[i]) PK_FREE(self->chunks[i]);

+ 1 - 0
src/interpreter/vm.c

@@ -63,6 +63,7 @@ static void py_TypeInfo__ctor(py_TypeInfo* self,
 
     self->module = module;
     self->annotations = *py_NIL();
+    c11_vector__ctor(&self->ordered_attrs, sizeof(py_Name));
 }
 
 void VM__ctor(VM* self) {

+ 12 - 0
src/public/internal.c

@@ -247,6 +247,18 @@ py_Ref py_tpfindname(py_Type t, py_Name name) {
     return NULL;
 }
 
+py_Name* py_tpclassattrs(py_Type t, int* out_length) {
+    py_TypeInfo* ti = pk__type_info(t);
+    *out_length = ti->ordered_attrs.length;
+    return ti->ordered_attrs.data;
+}
+
+py_Type py_tpbase(py_Type t) {
+    assert(t);
+    py_TypeInfo* ti = pk__type_info(t);
+    return py_totype(&ti->base_ti->self);
+}
+
 PK_DEPRECATED py_Ref py_tpgetmagic(py_Type type, py_Name name) {
     assert(py_ismagicname(name));
     py_TypeInfo* ti = pk__type_info(type);