From 01f04b2e410b83181d568f8206bd44925fb40449 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Thu, 17 Jul 2025 11:24:39 +0800 Subject: [PATCH] add `py_tpsetfinal` --- include/pocketpy/interpreter/typeinfo.h | 6 +++--- include/pocketpy/pocketpy.h | 3 ++- src/interpreter/ceval.c | 2 +- src/interpreter/typeinfo.c | 22 ++++++++++++++-------- src/modules/enum.c | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/pocketpy/interpreter/typeinfo.h b/include/pocketpy/interpreter/typeinfo.h index 5be349aa..80790894 100644 --- a/include/pocketpy/interpreter/typeinfo.h +++ b/include/pocketpy/interpreter/typeinfo.h @@ -14,7 +14,7 @@ typedef struct py_TypeInfo { py_GlobalRef module; bool is_python; // is it a python class? (not derived from c object) - bool is_sealed; // can it be subclassed? + bool is_final; // can it be subclassed? 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; @@ -35,7 +35,7 @@ py_Type pk_newtype(const char* name, const py_GlobalRef module, void (*dtor)(void*), bool is_python, - bool is_sealed); + bool is_final); py_Type pk_newtypewithmode(py_Name name, @@ -43,4 +43,4 @@ py_Type pk_newtypewithmode(py_Name name, const py_GlobalRef module, void (*dtor)(void*), bool is_python, - bool is_sealed, enum py_CompileMode mode); \ No newline at end of file + bool is_final, enum py_CompileMode mode); \ No newline at end of file diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 9604071b..9e56fb2b 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -370,7 +370,8 @@ PK_API py_GlobalRef py_tpobject(py_Type type); PK_API const char* py_tpname(py_Type type); /// Call a type to create a new instance. PK_API bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN; - +/// Disable the type for subclassing. +PK_API void py_tpsetfinal(py_Type type); /// Set attribute hooks for the given type. PK_API void py_tphookattributes(py_Type type, bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN, diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 2d2b6a20..4427de9a 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -1041,7 +1041,7 @@ __NEXT_STEP: POP(); py_TypeInfo* base_ti = pk_typeinfo(base); - if(base_ti->is_sealed) { + if(base_ti->is_final) { TypeError("type '%t' is not an acceptable base type", base); goto __ERROR; } diff --git a/src/interpreter/typeinfo.c b/src/interpreter/typeinfo.c index 11e02d8c..93fba34d 100644 --- a/src/interpreter/typeinfo.c +++ b/src/interpreter/typeinfo.c @@ -61,11 +61,11 @@ static void py_TypeInfo__common_init(py_Name name, const py_GlobalRef module, void (*dtor)(void*), bool is_python, - bool is_sealed, + bool is_final, py_TypeInfo* self, py_TValue* typeobject) { py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL; - if(base_ti && base_ti->is_sealed) { + if(base_ti && base_ti->is_final) { c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name)); } @@ -79,7 +79,7 @@ static void py_TypeInfo__common_init(py_Name name, if(!dtor && base) dtor = base_ti->dtor; self->is_python = is_python; - self->is_sealed = is_sealed; + self->is_final = is_final; self->getattribute = NULL; self->setattribute = NULL; @@ -96,7 +96,7 @@ py_Type pk_newtype(const char* name, const py_GlobalRef module, void (*dtor)(void*), bool is_python, - bool is_sealed) { + bool is_final) { py_Type index = pk_current_vm->types.length; py_TypeInfo* self = py_newobject(py_retval(), tp_type, -1, sizeof(py_TypeInfo)); py_TypeInfo__common_init(py_name(name), @@ -105,7 +105,7 @@ py_Type pk_newtype(const char* name, module, dtor, is_python, - is_sealed, + is_final, self, py_retval()); TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types); @@ -119,7 +119,7 @@ py_Type pk_newtypewithmode(py_Name name, const py_GlobalRef module, void (*dtor)(void*), bool is_python, - bool is_sealed, + bool is_final, enum py_CompileMode mode) { if(mode == RELOAD_MODE && module != NULL) { py_ItemRef old_class = py_getdict(module, name); @@ -137,7 +137,7 @@ py_Type pk_newtypewithmode(py_Name name, module, dtor, is_python, - is_sealed, + is_final, self, &self->self); TypePointer* pointer = c11__at(TypePointer, &pk_current_vm->types, index); @@ -147,7 +147,7 @@ py_Type pk_newtypewithmode(py_Name name, } } - return pk_newtype(py_name2str(name), base, module, dtor, is_python, is_sealed); + return pk_newtype(py_name2str(name), base, module, dtor, is_python, is_final); } py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) { @@ -157,6 +157,12 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo return type; } +void py_tpsetfinal(py_Type type) { + assert(type); + py_TypeInfo* ti = pk_typeinfo(type); + ti->is_final = true; +} + 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), diff --git a/src/modules/enum.c b/src/modules/enum.c index 9c7a5659..f0601f48 100644 --- a/src/modules/enum.c +++ b/src/modules/enum.c @@ -16,7 +16,7 @@ static bool Enum__wrapper_field(py_Name name, py_Ref value, void* ctx) { } static void Enum__on_end_subclass(py_TypeInfo* derived_ti) { - derived_ti->is_sealed = true; + derived_ti->is_final = true; py_applydict(&derived_ti->self, Enum__wrapper_field, &derived_ti->self); }