From b89414a5d7f74da5f9f54f52edc99ef5aaff52e2 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Wed, 10 Jul 2024 01:19:56 +0800 Subject: [PATCH] ... --- include/pocketpy/interpreter/vm.h | 24 ++++----- include/pocketpy/pocketpy.h | 7 +++ src/interpreter/vm.c | 90 ++++++++++++++++--------------- src/public/modules.c | 9 ++-- src/public/py_array.c | 3 +- src/public/py_exception.c | 12 +++-- src/public/py_list.c | 8 ++- src/public/py_object.c | 8 ++- src/public/py_range.c | 6 +-- src/public/py_slice.c | 14 +++-- src/public/py_str.c | 10 ++-- src/public/py_tuple.c | 3 +- 12 files changed, 99 insertions(+), 95 deletions(-) diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 678ce84f..f801c3c9 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -15,10 +15,11 @@ typedef struct pk_TypeInfo { py_TValue self; py_TValue module; // the module where the type is defined - bool subclass_enabled; + + bool is_python; // is it a python class? (not derived from c object) + bool is_sealed; // can it be subclassed? void (*dtor)(void*); - void (*gc_mark)(void*); c11_vector /*T=py_Name*/ annotated_fields; @@ -28,14 +29,6 @@ typedef struct pk_TypeInfo { py_TValue magic[64]; } pk_TypeInfo; -void pk_TypeInfo__ctor(pk_TypeInfo* self, - py_Name name, - py_Type index, - py_Type base, - const py_TValue* module, - bool subclass_enabled); -void pk_TypeInfo__dtor(pk_TypeInfo* self); - typedef struct pk_VM { Frame* top_frame; @@ -82,11 +75,12 @@ typedef enum pk_FrameResult { pk_FrameResult pk_VM__run_top_frame(pk_VM* self); -py_Type pk_VM__new_type(pk_VM* self, - const char* name, - py_Type base, - const py_TValue* module, - bool subclass_enabled); +py_Type pk_newtype(const char* name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed); pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall); diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 6ec12130..503bdab6 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -92,6 +92,13 @@ void py_newslice(py_Ref); // old style argc-based function void py_newnativefunc(py_Ref out, py_CFunction); +/// Create a new type. +/// @param name name of the type. +/// @param base base type. +/// @param module module where the type is defined. Use NULL for built-in types. +/// @param dtor destructor function. Use NULL if not needed. +py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)); + /// Create a new object. /// @param out output reference. /// @param type type of the object. diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 7d058da4..29ca621c 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -27,12 +27,11 @@ static void pk_default_stderr(const char* fmt, ...) { fflush(stderr); } -void pk_TypeInfo__ctor(pk_TypeInfo* self, - py_Name name, - py_Type index, - py_Type base, - const py_TValue* module, - bool subclass_enabled) { +static void pk_TypeInfo__ctor(pk_TypeInfo* self, + py_Name name, + py_Type index, + py_Type base, + const py_TValue* module) { memset(self, 0, sizeof(pk_TypeInfo)); self->name = name; @@ -49,12 +48,10 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self, }; self->module = module ? *module : PY_NIL; - self->subclass_enabled = subclass_enabled; - c11_vector__ctor(&self->annotated_fields, sizeof(py_Name)); } -void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); } +static void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); } void pk_VM__ctor(pk_VM* self) { self->top_frame = NULL; @@ -82,17 +79,19 @@ void pk_VM__ctor(pk_VM* self) { /* Init Builtin Types */ // 0: unused - pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, 0, NULL, false); + void* placeholder = c11_vector__emplace(&self->types); + memset(placeholder, 0, sizeof(pk_TypeInfo)); + #define validate(t, expr) \ if(t != (expr)) abort() - validate(tp_object, pk_VM__new_type(self, "object", 0, NULL, true)); - validate(tp_type, pk_VM__new_type(self, "type", 1, NULL, false)); + validate(tp_object, pk_newtype("object", 0, NULL, NULL, true, false)); + validate(tp_type, pk_newtype("type", 1, NULL, NULL, false, true)); pk_object__register(); - validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false)); - validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false)); - validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false)); + validate(tp_int, pk_newtype("int", tp_object, NULL, NULL, false, true)); + validate(tp_float, pk_newtype("float", tp_object, NULL, NULL, false, true)); + validate(tp_bool, pk_newtype("bool", tp_object, NULL, NULL, false, true)); pk_number__register(); validate(tp_str, pk_str__register()); @@ -105,32 +104,32 @@ void pk_VM__ctor(pk_VM* self) { validate(tp_slice, pk_slice__register()); validate(tp_range, pk_range__register()); validate(tp_range_iterator, pk_range_iterator__register()); - validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false)); + validate(tp_module, pk_newtype("module", tp_object, NULL, NULL, false, true)); validate(tp_function, pk_function__register()); validate(tp_nativefunc, pk_nativefunc__register()); - validate(tp_boundmethod, pk_VM__new_type(self, "boundmethod", tp_object, NULL, false)); + validate(tp_boundmethod, pk_newtype("boundmethod", tp_object, NULL, NULL, false, true)); - validate(tp_super, pk_VM__new_type(self, "super", tp_object, NULL, false)); + validate(tp_super, pk_newtype("super", tp_object, NULL, NULL, false, true)); validate(tp_BaseException, pk_BaseException__register()); validate(tp_Exception, pk_Exception__register()); validate(tp_bytes, pk_bytes__register()); - validate(tp_mappingproxy, pk_VM__new_type(self, "mappingproxy", tp_object, NULL, false)); + validate(tp_mappingproxy, pk_newtype("mappingproxy", tp_object, NULL, NULL, false, true)); - validate(tp_dict, pk_VM__new_type(self, "dict", tp_object, NULL, true)); - validate(tp_property, pk_VM__new_type(self, "property", tp_object, NULL, false)); - validate(tp_star_wrapper, pk_VM__new_type(self, "star_wrapper", tp_object, NULL, false)); + validate(tp_dict, pk_newtype("dict", tp_object, NULL, NULL, false, false)); + validate(tp_property, pk_newtype("property", tp_object, NULL, NULL, false, true)); + validate(tp_star_wrapper, pk_newtype("star_wrapper", tp_object, NULL, NULL, false, true)); - validate(tp_staticmethod, pk_VM__new_type(self, "staticmethod", tp_object, NULL, false)); - validate(tp_classmethod, pk_VM__new_type(self, "classmethod", tp_object, NULL, false)); + validate(tp_staticmethod, pk_newtype("staticmethod", tp_object, NULL, NULL, false, true)); + validate(tp_classmethod, pk_newtype("classmethod", tp_object, NULL, NULL, false, true)); - validate(tp_NoneType, pk_VM__new_type(self, "NoneType", tp_object, NULL, false)); + validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true)); validate(tp_NotImplementedType, - pk_VM__new_type(self, "NotImplementedType", tp_object, NULL, false)); - validate(tp_ellipsis, pk_VM__new_type(self, "ellipsis", tp_object, NULL, false)); + pk_newtype("NotImplementedType", tp_object, NULL, NULL, false, true)); + validate(tp_ellipsis, pk_newtype("ellipsis", tp_object, NULL, NULL, false, true)); - validate(tp_SyntaxError, pk_VM__new_type(self, "SyntaxError", tp_Exception, NULL, false)); - validate(tp_StopIteration, pk_VM__new_type(self, "StopIteration", tp_Exception, NULL, false)); + validate(tp_SyntaxError, pk_newtype("SyntaxError", tp_Exception, NULL, NULL, false, true)); + validate(tp_StopIteration, pk_newtype("StopIteration", tp_Exception, NULL, NULL, false, true)); #undef validate self->builtins = pk_builtins__register(); @@ -174,6 +173,7 @@ void pk_VM__dtor(pk_VM* self) { // clear frames // ... pk_NameDict__dtor(&self->modules); + c11__foreach(pk_TypeInfo, &self->types, ti) pk_TypeInfo__dtor(ti); c11_vector__dtor(&self->types); ValueStack__clear(&self->stack); } @@ -255,22 +255,28 @@ bool pk__normalize_index(int* index, int length) { return true; } -py_Type pk_VM__new_type(pk_VM* self, - const char* name, - py_Type base, - const py_TValue* module, - bool subclass_enabled) { - py_Type index = self->types.count; - pk_TypeInfo* ti = c11_vector__emplace(&self->types); - pk_TypeInfo__ctor(ti, py_name(name), index, base, module, subclass_enabled); +py_Type pk_newtype(const char* name, + py_Type base, + const py_GlobalRef module, + void (*dtor)(void*), + bool is_python, + bool is_sealed) { + c11_vector* types = &pk_current_vm->types; + py_Type index = types->count; + pk_TypeInfo* ti = c11_vector__emplace(types); + pk_TypeInfo__ctor(ti, py_name(name), index, base, module); + ti->dtor = dtor; + ti->is_python = is_python; + ti->is_sealed = is_sealed; return index; } -bool __prepare_py_call(py_TValue* buffer, - py_Ref argv, - py_Ref p1, - int kwargc, - const FuncDecl* decl) { +py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) { + return pk_newtype(name, base, module, dtor, false, false); +} + +static bool + __prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) { const CodeObject* co = &decl->code; int decl_argc = decl->args.count; diff --git a/src/public/modules.c b/src/public/modules.c index a22f5862..f23711b2 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -163,10 +163,8 @@ py_TValue pk_builtins__register() { } py_Type pk_function__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "function", tp_object, NULL, false); - pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type); - ti->dtor = (void (*)(void*))Function__dtor; + py_Type type = + pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true); return type; } @@ -177,8 +175,7 @@ static bool _py_nativefunc__repr(int argc, py_Ref argv) { } py_Type pk_nativefunc__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "nativefunc", tp_object, NULL, false); + py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true); py_bindmagic(type, __repr__, _py_nativefunc__repr); return type; } \ No newline at end of file diff --git a/src/public/py_array.c b/src/public/py_array.c index ebf6b3c8..06c076d7 100644 --- a/src/public/py_array.c +++ b/src/public/py_array.c @@ -64,8 +64,7 @@ static bool _py_array_iterator__next__(int argc, py_Ref argv) { } py_Type pk_array_iterator__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "array_iterator", tp_object, NULL, false); + py_Type type = pk_newtype("array_iterator", tp_object, NULL, NULL, false, true); py_bindmagic(type, __new__, _py_array_iterator__new__); py_bindmagic(type, __iter__, _py_array_iterator__iter__); diff --git a/src/public/py_exception.c b/src/public/py_exception.c index 73872603..35ae75e3 100644 --- a/src/public/py_exception.c +++ b/src/public/py_exception.c @@ -17,6 +17,11 @@ typedef struct BaseException { c11_vector /*T=BaseExceptionFrame*/ stacktrace; } BaseException; +static void BaseException__dtor(void* ud) { + BaseException* self = (BaseException*)ud; + c11_vector__dtor(&self->stacktrace); +} + static bool _py_BaseException__new__(int argc, py_Ref argv) { py_Type cls = py_totype(argv); BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException)); @@ -65,8 +70,8 @@ static bool _py_BaseException__str__(int argc, py_Ref argv) { } py_Type pk_BaseException__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "BaseException", tp_object, NULL, true); + py_Type type = pk_newtype("BaseException", tp_object, NULL, BaseException__dtor, false, false); + py_bindmagic(type, __new__, _py_BaseException__new__); py_bindmagic(type, __init__, _py_BaseException__init__); py_bindmagic(type, __repr__, _py_BaseException__repr__); @@ -75,7 +80,6 @@ py_Type pk_BaseException__register() { } py_Type pk_Exception__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "Exception", tp_BaseException, NULL, true); + py_Type type = pk_newtype("Exception", tp_BaseException, NULL, NULL, false, true); return type; } \ No newline at end of file diff --git a/src/public/py_list.c b/src/public/py_list.c index 8febf5c2..be12da42 100644 --- a/src/public/py_list.c +++ b/src/public/py_list.c @@ -64,7 +64,7 @@ void py_list__insert(py_Ref self, int i, const py_Ref val) { c11_vector__insert(py_TValue, userdata, i, *val); } -void py_list__reverse(py_Ref self){ +void py_list__reverse(py_Ref self) { List* userdata = py_touserdata(self); c11__reverse(py_TValue, userdata); } @@ -405,10 +405,8 @@ static bool _py_list__iter__(int argc, py_Ref argv) { } py_Type pk_list__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false); - pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type); - ti->dtor = (void (*)(void*))c11_vector__dtor; + py_Type type = + pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true); py_bindmagic(type, __len__, _py_list__len__); py_bindmagic(type, __eq__, _py_list__eq__); diff --git a/src/public/py_object.c b/src/public/py_object.c index 726dc614..92ad38b6 100644 --- a/src/public/py_object.c +++ b/src/public/py_object.c @@ -3,8 +3,12 @@ #include "pocketpy/pocketpy.h" static bool _py_object__new__(int argc, py_Ref argv) { - assert(argc >= 1); + if(argc == 0) return TypeError("object.__new__(): not enough arguments"); py_Type cls = py_totype(py_arg(0)); + pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, cls); + if(!ti->is_python) { + return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls); + } py_newobject(py_retval(), cls, 0, 0); return true; } @@ -54,7 +58,9 @@ static bool _py_type__repr__(int argc, py_Ref argv) { } void pk_object__register() { + // use staticmethod py_bindmagic(tp_object, __new__, _py_object__new__); + py_bindmagic(tp_object, __hash__, _py_object__hash__); py_bindmagic(tp_object, __eq__, _py_object__eq__); py_bindmagic(tp_object, __ne__, _py_object__ne__); diff --git a/src/public/py_range.c b/src/public/py_range.c index 891b9e17..dd79d1d1 100644 --- a/src/public/py_range.c +++ b/src/public/py_range.c @@ -47,8 +47,7 @@ static bool _py_range__iter__(int argc, py_Ref argv) { } py_Type pk_range__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "range", tp_object, NULL, false); + py_Type type = pk_newtype("range", tp_object, NULL, NULL, false, true); py_bindmagic(type, __new__, _py_range__new__); py_bindmagic(type, __iter__, _py_range__iter__); @@ -89,8 +88,7 @@ static bool _py_range_iterator__next__(int argc, py_Ref argv) { } py_Type pk_range_iterator__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "range_iterator", tp_object, NULL, false); + py_Type type = pk_newtype("range_iterator", tp_object, NULL, NULL, false, true); py_bindmagic(type, __new__, _py_range_iterator__new__); py_bindmagic(type, __iter__, _py_range_iterator__iter__); diff --git a/src/public/py_slice.c b/src/public/py_slice.c index 32602ca3..6029ef70 100644 --- a/src/public/py_slice.c +++ b/src/public/py_slice.c @@ -5,8 +5,7 @@ #include "pocketpy/objects/object.h" #include "pocketpy/interpreter/vm.h" - -void py_newslice(py_Ref out){ +void py_newslice(py_Ref out) { pk_VM* vm = pk_current_vm; PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0); out->type = tp_slice; @@ -14,8 +13,8 @@ void py_newslice(py_Ref out){ out->_obj = obj; } -static bool _py_slice__new__(int argc, py_Ref argv){ - PY_CHECK_ARGC(1+3); +static bool _py_slice__new__(int argc, py_Ref argv) { + PY_CHECK_ARGC(1 + 3); py_Ref slice = py_retval(); py_newslice(slice); py_setslot(slice, 0, py_arg(1)); @@ -24,7 +23,7 @@ static bool _py_slice__new__(int argc, py_Ref argv){ return true; } -static bool _py_slice__repr__(int argc, py_Ref argv){ +static bool _py_slice__repr__(int argc, py_Ref argv) { c11_sbuf buf; c11_sbuf__ctor(&buf); c11_sbuf__write_cstr(&buf, "slice("); @@ -45,9 +44,8 @@ static bool _py_slice__repr__(int argc, py_Ref argv){ return true; } -py_Type pk_slice__register(){ - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "slice", tp_object, NULL, false); +py_Type pk_slice__register() { + py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true); py_bindmagic(type, __new__, _py_slice__new__); py_bindmagic(type, __repr__, _py_slice__repr__); diff --git a/src/public/py_str.c b/src/public/py_str.c index ccf8b504..342655ad 100644 --- a/src/public/py_str.c +++ b/src/public/py_str.c @@ -463,8 +463,7 @@ static bool _py_str__index(int argc, py_Ref argv) { } py_Type pk_str__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "str", tp_object, NULL, false); + py_Type type = pk_newtype("str", tp_object, NULL, NULL, false, true); // no need to dtor because the memory is controlled by the object py_bindmagic(tp_str, __new__, _py_str__new__); @@ -534,8 +533,8 @@ static bool _py_str_iterator__next__(int argc, py_Ref argv) { } py_Type pk_str_iterator__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "str_iterator", tp_object, NULL, false); + py_Type type = pk_newtype("str_iterator", tp_object, NULL, NULL, false, true); + py_bindmagic(type, __new__, _py_str_iterator__new__); py_bindmagic(type, __iter__, _py_str_iterator__iter__); py_bindmagic(type, __next__, _py_str_iterator__next__); @@ -543,8 +542,7 @@ py_Type pk_str_iterator__register() { } py_Type pk_bytes__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "bytes", tp_object, NULL, false); + py_Type type = pk_newtype("bytes", tp_object, NULL, NULL, false, true); // no need to dtor because the memory is controlled by the object return type; } diff --git a/src/public/py_tuple.c b/src/public/py_tuple.c index 822035c0..52e63d95 100644 --- a/src/public/py_tuple.c +++ b/src/public/py_tuple.c @@ -126,8 +126,7 @@ static bool _py_tuple__iter__(int argc, py_Ref argv) { } py_Type pk_tuple__register() { - pk_VM* vm = pk_current_vm; - py_Type type = pk_VM__new_type(vm, "tuple", tp_object, NULL, false); + py_Type type = pk_newtype("tuple", tp_object, NULL, NULL, false, true); py_bindmagic(type, __len__, _py_tuple__len__); py_bindmagic(type, __repr__, _py_tuple__repr__);