mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
fix py_name2ref
Update vm.c backup
This commit is contained in:
parent
a7159e5496
commit
4fd47072fc
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
25
include/pocketpy/objects/bintree.h
Normal file
25
include/pocketpy/objects/bintree.h
Normal file
@ -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);
|
@ -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;
|
||||
|
@ -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); \
|
||||
}
|
@ -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`.
|
||||
|
@ -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);
|
||||
}
|
72
src/objects/bintree.c
Normal file
72
src/objects/bintree.c
Normal file
@ -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);
|
||||
}
|
@ -1,93 +1,10 @@
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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 <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HASH_PROBE_1(__k, ok, i) \
|
||||
ok = false; \
|
||||
|
@ -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);
|
||||
|
@ -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'
|
Loading…
x
Reference in New Issue
Block a user