Compare commits

..

No commits in common. "332a51945ce0aadddd39e5ed374c18a0a70087d8" and "2bdbe8a6842a835551c07053d8181d88e9873ae3" have entirely different histories.

24 changed files with 194 additions and 222 deletions

View File

@ -3,7 +3,7 @@ output: .retype
url: https://pocketpy.dev url: https://pocketpy.dev
branding: branding:
title: pocketpy title: pocketpy
label: v2.0.9 label: v2.0.8
logo: "./static/logo.png" logo: "./static/logo.png"
favicon: "./static/logo.png" favicon: "./static/logo.png"
meta: meta:

View File

@ -13,8 +13,6 @@ typedef struct c11_string {
char data[]; // flexible array member char data[]; // flexible array member
} c11_string; } c11_string;
c11_string* pk_tostr(py_Ref self);
/* bytes */ /* bytes */
typedef struct c11_bytes { typedef struct c11_bytes {
int size; int size;

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
// clang-format off // clang-format off
#define PK_VERSION "2.0.9" #define PK_VERSION "2.0.8"
#define PK_VERSION_MAJOR 2 #define PK_VERSION_MAJOR 2
#define PK_VERSION_MINOR 0 #define PK_VERSION_MINOR 0
#define PK_VERSION_PATCH 9 #define PK_VERSION_PATCH 8
/*************** feature settings ***************/ /*************** feature settings ***************/
// Whether to compile os-related modules or not // Whether to compile os-related modules or not

View File

@ -68,5 +68,5 @@ int Frame__prepare_jump_exception_handler(py_Frame* self, ValueStack*);
UnwindTarget* Frame__find_unwind_target(py_Frame* self, int iblock); UnwindTarget* Frame__find_unwind_target(py_Frame* self, int iblock);
void Frame__set_unwind_target(py_Frame* self, py_TValue* sp); void Frame__set_unwind_target(py_Frame* self, py_TValue* sp);
void Frame__gc_mark(py_Frame* self, c11_vector* p_stack); void Frame__gc_mark(py_Frame* self);
SourceLocation Frame__source_location(py_Frame* self); SourceLocation Frame__source_location(py_Frame* self);

View File

@ -5,8 +5,7 @@
typedef struct ManagedHeap { typedef struct ManagedHeap {
MultiPool small_objects; MultiPool small_objects;
c11_vector /* PyObject_p */ large_objects; c11_vector /* PyObject* */ large_objects;
c11_vector /* PyObject_p */ gc_roots;
int freed_ma[3]; int freed_ma[3];
int gc_threshold; // threshold for gc_counter int gc_threshold; // threshold for gc_counter

View File

@ -24,5 +24,5 @@ typedef struct {
typedef c11_vector List; typedef c11_vector List;
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack); void c11_chunked_array2d__mark(void* ud);
void function__gc_mark(void* ud, c11_vector* p_stack); void function__gc_mark(void* ud);

View File

@ -34,6 +34,8 @@ typedef struct VM {
py_Callbacks callbacks; py_Callbacks callbacks;
py_TValue ascii_literals[128+1];
py_TValue last_retval; py_TValue last_retval;
py_TValue curr_exception; py_TValue curr_exception;
@ -62,19 +64,10 @@ void VM__dtor(VM* self);
void VM__push_frame(VM* self, py_Frame* frame); void VM__push_frame(VM* self, py_Frame* frame);
void VM__pop_frame(VM* self); void VM__pop_frame(VM* self);
bool pk__parse_int_slice(py_Ref slice, bool pk__parse_int_slice(py_Ref slice, int length, int* restrict start, int* restrict stop, int* restrict step);
int length,
int* restrict start,
int* restrict stop,
int* restrict step);
bool pk__normalize_index(int* index, int length); bool pk__normalize_index(int* index, int length);
#define pk__mark_value(val) \ #define pk__mark_value(val) if((val)->is_ptr && !(val)->_obj->gc_marked) PyObject__mark((val)->_obj)
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); bool pk__object_new(int argc, py_Ref argv);
py_TypeInfo* pk__type_info(py_Type type); py_TypeInfo* pk__type_info(py_Type type);

View File

@ -21,6 +21,5 @@ typedef struct py_TValue {
c11_vec2i _vec2i; c11_vec2i _vec2i;
c11_color32 _color32; c11_color32 _color32;
void* _ptr; void* _ptr;
char _chars[8];
}; };
} py_TValue; } py_TValue;

View File

@ -89,7 +89,7 @@ typedef struct CodeObject {
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name); void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name);
void CodeObject__dtor(CodeObject* self); void CodeObject__dtor(CodeObject* self);
int CodeObject__add_varname(CodeObject* self, py_Name name); int CodeObject__add_varname(CodeObject* self, py_Name name);
void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack); void CodeObject__gc_mark(const CodeObject* self);
typedef struct FuncDeclKwArg { typedef struct FuncDeclKwArg {
int index; // index in co->varnames int index; // index in co->varnames
@ -122,7 +122,7 @@ void FuncDecl__add_arg(FuncDecl* self, py_Name name);
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value); void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value);
void FuncDecl__add_starred_arg(FuncDecl* self, py_Name name); void FuncDecl__add_starred_arg(FuncDecl* self, py_Name name);
void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name); void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name);
void FuncDecl__gc_mark(const FuncDecl* self, c11_vector* p_stack); void FuncDecl__gc_mark(const FuncDecl* self);
// runtime function // runtime function
typedef struct Function { typedef struct Function {

View File

@ -14,7 +14,7 @@
/* A simple binary tree for storing modules. */ /* A simple binary tree for storing modules. */
typedef struct ModuleDict { typedef struct ModuleDict {
char path[PK_MAX_MODULE_PATH_LEN + 1]; const char* path;
py_TValue module; py_TValue module;
struct ModuleDict* left; struct ModuleDict* left;
struct ModuleDict* right; struct ModuleDict* right;
@ -25,4 +25,4 @@ void ModuleDict__dtor(ModuleDict* self);
void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val); void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val);
py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path); py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path);
bool ModuleDict__contains(ModuleDict* self, const char* path); bool ModuleDict__contains(ModuleDict* self, const char* path);
void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack); void ModuleDict__apply_mark(ModuleDict* self);

