From 0b09246a6d12a1d9f837250275abc3d288c1cad1 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 22 Jun 2025 13:01:50 +0800 Subject: [PATCH] add `RELOAD_MODE` --- include/pocketpy/interpreter/typeinfo.h | 17 +++++- include/pocketpy/interpreter/vm.h | 7 --- include/pocketpy/pocketpy.h | 3 +- src/interpreter/ceval.c | 13 +++-- src/interpreter/typeinfo.c | 76 +++++++++++++++++++++++++ src/interpreter/vm.c | 41 ------------- src/public/modules.c | 2 +- 7 files changed, 102 insertions(+), 57 deletions(-) diff --git a/include/pocketpy/interpreter/typeinfo.h b/include/pocketpy/interpreter/typeinfo.h index 340920fc..e01b7146 100644 --- a/include/pocketpy/interpreter/typeinfo.h +++ b/include/pocketpy/interpreter/typeinfo.h @@ -25,4 +25,19 @@ typedef struct py_TypeInfo { py_TypeInfo* pk_typeinfo(py_Type type); py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name); -#define pk_tpfindmagic pk_tpfindname \ No newline at end of file +#define pk_tpfindmagic pk_tpfindname + +py_Type pk_newtype(const char* name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed); + + +py_Type pk_newtypewithmode(py_Name name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed, enum py_CompileMode mode); \ No newline at end of file diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 3592fea5..ce822c85 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -100,13 +100,6 @@ typedef enum FrameResult { FrameResult VM__run_top_frame(VM* self); -py_Type pk_newtype(const char* name, - py_Type base, - const py_GlobalRef module, - void (*dtor)(void*), - bool is_python, - bool is_sealed); - FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall); const char* pk_opname(Opcode op); diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 798985dd..79abaa2e 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -92,7 +92,8 @@ typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE PY_RETURN; /// + `EXEC_MODE`: for statements. /// + `EVAL_MODE`: for expressions. /// + `SINGLE_MODE`: for REPL or jupyter notebook execution. -enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE }; +/// + `RELOAD_MODE`: for reloading a module without allocating new types if possible. +enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE, RELOAD_MODE }; /************* Global Setup *************/ diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 5c391e40..7c6ece74 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -1042,12 +1042,13 @@ FrameResult VM__run_top_frame(VM* self) { goto __ERROR; } - py_Type type = pk_newtype(py_name2str(name), - base, - frame->module, - NULL, - base_ti->is_python, - false); + py_Type type = pk_newtypewithmode(name, + base, + frame->module, + NULL, + base_ti->is_python, + false, + frame->co->src->mode); PUSH(py_tpobject(type)); self->curr_class = TOP(); DISPATCH(); diff --git a/src/interpreter/typeinfo.c b/src/interpreter/typeinfo.c index db543c01..8c5fa460 100644 --- a/src/interpreter/typeinfo.c +++ b/src/interpreter/typeinfo.c @@ -46,4 +46,80 @@ const char* py_tpname(py_Type type) { py_TypeInfo* pk_typeinfo(py_Type type) { return c11__getitem(TypePointer, &pk_current_vm->types, type).ti; +} + +static void py_TypeInfo__common_init(py_Name name, + py_Type base, + py_Type index, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed, + py_TypeInfo* self) { + py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL; + if(base_ti && base_ti->is_sealed) { + c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name)); + } + + memset(self, 0, sizeof(py_TypeInfo)); + self->name = name; + self->index = index; + self->base = base; + self->base_ti = base_ti; + + self->self = *py_retval(); + self->module = module ? module : py_NIL(); + self->annotations = *py_NIL(); + + if(!dtor && base) dtor = base_ti->dtor; + self->is_python = is_python; + self->is_sealed = is_sealed; + self->dtor = dtor; +} + +py_Type pk_newtype(const char* name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed) { + 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), base, index, module, dtor, is_python, is_sealed, self); + TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types); + pointer->ti = self; + pointer->dtor = self->dtor; + return index; +} + +py_Type pk_newtypewithmode(py_Name name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed, + enum py_CompileMode mode) { + if(mode == RELOAD_MODE && module != NULL) { + py_ItemRef old_class = py_getdict(module, name); + if(old_class != NULL && py_istype(old_class, tp_type)) { + NameDict* old_dict = PyObject__dict(old_class->_obj); + NameDict__clear(old_dict); + py_TypeInfo* self = py_touserdata(old_class); + py_Type index = self->index; + py_TypeInfo__common_init(name, base, index, module, dtor, is_python, is_sealed, self); + TypePointer* pointer = c11__at(TypePointer, &pk_current_vm->types, index); + pointer->ti = self; + pointer->dtor = self->dtor; + return index; + } + } + + return pk_newtype(py_name2str(name), base, module, dtor, is_python, is_sealed); +} + +py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) { + if(strlen(name) == 0) c11__abort("type name cannot be empty"); + py_Type type = pk_newtype(name, base, module, dtor, false, false); + if(module) py_setdict(module, py_name(name), py_tpobject(type)); + return type; } \ No newline at end of file diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 5bcd9a44..648a8fa4 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -364,47 +364,6 @@ bool pk__normalize_index(int* index, int length) { return true; } -py_Type pk_newtype(const char* name, - py_Type base, - const py_GlobalRef module, - void (*dtor)(void*), - bool is_python, - bool is_sealed) { - py_Type index = pk_current_vm->types.length; - py_TypeInfo* self = py_newobject(py_retval(), tp_type, -1, sizeof(py_TypeInfo)); - py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL; - if(base_ti && base_ti->is_sealed) { - c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name)); - } - - memset(self, 0, sizeof(py_TypeInfo)); - self->name = py_name(name); - self->index = index; - self->base = base; - self->base_ti = base_ti; - - self->self = *py_retval(); - self->module = module ? module : py_NIL(); - self->annotations = *py_NIL(); - - if(!dtor && base) dtor = base_ti->dtor; - self->is_python = is_python; - self->is_sealed = is_sealed; - self->dtor = dtor; - - TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types); - pointer->ti = self; - pointer->dtor = dtor; - return index; -} - -py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) { - if(strlen(name) == 0) c11__abort("type name cannot be empty"); - py_Type type = pk_newtype(name, base, module, dtor, false, false); - if(module) py_setdict(module, py_name(name), py_tpobject(type)); - return type; -} - static bool prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) { const CodeObject* co = &decl->code; diff --git a/src/public/modules.c b/src/public/modules.c index 8ffa0348..7915a68f 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -176,7 +176,7 @@ bool py_importlib_reload(py_GlobalRef module) { } c11_string__delete(slashed_path); if(data == NULL) return ImportError("module '%v' not found", path); - bool ok = py_exec(data, filename->data, EXEC_MODE, module); + bool ok = py_exec(data, filename->data, RELOAD_MODE, module); c11_string__delete(filename); PK_FREE(data); py_assign(py_retval(), module);