From 4fd47072fcaa7764a0a54c6061efe99bbb584f3f Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 13 Jun 2025 16:49:05 +0800 Subject: [PATCH] fix `py_name2ref` Update vm.c backup --- include/pocketpy/interpreter/typeinfo.h | 1 + include/pocketpy/interpreter/vm.h | 12 +--- include/pocketpy/objects/bintree.h | 25 +++++++ include/pocketpy/objects/namedict.h | 18 ----- include/pocketpy/objects/object.h | 7 ++ include/pocketpy/pocketpy.h | 2 +- src/interpreter/vm.c | 44 +++++++++--- src/objects/bintree.c | 72 +++++++++++++++++++ src/objects/namedict.c | 91 ++----------------------- src/public/modules.c | 6 +- tests/81_dataclasses.py | 23 +++++++ 11 files changed, 172 insertions(+), 129 deletions(-) create mode 100644 include/pocketpy/objects/bintree.h create mode 100644 src/objects/bintree.c diff --git a/include/pocketpy/interpreter/typeinfo.h b/include/pocketpy/interpreter/typeinfo.h index ef5ead8a..9fd8614e 100644 --- a/include/pocketpy/interpreter/typeinfo.h +++ b/include/pocketpy/interpreter/typeinfo.h @@ -1,6 +1,7 @@ #pragma once #include "pocketpy/pocketpy.h" +#include "pocketpy/common/vector.h" #include "pocketpy/objects/object.h" #define PK_MAX_CHUNK_LENGTH 256 diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 78065bed..73650843 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -3,6 +3,7 @@ #include "pocketpy/common/memorypool.h" #include "pocketpy/common/name.h" #include "pocketpy/objects/codeobject.h" +#include "pocketpy/objects/bintree.h" #include "pocketpy/pocketpy.h" #include "pocketpy/interpreter/heap.h" #include "pocketpy/interpreter/frame.h" @@ -30,7 +31,7 @@ typedef struct WatchdogInfo { typedef struct VM { py_Frame* top_frame; - ModuleDict modules; + BinTree modules; TypeList types; py_TValue builtins; // builtins module @@ -49,7 +50,7 @@ typedef struct VM { py_TValue reg[8]; // users' registers void* ctx; // user-defined context - NameDict cached_names; + BinTree cached_names; py_StackRef curr_class; py_StackRef curr_decl_based_function; @@ -76,13 +77,6 @@ bool pk__parse_int_slice(py_Ref slice, int* restrict step); bool pk__normalize_index(int* index, int length); -#define pk__mark_value(val) \ - if((val)->is_ptr && !(val)->_obj->gc_marked) { \ - PyObject* obj = (val)->_obj; \ - obj->gc_marked = true; \ - c11_vector__push(PyObject*, p_stack, obj); \ - } - bool pk__object_new(int argc, py_Ref argv); py_TypeInfo* pk__type_info(py_Type type); diff --git a/include/pocketpy/objects/bintree.h b/include/pocketpy/objects/bintree.h new file mode 100644 index 00000000..7d9acb26 --- /dev/null +++ b/include/pocketpy/objects/bintree.h @@ -0,0 +1,25 @@ +#pragma once + +#include "pocketpy/objects/base.h" +#include "pocketpy/common/vector.h" +#include "pocketpy/pocketpy.h" + +typedef struct BinTreeConfig { + int (*f_cmp)(void* lhs, void* rhs); + bool need_free_key; +} BinTreeConfig; + +typedef struct BinTree { + void* key; + py_TValue value; + const BinTreeConfig* config; + struct BinTree* left; + struct BinTree* right; +} BinTree; + +void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config); +void BinTree__dtor(BinTree* self); +void BinTree__set(BinTree* self, void* key, py_Ref value); +py_Ref BinTree__try_get(BinTree* self, void* key); +bool BinTree__contains(BinTree* self, void* key); +void BinTree__apply_mark(BinTree* self, c11_vector* p_stack); diff --git a/include/pocketpy/objects/namedict.h b/include/pocketpy/objects/namedict.h index 1ce2a735..db19ac56 100644 --- a/include/pocketpy/objects/namedict.h +++ b/include/pocketpy/objects/namedict.h @@ -1,26 +1,8 @@ #pragma once -#include "pocketpy/common/vector.h" #include "pocketpy/objects/base.h" #include "pocketpy/pocketpy.h" -/* A simple binary tree for storing modules. */ -typedef struct ModuleDict { - char path[PK_MAX_MODULE_PATH_LEN + 1]; - py_TValue module; - struct ModuleDict* left; - struct ModuleDict* right; -} ModuleDict; - -void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module); -void ModuleDict__dtor(ModuleDict* self); -void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val); -py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path); -bool ModuleDict__contains(ModuleDict* self, const char* path); -void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack); - -/////////////////// NameDict /////////////////// - typedef struct NameDict_KV { py_Name key; py_TValue value; diff --git a/include/pocketpy/objects/object.h b/include/pocketpy/objects/object.h index ce2b28d4..c6e5e8da 100644 --- a/include/pocketpy/objects/object.h +++ b/include/pocketpy/objects/object.h @@ -25,3 +25,10 @@ void* PyObject__userdata(PyObject* self); void PyObject__dtor(PyObject* self); + +#define pk__mark_value(val) \ + if((val)->is_ptr && !(val)->_obj->gc_marked) { \ + PyObject* obj = (val)->_obj; \ + obj->gc_marked = true; \ + c11_vector__push(PyObject*, p_stack, obj); \ + } \ No newline at end of file diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 7887d803..3c05a016 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -245,7 +245,7 @@ PK_API py_Name py_name(const char*); /// Convert a name to a null-terminated string. PK_API const char* py_name2str(py_Name); /// Convert a name to a python `str` object with cache. -PK_API py_ItemRef py_name2ref(py_Name); +PK_API py_GlobalRef py_name2ref(py_Name); /// Convert a `c11_sv` to a name. PK_API py_Name py_namev(c11_sv); /// Convert a name to a `c11_sv`. diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 9d47c92f..c03ec946 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -66,10 +66,24 @@ static void py_TypeInfo__ctor(py_TypeInfo* self, c11_vector__ctor(&self->ordered_attrs, sizeof(py_Name)); } +static int BinTree__cmp_cstr(void* lhs, void* rhs) { + const char* l = (const char*)lhs; + const char* r = (const char*)rhs; + return strcmp(l, r); +} + +static int BinTree__cmp_voidp(void* lhs, void* rhs) { + return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0); +} + void VM__ctor(VM* self) { self->top_frame = NULL; - ModuleDict__ctor(&self->modules, "", *py_NIL()); + static const BinTreeConfig modules_config = { + .f_cmp = BinTree__cmp_cstr, + .need_free_key = true, + }; + BinTree__ctor(&self->modules, c11_strdup(""), py_NIL(), &modules_config); TypeList__ctor(&self->types); self->builtins = *py_NIL(); @@ -99,7 +113,12 @@ void VM__ctor(VM* self) { ManagedHeap__ctor(&self->heap); ValueStack__ctor(&self->stack); - NameDict__ctor(&self->cached_names, PK_INST_ATTR_LOAD_FACTOR); + + static const BinTreeConfig cached_names_config = { + .f_cmp = BinTree__cmp_voidp, + .need_free_key = false, + }; + BinTree__ctor(&self->cached_names, NULL, py_NIL(), &cached_names_config); /* Init Builtin Types */ // 0: unused @@ -273,11 +292,11 @@ void VM__dtor(VM* self) { // clear frames while(self->top_frame) VM__pop_frame(self); - ModuleDict__dtor(&self->modules); + BinTree__dtor(&self->modules); TypeList__dtor(&self->types); FixedMemoryPool__dtor(&self->pool_frame); ValueStack__dtor(&self->stack); - NameDict__dtor(&self->cached_names); + BinTree__dtor(&self->cached_names); } void VM__push_frame(VM* self, py_Frame* frame) { @@ -653,7 +672,9 @@ void ManagedHeap__mark(ManagedHeap* self) { pk__mark_value(p); } // mark modules - ModuleDict__apply_mark(&vm->modules, p_stack); + BinTree__apply_mark(&vm->modules, p_stack); + // mark cached names + BinTree__apply_mark(&vm->cached_names, p_stack); // mark types int types_length = vm->types.length; // 0-th type is placeholder @@ -849,12 +870,13 @@ int py_replinput(char* buf, int max_size) { py_Ref py_name2ref(py_Name name) { assert(name != NULL); - NameDict* d = &pk_current_vm->cached_names; - py_Ref res = NameDict__try_get(d, name); + BinTree* d = &pk_current_vm->cached_names; + py_Ref res = BinTree__try_get(d, name); if(res != NULL) return res; // not found, create a new one - py_TValue tmp; - py_newstrv(&tmp, py_name2sv(name)); - NameDict__set(d, name, &tmp); - return NameDict__try_get(d, name); + py_StackRef tmp = py_pushtmp(); + py_newstrv(tmp, py_name2sv(name)); + BinTree__set(d, name, tmp); + py_pop(); + return BinTree__try_get(d, name); } \ No newline at end of file diff --git a/src/objects/bintree.c b/src/objects/bintree.c new file mode 100644 index 00000000..eb3905bc --- /dev/null +++ b/src/objects/bintree.c @@ -0,0 +1,72 @@ +#include "pocketpy/objects/bintree.h" + +#include "pocketpy/common/vector.h" +#include "pocketpy/objects/object.h" + +void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config) { + self->key = key; + self->value = *value; + self->config = config; + self->left = NULL; + self->right = NULL; +} + +void BinTree__dtor(BinTree* self) { + if(self->config->need_free_key) PK_FREE(self->key); + if(self->left) { + BinTree__dtor(self->left); + PK_FREE(self->left); + } + if(self->right) { + BinTree__dtor(self->right); + PK_FREE(self->right); + } +} + +void BinTree__set(BinTree* self, void* key, py_Ref value) { + int cmp = self->config->f_cmp(key, self->key); + if(cmp < 0) { + if(self->left) { + BinTree__set(self->left, key, value); + } else { + self->left = PK_MALLOC(sizeof(BinTree)); + BinTree__ctor(self->left, key, value, self->config); + } + } else if(cmp > 0) { + if(self->right) { + BinTree__set(self->right, key, value); + } else { + self->right = PK_MALLOC(sizeof(BinTree)); + BinTree__ctor(self->right, key, value, self->config); + } + } else { + self->value = *value; + } +} + +py_Ref BinTree__try_get(BinTree* self, void* key) { + int cmp = self->config->f_cmp(key, self->key); + if(cmp < 0) { + if(self->left) { + return BinTree__try_get(self->left, key); + } else { + return NULL; + } + } else if(cmp > 0) { + if(self->right) { + return BinTree__try_get(self->right, key); + } else { + return NULL; + } + } else { + return &self->value; + } +} + +bool BinTree__contains(BinTree* self, void* key) { return BinTree__try_get(self, key) != NULL; } + +void BinTree__apply_mark(BinTree* self, c11_vector* p_stack) { + pk__mark_value(&self->value); + if(self->left) BinTree__apply_mark(self->left, p_stack); + if(self->right) BinTree__apply_mark(self->right, p_stack); +} \ No newline at end of file diff --git a/src/objects/namedict.c b/src/objects/namedict.c index d5f2cdbb..b95c4448 100644 --- a/src/objects/namedict.c +++ b/src/objects/namedict.c @@ -1,93 +1,10 @@ #include "pocketpy/objects/namedict.h" #include "pocketpy/common/utils.h" -#include "pocketpy/objects/object.h" -#include "pocketpy/pocketpy.h" + #include - -void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) { - assert(path != NULL); - int length = strlen(path); - assert(length <= PK_MAX_MODULE_PATH_LEN); - memcpy(self->path, path, length); - self->path[length] = '\0'; - self->module = module; - self->left = NULL; - self->right = NULL; -} - -void ModuleDict__dtor(ModuleDict* self) { - if(self->left) { - ModuleDict__dtor(self->left); - PK_FREE(self->left); - } - if(self->right) { - ModuleDict__dtor(self->right); - PK_FREE(self->right); - } -} - -void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val) { - assert(key != NULL); - int cmp = strcmp(key, self->path); - if(cmp < 0) { - if(self->left) { - ModuleDict__set(self->left, key, val); - } else { - self->left = PK_MALLOC(sizeof(ModuleDict)); - ModuleDict__ctor(self->left, key, val); - } - } else if(cmp > 0) { - if(self->right) { - ModuleDict__set(self->right, key, val); - } else { - self->right = PK_MALLOC(sizeof(ModuleDict)); - ModuleDict__ctor(self->right, key, val); - } - } else { - self->module = val; - } -} - -py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path) { - assert(path != NULL); - int cmp = strcmp(path, self->path); - if(cmp < 0) { - if(self->left) { - return ModuleDict__try_get(self->left, path); - } else { - return NULL; - } - } else if(cmp > 0) { - if(self->right) { - return ModuleDict__try_get(self->right, path); - } else { - return NULL; - } - } else { - return &self->module; - } -} - -bool ModuleDict__contains(ModuleDict* self, const char* path) { - assert(path != NULL); - return ModuleDict__try_get(self, path) != NULL; -} - -void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack) { - if(!py_isnil(&self->module)) { - // root node is dummy - PyObject* obj = self->module._obj; - assert(obj != NULL); - if(!obj->gc_marked) { - obj->gc_marked = true; - c11_vector__push(PyObject*, p_stack, obj); - } - } - if(self->left) ModuleDict__apply_mark(self->left, p_stack); - if(self->right) ModuleDict__apply_mark(self->right, p_stack); -} - -/////////////////// NameDict /////////////////// +#include +#include +#include #define HASH_PROBE_1(__k, ok, i) \ ok = false; \ diff --git a/src/public/modules.c b/src/public/modules.c index 5eb84800..43c25163 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -13,7 +13,7 @@ py_Ref py_getmodule(const char* path) { VM* vm = pk_current_vm; - return ModuleDict__try_get(&vm->modules, path); + return BinTree__try_get(&vm->modules, (void*)path); } py_Ref py_getbuiltin(py_Name name) { return py_getdict(&pk_current_vm->builtins, name); } @@ -54,12 +54,12 @@ py_Ref py_newmodule(const char* path) { // we do not allow override in order to avoid memory leak // it is because Module objects are not garbage collected - bool exists = ModuleDict__contains(&pk_current_vm->modules, path); + bool exists = BinTree__contains(&pk_current_vm->modules, (void*)path); if(exists) c11__abort("module '%s' already exists", path); // convert to a weak (const char*) path = py_tostr(py_getdict(r0, __path__)); - ModuleDict__set(&pk_current_vm->modules, path, *r0); + BinTree__set(&pk_current_vm->modules, c11_strdup(path), r0); py_shrink(2); return py_getmodule(path); diff --git a/tests/81_dataclasses.py b/tests/81_dataclasses.py index 2aa9bebf..878081d2 100644 --- a/tests/81_dataclasses.py +++ b/tests/81_dataclasses.py @@ -34,3 +34,26 @@ assert d.i == 1 assert d.j == 2 assert d.k == 'default' assert d.sum() == 3 + + +@dataclass +class PrimaryForceConfig: + # 风场图 + planetary_wind: 'str' + local_wind: int + # 地壳运动(含地震带/地形生成) + geothermal_activity: int + # 太阳辐射标量场 + solar_radiation: int + # 水汽场 + planetary_humidity: int + +config = PrimaryForceConfig( + planetary_wind = 'default', + local_wind = 1, + geothermal_activity = 2, + solar_radiation = 3, + planetary_humidity = 4 +) + +assert config.planetary_wind == 'default' \ No newline at end of file