diff --git a/include/pocketpy/interpreter/typeinfo.h b/include/pocketpy/interpreter/typeinfo.h index e2901fa2..ef5ead8a 100644 --- a/include/pocketpy/interpreter/typeinfo.h +++ b/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); - diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 8b5d084f..7887d803 100644 --- a/include/pocketpy/pocketpy.h +++ b/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); diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 0921392f..af09c1f9 100644 --- a/src/interpreter/ceval.c +++ b/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(); } diff --git a/src/interpreter/typeinfo.c b/src/interpreter/typeinfo.c index 7d352ae6..14b410bf 100644 --- a/src/interpreter/typeinfo.c +++ b/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]); diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 9f6c7520..9d47c92f 100644 --- a/src/interpreter/vm.c +++ b/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) { diff --git a/src/public/internal.c b/src/public/internal.c index 5a2912fc..8017762e 100644 --- a/src/public/internal.c +++ b/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);