View File

@ -24,4 +24,4 @@ void* PyObject__userdata(PyObject* self);
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(NameDict)) #define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(NameDict))
void PyObject__dtor(PyObject* self); void PyObject__dtor(PyObject* self);
void PyObject__mark(PyObject* self);

View File

@ -280,7 +280,7 @@ void invoke(Fn&& fn,
if constexpr(is_member_function_pointer) { if constexpr(is_member_function_pointer) {
// helper function to unpack the arguments to call the member pointer // helper function to unpack the arguments to call the member pointer
auto unpack = [&](class_type_t<underlying_type>& self, auto&&... args) { auto unpack = [&](class_type_t<underlying_type>& self, auto&... args) {
return (self.*fn)(args...); return (self.*fn)(args...);
}; };

View File

@ -45,12 +45,6 @@ public:
std::string stringfy() const { std::string stringfy() const {
return "(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")"; return "(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")";
} }
void set_pointer(Point* p) {
this->x = p->x;
this->y = p->y;
this->z = p->z;
}
}; };
struct Line { struct Line {
@ -66,8 +60,7 @@ TEST_F(PYBIND11_TEST, class) {
.def_readwrite("x", &Point::x) .def_readwrite("x", &Point::x)
.def_readwrite("y", &Point::y) .def_readwrite("y", &Point::y)
.def_property("z", &Point::get_z, &Point::set_z) .def_property("z", &Point::get_z, &Point::set_z)
.def("stringfy", &Point::stringfy) .def("stringfy", &Point::stringfy);
.def("set_pointer", &Point::set_pointer);
py::exec(R"( py::exec(R"(
p = Point() p = Point()
@ -81,8 +74,6 @@ p.x = 10
p.y = 20 p.y = 20
p.z = 30 p.z = 30
assert p.stringfy() == '(10, 20, 30)' assert p.stringfy() == '(10, 20, 30)'
p.set_pointer(Point(4,5,6))
assert p.stringfy() == '(4, 5, 6)'
)"); )");
py::class_<Line> line(m, "Line"); py::class_<Line> line(m, "Line");

View File

@ -11,7 +11,7 @@
void c11_sbuf__ctor(c11_sbuf* self) { void c11_sbuf__ctor(c11_sbuf* self) {
c11_vector__ctor(&self->data, sizeof(char)); c11_vector__ctor(&self->data, sizeof(char));
c11_vector__reserve(&self->data, sizeof(c11_string) + 64); c11_vector__reserve(&self->data, sizeof(c11_string) + 100);
self->data.length = sizeof(c11_string); self->data.length = sizeof(c11_string);
} }

View File

@ -1091,11 +1091,6 @@ static void Ctx__dtor(Ctx* self) {
} }
c11_vector__dtor(&self->s_expr); c11_vector__dtor(&self->s_expr);
c11_smallmap_n2i__dtor(&self->global_names); c11_smallmap_n2i__dtor(&self->global_names);
// free the dedup map
c11__foreach(c11_smallmap_s2n_KV, &self->co_consts_string_dedup_map, p_kv) {
const char* p = p_kv->key.data;
PK_FREE((void*)p);
}
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map);
} }
@ -1206,25 +1201,16 @@ static int Ctx__add_varname(Ctx* self, py_Name name) {
} }
static int Ctx__add_const_string(Ctx* self, c11_sv key) { static int Ctx__add_const_string(Ctx* self, c11_sv key) {
if(key.size > 100) {
py_Ref tmp = c11_vector__emplace(&self->co->consts);
py_newstrv(tmp, key);
int index = self->co->consts.length - 1;
return index;
}
uint16_t* val = c11_smallmap_s2n__try_get(&self->co_consts_string_dedup_map, key); uint16_t* val = c11_smallmap_s2n__try_get(&self->co_consts_string_dedup_map, key);
if(val) { if(val) {
return *val; return *val;
} else { } else {
py_Ref tmp = c11_vector__emplace(&self->co->consts); py_TValue tmp;
py_newstrv(tmp, key); py_newstrv(&tmp, key);
c11_vector__push(py_TValue, &self->co->consts, tmp);
int index = self->co->consts.length - 1; int index = self->co->consts.length - 1;
// dedup
char* new_buf = PK_MALLOC(key.size + 1);
memcpy(new_buf, key.data, key.size);
new_buf[key.size] = 0;
c11_smallmap_s2n__set(&self->co_consts_string_dedup_map, c11_smallmap_s2n__set(&self->co_consts_string_dedup_map,
(c11_sv){new_buf, key.size}, c11_string__sv(PyObject__userdata(tmp._obj)),
index); index);
return index; return index;
} }

View File

@ -114,10 +114,10 @@ void Frame__set_unwind_target(py_Frame* self, py_TValue* sp) {
} }
} }
void Frame__gc_mark(py_Frame* self, c11_vector* p_stack) { void Frame__gc_mark(py_Frame* self) {
pk__mark_value(self->globals); pk__mark_value(self->globals);
if(self->is_locals_special) pk__mark_value(self->locals); if(self->is_locals_special) pk__mark_value(self->locals);
CodeObject__gc_mark(self->co, p_stack); CodeObject__gc_mark(self->co);
} }
int Frame__lineno(const py_Frame* self) { int Frame__lineno(const py_Frame* self) {

View File

@ -7,7 +7,6 @@
void ManagedHeap__ctor(ManagedHeap* self) { void ManagedHeap__ctor(ManagedHeap* self) {
MultiPool__ctor(&self->small_objects); MultiPool__ctor(&self->small_objects);
c11_vector__ctor(&self->large_objects, sizeof(PyObject*)); c11_vector__ctor(&self->large_objects, sizeof(PyObject*));
c11_vector__ctor(&self->gc_roots, sizeof(PyObject*));
for(int i = 0; i < c11__count_array(self->freed_ma); i++) { for(int i = 0; i < c11__count_array(self->freed_ma); i++) {
self->freed_ma[i] = PK_GC_MIN_THRESHOLD; self->freed_ma[i] = PK_GC_MIN_THRESHOLD;
@ -27,7 +26,6 @@ void ManagedHeap__dtor(ManagedHeap* self) {
PK_FREE(obj); PK_FREE(obj);
} }
c11_vector__dtor(&self->large_objects); c11_vector__dtor(&self->large_objects);
c11_vector__dtor(&self->gc_roots);
} }
void ManagedHeap__collect_if_needed(ManagedHeap* self) { void ManagedHeap__collect_if_needed(ManagedHeap* self) {
@ -40,9 +38,9 @@ void ManagedHeap__collect_if_needed(ManagedHeap* self) {
self->freed_ma[1] = self->freed_ma[2]; self->freed_ma[1] = self->freed_ma[2];
self->freed_ma[2] = freed; self->freed_ma[2] = freed;
int avg_freed = (self->freed_ma[0] + self->freed_ma[1] + self->freed_ma[2]) / 3; int avg_freed = (self->freed_ma[0] + self->freed_ma[1] + self->freed_ma[2]) / 3;
const int upper = PK_GC_MIN_THRESHOLD * 8; const int upper = PK_GC_MIN_THRESHOLD * 2;
const int lower = PK_GC_MIN_THRESHOLD / 2; const int lower = PK_GC_MIN_THRESHOLD / 2;
float free_ratio = (float)avg_freed / self->gc_threshold; float free_ratio = (float)avg_freed / PK_GC_MIN_THRESHOLD;
int new_threshold = self->gc_threshold * (1 / free_ratio); int new_threshold = self->gc_threshold * (1 / free_ratio);
// printf("gc_threshold=%d, avg_freed=%d, new_threshold=%d\n", self->gc_threshold, avg_freed, new_threshold); // printf("gc_threshold=%d, avg_freed=%d, new_threshold=%d\n", self->gc_threshold, avg_freed, new_threshold);
self->gc_threshold = c11__min(c11__max(new_threshold, lower), upper); self->gc_threshold = c11__min(c11__max(new_threshold, lower), upper);

View File

@ -59,7 +59,7 @@ void VM__ctor(VM* self) {
self->top_frame = NULL; self->top_frame = NULL;
InternedNames__ctor(&self->names); InternedNames__ctor(&self->names);
ModuleDict__ctor(&self->modules, "", *py_NIL()); ModuleDict__ctor(&self->modules, NULL, *py_NIL());
TypeList__ctor(&self->types); TypeList__ctor(&self->types);
self->builtins = *py_NIL(); self->builtins = *py_NIL();
@ -88,6 +88,12 @@ void VM__ctor(VM* self) {
ValueStack__ctor(&self->stack); ValueStack__ctor(&self->stack);
/* Init Builtin Types */ /* Init Builtin Types */
for(int i = 0; i < 128; i++) {
char* p = py_newstrn(&self->ascii_literals[i], 1);
*p = i;
}
py_newstrn(&self->ascii_literals[128], 0); // empty string
// 0: unused // 0: unused
void* placeholder = TypeList__emplace(&self->types); void* placeholder = TypeList__emplace(&self->types);
memset(placeholder, 0, sizeof(py_TypeInfo)); memset(placeholder, 0, sizeof(py_TypeInfo));
@ -600,36 +606,94 @@ void PyObject__dtor(PyObject* self) {
if(self->slots == -1) NameDict__dtor(PyObject__dict(self)); if(self->slots == -1) NameDict__dtor(PyObject__dict(self));
} }
void FuncDecl__gc_mark(const FuncDecl* self, c11_vector* p_stack) { void PyObject__mark(PyObject* obj) {
CodeObject__gc_mark(&self->code, p_stack); assert(!obj->gc_marked);
obj->gc_marked = true;
if(obj->slots > 0) {
py_TValue* p = PyObject__slots(obj);
for(int i = 0; i < obj->slots; i++)
pk__mark_value(p + i);
} else if(obj->slots == -1) {
NameDict* namedict = PyObject__dict(obj);
for(int i = 0; i < namedict->length; i++) {
NameDict_KV* kv = c11__at(NameDict_KV, namedict, i);
pk__mark_value(&kv->value);
}
}
void* ud = PyObject__userdata(obj);
switch(obj->type) {
case tp_list: {
List* self = ud;
for(int i = 0; i < self->length; i++) {
pk__mark_value(c11__at(py_TValue, self, i));
}
break;
}
case tp_dict: {
Dict* self = ud;
for(int i = 0; i < self->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
pk__mark_value(&entry->key);
pk__mark_value(&entry->val);
}
break;
}
case tp_generator: {
Generator* self = ud;
if(self->frame) Frame__gc_mark(self->frame);
break;
}
case tp_function: {
function__gc_mark(ud);
break;
}
case tp_code: {
CodeObject* self = ud;
CodeObject__gc_mark(self);
break;
}
case tp_chunked_array2d: {
c11_chunked_array2d__mark(ud);
}
default: return;
}
}
void FuncDecl__gc_mark(const FuncDecl* self) {
CodeObject__gc_mark(&self->code);
for(int j = 0; j < self->kwargs.length; j++) { for(int j = 0; j < self->kwargs.length; j++) {
FuncDeclKwArg* kw = c11__at(FuncDeclKwArg, &self->kwargs, j); FuncDeclKwArg* kw = c11__at(FuncDeclKwArg, &self->kwargs, j);
pk__mark_value(&kw->value); pk__mark_value(&kw->value);
} }
} }
void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack) { void CodeObject__gc_mark(const CodeObject* self) {
for(int i = 0; i < self->consts.length; i++) { for(int i = 0; i < self->consts.length; i++) {
py_TValue* p = c11__at(py_TValue, &self->consts, i); py_TValue* p = c11__at(py_TValue, &self->consts, i);
pk__mark_value(p); pk__mark_value(p);
} }
for(int i = 0; i < self->func_decls.length; i++) { for(int i = 0; i < self->func_decls.length; i++) {
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i); FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
FuncDecl__gc_mark(decl, p_stack); FuncDecl__gc_mark(decl);
} }
} }
void ManagedHeap__mark(ManagedHeap* self) { void ManagedHeap__mark(ManagedHeap* self) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
c11_vector* p_stack = &self->gc_roots;
assert(p_stack->length == 0);
// mark value stack // mark value stack
for(py_TValue* p = vm->stack.begin; p != vm->stack.end; p++) { for(py_TValue* p = vm->stack.begin; p != vm->stack.end; p++) {
pk__mark_value(p); pk__mark_value(p);
} }
// mark ascii literals
for(int i = 0; i < c11__count_array(vm->ascii_literals); i++) {
pk__mark_value(&vm->ascii_literals[i]);
}
// mark modules // mark modules
ModuleDict__apply_mark(&vm->modules, p_stack); ModuleDict__apply_mark(&vm->modules);
// mark types // mark types
int types_length = vm->types.length; int types_length = vm->types.length;
// 0-th type is placeholder // 0-th type is placeholder
@ -656,7 +720,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
} }
// mark frame // mark frame
for(py_Frame* frame = vm->top_frame; frame; frame = frame->f_back) { for(py_Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
Frame__gc_mark(frame, p_stack); Frame__gc_mark(frame);
} }
// mark vm's registers // mark vm's registers
pk__mark_value(&vm->last_retval); pk__mark_value(&vm->last_retval);
@ -669,66 +733,6 @@ void ManagedHeap__mark(ManagedHeap* self) {
RInternedEntry* entry = c11__at(RInternedEntry, &vm->names.r_interned, i); RInternedEntry* entry = c11__at(RInternedEntry, &vm->names.r_interned, i);
pk__mark_value(&entry->obj); pk__mark_value(&entry->obj);
} }
/*****************************/
while(p_stack->length > 0) {
PyObject* obj = c11_vector__back(PyObject*, p_stack);
c11_vector__pop(p_stack);
assert(obj->gc_marked);
if(obj->slots > 0) {
py_TValue* p = PyObject__slots(obj);
for(int i = 0; i < obj->slots; i++)
pk__mark_value(p + i);
} else if(obj->slots == -1) {
NameDict* namedict = PyObject__dict(obj);
for(int i = 0; i < namedict->length; i++) {
NameDict_KV* kv = c11__at(NameDict_KV, namedict, i);
pk__mark_value(&kv->value);
}
}
void* ud = PyObject__userdata(obj);
switch(obj->type) {
case tp_list: {
List* self = ud;
for(int i = 0; i < self->length; i++) {
py_TValue* val = c11__at(py_TValue, self, i);
pk__mark_value(val);
}
break;
}
case tp_dict: {
Dict* self = ud;
for(int i = 0; i < self->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
pk__mark_value(&entry->key);
pk__mark_value(&entry->val);
}
break;
}
case tp_generator: {
Generator* self = ud;
if(self->frame) Frame__gc_mark(self->frame, p_stack);
break;
}
case tp_function: {
function__gc_mark(ud, p_stack);
break;
}
case tp_code: {
CodeObject* self = ud;
CodeObject__gc_mark(self, p_stack);
break;
}
case tp_chunked_array2d: {
c11_chunked_array2d__mark(ud, p_stack);
break;
}
}
}
} }
void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte) { void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte) {

View File

@ -1222,7 +1222,7 @@ void c11_chunked_array2d__dtor(c11_chunked_array2d* self) {
c11_chunked_array2d_chunks__dtor(&self->chunks); c11_chunked_array2d_chunks__dtor(&self->chunks);
} }
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack) { void c11_chunked_array2d__mark(void* ud) {
c11_chunked_array2d* self = ud; c11_chunked_array2d* self = ud;
pk__mark_value(&self->default_T); pk__mark_value(&self->default_T);
pk__mark_value(&self->context_builder); pk__mark_value(&self->context_builder);

View File

@ -9,11 +9,7 @@
#undef SMALLMAP_T__SOURCE #undef SMALLMAP_T__SOURCE
void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) { void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) {
assert(path != NULL); self->path = path;
int length = strlen(path);
assert(length <= PK_MAX_MODULE_PATH_LEN);
memcpy(self->path, path, length);
self->path[length] = '\0';
self->module = module; self->module = module;
self->left = NULL; self->left = NULL;
self->right = NULL; self->right = NULL;
@ -31,7 +27,10 @@ void ModuleDict__dtor(ModuleDict* self) {
} }
void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val) { void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val) {
assert(key != NULL); if(self->path == NULL) {
self->path = key;
self->module = val;
}
int cmp = strcmp(key, self->path); int cmp = strcmp(key, self->path);
if(cmp < 0) { if(cmp < 0) {
if(self->left) { if(self->left) {
@ -53,7 +52,7 @@ void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val) {
} }
py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path) { py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path) {
assert(path != NULL); if(self->path == NULL) return NULL;
int cmp = strcmp(path, self->path); int cmp = strcmp(path, self->path);
if(cmp < 0) { if(cmp < 0) {
if(self->left) { if(self->left) {
@ -73,20 +72,11 @@ py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path) {
} }
bool ModuleDict__contains(ModuleDict* self, const char* path) { bool ModuleDict__contains(ModuleDict* self, const char* path) {
assert(path != NULL);
return ModuleDict__try_get(self, path) != NULL; return ModuleDict__try_get(self, path) != NULL;
} }
void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack) { void ModuleDict__apply_mark(ModuleDict *self) {
if(!py_isnil(&self->module)) { if(!self->module._obj->gc_marked) PyObject__mark(self->module._obj);
// root node is dummy if(self->left) ModuleDict__apply_mark(self->left);
PyObject* obj = self->module._obj; if(self->right) ModuleDict__apply_mark(self->right);
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);
} }

View File

@ -450,11 +450,15 @@ static bool builtins_chr(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int); PY_CHECK_ARG_TYPE(0, tp_int);
uint32_t val = py_toint(py_arg(0)); uint32_t val = py_toint(py_arg(0));
if(val >= 0 && val < 128) {
py_assign(py_retval(), &pk_current_vm->ascii_literals[val]);
} else {
// convert to utf-8 // convert to utf-8
char utf8[4]; char utf8[4];
int len = c11__u32_to_u8(val, utf8); int len = c11__u32_to_u8(val, utf8);
if(len == -1) return ValueError("invalid unicode code point: %d", val); if(len == -1) return ValueError("invalid unicode code point: %d", val);
py_newstrv(py_retval(), (c11_sv){utf8, len}); py_newstrv(py_retval(), (c11_sv){utf8, len});
}
return true; return true;
} }
@ -755,7 +759,7 @@ py_TValue pk_builtins__register() {
return *builtins; return *builtins;
} }
void function__gc_mark(void* ud, c11_vector* p_stack) { void function__gc_mark(void* ud) {
Function* func = ud; Function* func = ud;
if(func->globals) pk__mark_value(func->globals); if(func->globals) pk__mark_value(func->globals);
if(func->closure) { if(func->closure) {
@ -765,7 +769,7 @@ void function__gc_mark(void* ud, c11_vector* p_stack) {
pk__mark_value(&kv->value); pk__mark_value(&kv->value);
} }
} }
FuncDecl__gc_mark(func->decl, p_stack); FuncDecl__gc_mark(func->decl);
} }
static bool function__doc__(int argc, py_Ref argv) { static bool function__doc__(int argc, py_Ref argv) {

View File

@ -9,13 +9,6 @@ bool py_isidentical(py_Ref lhs, py_Ref rhs) {
case tp_int: return lhs->_i64 == rhs->_i64; case tp_int: return lhs->_i64 == rhs->_i64;
case tp_float: return lhs->_f64 == rhs->_f64; case tp_float: return lhs->_f64 == rhs->_f64;
case tp_bool: return lhs->_bool == rhs->_bool; case tp_bool: return lhs->_bool == rhs->_bool;
case tp_str: {
if(lhs->is_ptr && rhs->is_ptr) {
return lhs->_obj == rhs->_obj;
} else {
return strcmp(lhs->_chars, rhs->_chars) == 0;
}
}
case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc; case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc;
case tp_NoneType: return true; case tp_NoneType: return true;
case tp_NotImplementedType: return true; case tp_NotImplementedType: return true;

View File

@ -9,13 +9,6 @@
void py_newstr(py_Ref out, const char* data) { py_newstrv(out, (c11_sv){data, strlen(data)}); } void py_newstr(py_Ref out, const char* data) { py_newstrv(out, (c11_sv){data, strlen(data)}); }
char* py_newstrn(py_Ref out, int size) { char* py_newstrn(py_Ref out, int size) {
if(size < 8) {
out->type = tp_str;
out->is_ptr = false;
c11_string* ud = (c11_string*)(&out->extra);
c11_string__ctor3(ud, size);
return ud->data;
}
ManagedHeap* heap = &pk_current_vm->heap; ManagedHeap* heap = &pk_current_vm->heap;
int total_size = sizeof(c11_string) + size + 1; int total_size = sizeof(c11_string) + size + 1;
PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size); PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size);
@ -28,6 +21,17 @@ char* py_newstrn(py_Ref out, int size) {
} }
void py_newstrv(py_OutRef out, c11_sv sv) { void py_newstrv(py_OutRef out, c11_sv sv) {
if(sv.size == 0) {
*out = pk_current_vm->ascii_literals[128];
return;
}
if(sv.size == 1) {
int c = sv.data[0];
if(c >= 0 && c < 128) {
*out = pk_current_vm->ascii_literals[c];
return;
}
}
char* data = py_newstrn(out, sv.size); char* data = py_newstrn(out, sv.size);
memcpy(data, sv.data, sv.size); memcpy(data, sv.data, sv.size);
} }
@ -54,25 +58,22 @@ unsigned char* py_newbytes(py_Ref out, int size) {
return ud->data; return ud->data;
} }
c11_string* pk_tostr(py_Ref self) { const char* py_tostr(py_Ref self) {
assert(self->type == tp_str); assert(self->type == tp_str);
if(!self->is_ptr) { c11_string* ud = PyObject__userdata(self->_obj);
return (c11_string*)(&self->extra); return ud->data;
} else {
return PyObject__userdata(self->_obj);
}
} }
const char* py_tostr(py_Ref self) { return pk_tostr(self)->data; }
const char* py_tostrn(py_Ref self, int* size) { const char* py_tostrn(py_Ref self, int* size) {
c11_string* ud = pk_tostr(self); assert(self->type == tp_str);
c11_string* ud = PyObject__userdata(self->_obj);
*size = ud->size; *size = ud->size;
return ud->data; return ud->data;
} }
c11_sv py_tosv(py_Ref self) { c11_sv py_tosv(py_Ref self) {
c11_string* ud = pk_tostr(self); assert(self->type == tp_str);
c11_string* ud = PyObject__userdata(self->_obj);
return c11_string__sv(ud); return c11_string__sv(ud);
} }
@ -115,28 +116,32 @@ static bool str__hash__(int argc, py_Ref argv) {
static bool str__len__(int argc, py_Ref argv) { static bool str__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
py_newint(py_retval(), c11_sv__u8_length((c11_sv){self->data, self->size})); py_newint(py_retval(), c11_sv__u8_length((c11_sv){self->data, self->size}));
return true; return true;
} }
static bool str__add__(int argc, py_Ref argv) { static bool str__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_str) { if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval()); py_newnotimplemented(py_retval());
} else { } else {
c11_string* other = pk_tostr(&argv[1]); c11_string* other = py_touserdata(&argv[1]);
char* p = py_newstrn(py_retval(), self->size + other->size); int total_size = sizeof(c11_string) + self->size + other->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size + other->size;
char* p = res->data;
memcpy(p, self->data, self->size); memcpy(p, self->data, self->size);
memcpy(p + self->size, other->data, other->size); memcpy(p + self->size, other->data, other->size);
p[res->size] = '\0';
} }
return true; return true;
} }
static bool str__mul__(int argc, py_Ref argv) { static bool str__mul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_int) { if(py_arg(1)->type != tp_int) {
py_newnotimplemented(py_retval()); py_newnotimplemented(py_retval());
} else { } else {
@ -144,10 +149,14 @@ static bool str__mul__(int argc, py_Ref argv) {
if(n <= 0) { if(n <= 0) {
py_newstr(py_retval(), ""); py_newstr(py_retval(), "");
} else { } else {
char* p = py_newstrn(py_retval(), self->size * n); int total_size = sizeof(c11_string) + self->size * n + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size * n;
char* p = res->data;
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
memcpy(p + i * self->size, self->data, self->size); memcpy(p + i * self->size, self->data, self->size);
} }
p[res->size] = '\0';
} }
} }
return true; return true;
@ -157,11 +166,11 @@ static bool str__rmul__(int argc, py_Ref argv) { return str__mul__(argc, argv);
static bool str__contains__(int argc, py_Ref argv) { static bool str__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_str) { if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval()); py_newnotimplemented(py_retval());
} else { } else {
c11_string* other = pk_tostr(&argv[1]); c11_string* other = py_touserdata(&argv[1]);
const char* p = strstr(self->data, other->data); const char* p = strstr(self->data, other->data);
py_newbool(py_retval(), p != NULL); py_newbool(py_retval(), p != NULL);
} }
@ -193,7 +202,7 @@ static bool str__iter__(int argc, py_Ref argv) {
static bool str__getitem__(int argc, py_Ref argv) { static bool str__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
py_Ref _1 = py_arg(1); py_Ref _1 = py_arg(1);
if(_1->type == tp_int) { if(_1->type == tp_int) {
int index = py_toint(py_arg(1)); int index = py_toint(py_arg(1));
@ -217,11 +226,11 @@ static bool str__getitem__(int argc, py_Ref argv) {
#define DEF_STR_CMP_OP(op, __f, __cond) \ #define DEF_STR_CMP_OP(op, __f, __cond) \
static bool str##op(int argc, py_Ref argv) { \ static bool str##op(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \ PY_CHECK_ARGC(2); \
c11_string* self = pk_tostr(&argv[0]); \ c11_string* self = py_touserdata(&argv[0]); \
if(py_arg(1)->type != tp_str) { \ if(py_arg(1)->type != tp_str) { \
py_newnotimplemented(py_retval()); \ py_newnotimplemented(py_retval()); \
} else { \ } else { \
c11_string* other = pk_tostr(&argv[1]); \ c11_string* other = py_touserdata(&argv[1]); \
int res = __f(c11_string__sv(self), c11_string__sv(other)); \ int res = __f(c11_string__sv(self), c11_string__sv(other)); \
py_newbool(py_retval(), __cond); \ py_newbool(py_retval(), __cond); \
} \ } \
@ -239,47 +248,55 @@ DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
static bool str_lower(int argc, py_Ref argv) { static bool str_lower(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
char* p = py_newstrn(py_retval(), self->size); int total_size = sizeof(c11_string) + self->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size;
char* p = res->data;
for(int i = 0; i < self->size; i++) { for(int i = 0; i < self->size; i++) {
char c = self->data[i]; char c = self->data[i];
p[i] = c >= 'A' && c <= 'Z' ? c + 32 : c; p[i] = c >= 'A' && c <= 'Z' ? c + 32 : c;
} }
p[res->size] = '\0';
return true; return true;
} }
static bool str_upper(int argc, py_Ref argv) { static bool str_upper(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
char* p = py_newstrn(py_retval(), self->size); int total_size = sizeof(c11_string) + self->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size;
char* p = res->data;
for(int i = 0; i < self->size; i++) { for(int i = 0; i < self->size; i++) {
char c = self->data[i]; char c = self->data[i];
p[i] = c >= 'a' && c <= 'z' ? c - 32 : c; p[i] = c >= 'a' && c <= 'z' ? c - 32 : c;
} }
p[res->size] = '\0';
return true; return true;
} }
static bool str_startswith(int argc, py_Ref argv) { static bool str_startswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = pk_tostr(&argv[1]); c11_string* other = py_touserdata(&argv[1]);
py_newbool(py_retval(), c11_sv__startswith(c11_string__sv(self), c11_string__sv(other))); py_newbool(py_retval(), c11_sv__startswith(c11_string__sv(self), c11_string__sv(other)));
return true; return true;
} }
static bool str_endswith(int argc, py_Ref argv) { static bool str_endswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = pk_tostr(&argv[1]); c11_string* other = py_touserdata(&argv[1]);
py_newbool(py_retval(), c11_sv__endswith(c11_string__sv(self), c11_string__sv(other))); py_newbool(py_retval(), c11_sv__endswith(c11_string__sv(self), c11_string__sv(other)));
return true; return true;
} }
static bool str_join(int argc, py_Ref argv) { static bool str_join(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(argv)); c11_sv self = c11_string__sv(py_touserdata(argv));
if(!py_iter(py_arg(1))) return false; if(!py_iter(py_arg(1))) return false;
py_push(py_retval()); // iter py_push(py_retval()); // iter
@ -301,7 +318,7 @@ static bool str_join(int argc, py_Ref argv) {
c11_sbuf__dtor(&buf); c11_sbuf__dtor(&buf);
return false; return false;
} }
c11_string* item = pk_tostr(py_retval()); c11_string* item = py_touserdata(py_retval());
c11_sbuf__write_cstrn(&buf, item->data, item->size); c11_sbuf__write_cstrn(&buf, item->data, item->size);
first = false; first = false;
} }
@ -313,11 +330,11 @@ static bool str_join(int argc, py_Ref argv) {
static bool str_replace(int argc, py_Ref argv) { static bool str_replace(int argc, py_Ref argv) {
PY_CHECK_ARGC(3); PY_CHECK_ARGC(3);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_str); PY_CHECK_ARG_TYPE(2, tp_str);
c11_string* old = pk_tostr(&argv[1]); c11_string* old = py_touserdata(&argv[1]);
c11_string* new_ = pk_tostr(&argv[2]); c11_string* new_ = py_touserdata(&argv[2]);
c11_string* res = c11_string* res =
c11_sv__replace2(c11_string__sv(self), c11_string__sv(old), c11_string__sv(new_)); c11_sv__replace2(c11_string__sv(self), c11_string__sv(old), c11_string__sv(new_));
py_newstrv(py_retval(), (c11_sv){res->data, res->size}); py_newstrv(py_retval(), (c11_sv){res->data, res->size});
@ -326,7 +343,7 @@ static bool str_replace(int argc, py_Ref argv) {
} }
static bool str_split(int argc, py_Ref argv) { static bool str_split(int argc, py_Ref argv) {
c11_sv self = c11_string__sv(pk_tostr(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
c11_vector res; c11_vector res;
bool discard_empty = false; bool discard_empty = false;
if(argc > 2) return TypeError("split() takes at most 2 arguments"); if(argc > 2) return TypeError("split() takes at most 2 arguments");
@ -338,7 +355,7 @@ static bool str_split(int argc, py_Ref argv) {
if(argc == 2) { if(argc == 2) {
// sep = argv[1] // sep = argv[1]
if(!py_checkstr(&argv[1])) return false; if(!py_checkstr(&argv[1])) return false;
c11_sv sep = c11_string__sv(pk_tostr(&argv[1])); c11_sv sep = c11_string__sv(py_touserdata(&argv[1]));
if(sep.size == 0) return ValueError("empty separator"); if(sep.size == 0) return ValueError("empty separator");
res = c11_sv__split2(self, sep); res = c11_sv__split2(self, sep);
} }
@ -354,22 +371,22 @@ static bool str_split(int argc, py_Ref argv) {
static bool str_count(int argc, py_Ref argv) { static bool str_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* sub = pk_tostr(&argv[1]); c11_string* sub = py_touserdata(&argv[1]);
int res = c11_sv__count(c11_string__sv(self), c11_string__sv(sub)); int res = c11_sv__count(c11_string__sv(self), c11_string__sv(sub));
py_newint(py_retval(), res); py_newint(py_retval(), res);
return true; return true;
} }
static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) { static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
c11_sv self = c11_string__sv(pk_tostr(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
c11_sv chars; c11_sv chars;
if(argc == 1) { if(argc == 1) {
chars = (c11_sv){" \t\n\r", 4}; chars = (c11_sv){" \t\n\r", 4};
} else if(argc == 2) { } else if(argc == 2) {
if(!py_checkstr(&argv[1])) return false; if(!py_checkstr(&argv[1])) return false;
chars = c11_string__sv(pk_tostr(&argv[1])); chars = c11_string__sv(py_touserdata(&argv[1]));
} else { } else {
return TypeError("strip() takes at most 2 arguments"); return TypeError("strip() takes at most 2 arguments");
} }
@ -386,7 +403,7 @@ static bool str_rstrip(int argc, py_Ref argv) { return str__strip_impl(false, tr
static bool str_zfill(int argc, py_Ref argv) { static bool str_zfill(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
PY_CHECK_ARG_TYPE(1, tp_int); PY_CHECK_ARG_TYPE(1, tp_int);
int width = py_toint(py_arg(1)); int width = py_toint(py_arg(1));
int delta = width - c11_sv__u8_length(self); int delta = width - c11_sv__u8_length(self);
@ -411,12 +428,12 @@ static bool str__widthjust_impl(bool left, int argc, py_Ref argv) {
pad = ' '; pad = ' ';
} else { } else {
if(!py_checkstr(&argv[2])) return false; if(!py_checkstr(&argv[2])) return false;
c11_string* padstr = pk_tostr(&argv[2]); c11_string* padstr = py_touserdata(&argv[2]);
if(padstr->size != 1) if(padstr->size != 1)
return TypeError("The fill character must be exactly one character long"); return TypeError("The fill character must be exactly one character long");
pad = padstr->data[0]; pad = padstr->data[0];
} }
c11_sv self = c11_string__sv(pk_tostr(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
PY_CHECK_ARG_TYPE(1, tp_int); PY_CHECK_ARG_TYPE(1, tp_int);
int width = py_toint(py_arg(1)); int width = py_toint(py_arg(1));
if(width <= self.size) { if(width <= self.size) {
@ -451,9 +468,9 @@ static bool str_find(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(2, tp_int); PY_CHECK_ARG_TYPE(2, tp_int);
start = py_toint(py_arg(2)); start = py_toint(py_arg(2));
} }
c11_string* self = pk_tostr(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* sub = pk_tostr(&argv[1]); c11_string* sub = py_touserdata(&argv[1]);
int res = c11_sv__index2(c11_string__sv(self), c11_string__sv(sub), start); int res = c11_sv__index2(c11_string__sv(self), c11_string__sv(sub), start);
py_newint(py_retval(), res); py_newint(py_retval(), res);
return true; return true;

View File

@ -190,7 +190,7 @@ assert (1 != '1') is True
assert (1 == '1') is False assert (1 == '1') is False
assert 1 == 1.0 assert 1 == 1.0
assert chr(97) == 'a' assert chr(97) is 'a'
assert ord('a') == 97 assert ord('a') == 97
assert ord('🥕') == 0x1f955 assert ord('🥕') == 0x1f955