From f9de245bc61eb240830e9f8dc0df0692e314f724 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 8 Jul 2024 13:16:27 +0800 Subject: [PATCH] ... --- include/pocketpy/objects/codeobject.h | 16 +++++- include/pocketpy/pocketpy.h | 26 +++++---- src/compiler/compiler.c | 35 +++-------- src/interpreter/ceval.c | 2 +- src/objects/codeobject.c | 83 +++++++++++++++++++++++++-- src/public/values.c | 45 ++++++--------- 6 files changed, 135 insertions(+), 72 deletions(-) diff --git a/include/pocketpy/objects/codeobject.h b/include/pocketpy/objects/codeobject.h index 4f3c19e9..e2c3ee2d 100644 --- a/include/pocketpy/objects/codeobject.h +++ b/include/pocketpy/objects/codeobject.h @@ -90,6 +90,7 @@ typedef struct CodeObject { void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name); void CodeObject__dtor(CodeObject* self); +int CodeObject__add_varname(CodeObject* self, py_Name name); void CodeObject__gc_mark(const CodeObject* self); typedef struct FuncDeclKwArg { @@ -118,7 +119,20 @@ typedef struct FuncDecl { typedef FuncDecl* FuncDecl_; FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name); -void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const py_TValue* value); +bool FuncDecl__is_duplicated_arg(const FuncDecl* self, py_Name name); +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_starred_arg(FuncDecl* self, py_Name name); +void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name); +FuncDecl_ FuncDecl__build(const char* name, + const char** args, + int argc, + const char* starred_arg, + const char** kwargs, + int kwargc, + py_Ref kwdefaults, // a tuple contains default values + const char* starred_kwarg, + const char* docstring); // runtime function typedef struct Function { diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index a09490a2..25630017 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -81,15 +81,6 @@ bool py_ismagicname(py_Name); void py_newdict(py_Ref); void py_newset(py_Ref); void py_newslice(py_Ref, const py_Ref start, const py_Ref stop, const py_Ref step); - -// new style decl-based function -void py_newfunction(py_Ref out, py_CFunction, const char* sig); -void py_newfunction2(py_Ref out, - py_CFunction, - const char* sig, - enum BindType bt, - const char* docstring, - int slots); // old style argc-based function void py_newnativefunc(py_Ref out, py_CFunction); @@ -135,12 +126,27 @@ py_GlobalRef py_tpmagic(py_Type type, py_Name name); // new style decl-based bindings void py_bind(py_Ref obj, const char* sig, py_CFunction f); -void py_bind2(py_Ref obj, +py_ObjectRef py_bind2(py_Ref obj, const char* sig, py_CFunction f, enum BindType bt, const char* docstring, int slots); + +py_ObjectRef py_bind3(py_Ref obj, + py_CFunction f, + const char* name, + const char** args, + int argc, + const char* starred_arg, + const char** kwargs, + int kwargc, + py_Ref kwdefaults, // a tuple contains default values + const char* starred_kwarg, + enum BindType bt, + const char* docstring, + int slots); + // old style argc-based bindings void py_bindmethod(py_Type type, const char* name, py_CFunction f); void py_bindmethod2(py_Type type, const char* name, py_CFunction f, enum BindType bt); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index a165aef9..645b91e4 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1327,13 +1327,7 @@ static bool Ctx__add_label(Ctx* self, py_Name name) { static int Ctx__add_varname(Ctx* self, py_Name name) { // PK_MAX_CO_VARNAMES will be checked when pop_context(), not here - int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1); - if(index >= 0) return index; - c11_vector__push(uint16_t, &self->co->varnames, name); - self->co->nlocals++; - index = self->co->varnames.count - 1; - c11_smallmap_n2i__set(&self->co->varnames_inv, name, index); - return index; + return CodeObject__add_varname(self->co, name); } static int Ctx__add_const_string(Ctx* self, c11_sv key) { @@ -2244,32 +2238,17 @@ static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool enable_type_h py_Name name = py_name2(Token__sv(prev())); // check duplicate argument name - py_Name tmp_name; - c11__foreach(int, &decl->args, j) { - tmp_name = c11__getitem(py_Name, &decl->args, *j); - if(tmp_name == name) return SyntaxError("duplicate argument name"); - } - c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) { - tmp_name = c11__getitem(py_Name, &decl->code.varnames, kv->index); - if(tmp_name == name) return SyntaxError("duplicate argument name"); - } - if(decl->starred_arg != -1) { - tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_arg); - if(tmp_name == name) return SyntaxError("duplicate argument name"); - } - if(decl->starred_kwarg != -1) { - tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_kwarg); - if(tmp_name == name) return SyntaxError("duplicate argument name"); + if(FuncDecl__is_duplicated_arg(decl, name)) { + return SyntaxError("duplicate argument name"); } // eat type hints if(enable_type_hints && match(TK_COLON)) check(consume_type_hints(self)); if(state == 0 && curr()->type == TK_ASSIGN) state = 2; - int index = Ctx__add_varname(ctx(), name); switch(state) { - case 0: c11_vector__push(int, &decl->args, index); break; + case 0: FuncDecl__add_arg(decl, name); break; case 1: - decl->starred_arg = index; + FuncDecl__add_starred_arg(decl, name); state += 1; break; case 2: { @@ -2277,10 +2256,10 @@ static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool enable_type_h py_TValue value; check(read_literal(self, &value)); if(py_isnil(&value)) return SyntaxError("default argument must be a literal"); - FuncDecl__add_kwarg(decl, index, name, &value); + FuncDecl__add_kwarg(decl, name, &value); } break; case 3: - decl->starred_kwarg = index; + FuncDecl__add_starred_kwarg(decl, name); state += 1; break; } diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 7e10adad..1d7c389e 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -83,7 +83,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { __NEXT_STEP: byte = *frame->ip; -#if 1 +#if 0 c11_sbuf buf; c11_sbuf__ctor(&buf); for(py_Ref p = self->stack.begin; p != SP(); p++) { diff --git a/src/objects/codeobject.c b/src/objects/codeobject.c index 36109651..c0e2ac23 100644 --- a/src/objects/codeobject.c +++ b/src/objects/codeobject.c @@ -40,10 +40,75 @@ FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name) { return self; } -void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const py_TValue* value) { - c11_smallmap_n2i__set(&self->kw_to_index, key, index); - FuncDeclKwArg item = {index, key, *value}; - c11_vector__push(FuncDeclKwArg, &self->kwargs, item); +bool FuncDecl__is_duplicated_arg(const FuncDecl* decl, py_Name name) { + py_Name tmp_name; + c11__foreach(int, &decl->args, j) { + tmp_name = c11__getitem(py_Name, &decl->args, *j); + if(tmp_name == name) return true; + } + c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) { + tmp_name = c11__getitem(py_Name, &decl->code.varnames, kv->index); + if(tmp_name == name) return true; + } + if(decl->starred_arg != -1) { + tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_arg); + if(tmp_name == name) return true; + } + if(decl->starred_kwarg != -1) { + tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_kwarg); + if(tmp_name == name) return true; + } + return false; +} + +void FuncDecl__add_arg(FuncDecl* self, py_Name name) { + int index = CodeObject__add_varname(&self->code, name); + c11_vector__push(int, &self->args, index); +} + +void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value) { + int index = CodeObject__add_varname(&self->code, name); + c11_smallmap_n2i__set(&self->kw_to_index, name, index); + FuncDeclKwArg* item = c11_vector__emplace(&self->kwargs); + item->index = index; + item->key = name; + item->value = *value; +} + +void FuncDecl__add_starred_arg(FuncDecl* self, py_Name name) { + int index = CodeObject__add_varname(&self->code, name); + self->starred_arg = index; +} + +void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name) { + int index = CodeObject__add_varname(&self->code, name); + self->starred_kwarg = index; +} + +FuncDecl_ FuncDecl__build(const char* name, + const char** args, + int argc, + const char* starred_arg, + const char** kwargs, + int kwargc, + py_Ref kwdefaults, // a tuple contains default values + const char* starred_kwarg, + const char* docstring) { + pk_SourceData_ source = pk_SourceData__rcnew("pass", "", EXEC_MODE, false); + FuncDecl_ decl = FuncDecl__rcnew(source, (c11_sv){name, strlen(name)}); + for(int i = 0; i < argc; i++) { + FuncDecl__add_arg(decl, py_name(args[i])); + } + if(starred_arg) { FuncDecl__add_starred_arg(decl, py_name(starred_arg)); } + assert(py_istype(kwdefaults, tp_tuple)); + assert(py_tuple__len(kwdefaults) == kwargc); + for(int i = 0; i < kwargc; i++) { + FuncDecl__add_kwarg(decl, py_name(kwargs[i]), py_tuple__getitem(kwdefaults, i)); + } + if(starred_kwarg) FuncDecl__add_starred_kwarg(decl, py_name(starred_kwarg)); + decl->docstring = docstring; + PK_DECREF(source); + return decl; } void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name) { @@ -102,6 +167,16 @@ void Function__ctor(Function* self, FuncDecl_ decl, PyObject* module) { self->cfunc = NULL; } +int CodeObject__add_varname(CodeObject* self, py_Name name) { + int index = c11_smallmap_n2i__get(&self->varnames_inv, name, -1); + if(index >= 0) return index; + c11_vector__push(uint16_t, &self->varnames, name); + self->nlocals++; + index = self->varnames.count - 1; + c11_smallmap_n2i__set(&self->varnames_inv, name, index); + return index; +} + void Function__dtor(Function* self) { PK_DECREF(self->decl); if(self->closure) pk_NameDict__delete(self->closure); diff --git a/src/public/values.c b/src/public/values.c index d3578ad9..abbb0d3d 100644 --- a/src/public/values.c +++ b/src/public/values.c @@ -42,33 +42,6 @@ void py_newellipsis(py_Ref out) { void py_newnil(py_Ref out) { out->type = 0; } -void py_newfunction(py_Ref out, py_CFunction f, const char* sig) { - py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, 0); -} - -void py_newfunction2(py_Ref out, - py_CFunction f, - const char* sig, - enum BindType bt, - const char* docstring, - int slots) { - char buffer[256]; - snprintf(buffer, sizeof(buffer), "def %s: pass", sig); - // fn(a, b, *c, d=1) -> None - CodeObject code; - pk_SourceData_ source = pk_SourceData__rcnew(buffer, "", EXEC_MODE, false); - Error* err = pk_compile(source, &code); - if(err) abort(); - if(code.func_decls.count != 1) abort(); - FuncDecl_ decl = c11__getitem(FuncDecl_, &code.func_decls, 0); - // construct the function - Function* ud = py_newobject(out, tp_function, slots, sizeof(Function)); - Function__ctor(ud, decl, NULL); - ud->cfunc = f; - CodeObject__dtor(&code); - PK_DECREF(source); -} - void py_newnativefunc(py_Ref out, py_CFunction f) { out->type = tp_nativefunc; out->is_ptr = false; @@ -93,7 +66,23 @@ void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f) { void py_bind(py_Ref obj, const char* sig, py_CFunction f) { py_TValue tmp; - py_newfunction(&tmp, f, sig); + do{ + char buffer[256]; + snprintf(buffer, sizeof(buffer), "def %s: pass", sig); + // fn(a, b, *c, d=1) -> None + CodeObject code; + pk_SourceData_ source = pk_SourceData__rcnew(buffer, "", EXEC_MODE, false); + Error* err = pk_compile(source, &code); + if(err) abort(); + if(code.func_decls.count != 1) abort(); + FuncDecl_ decl = c11__getitem(FuncDecl_, &code.func_decls, 0); + // construct the function + Function* ud = py_newobject(&tmp, tp_function, 0, sizeof(Function)); + Function__ctor(ud, decl, NULL); + ud->cfunc = f; + CodeObject__dtor(&code); + PK_DECREF(source); + }while(0); Function* ud = py_touserdata(&tmp); py_Name name = py_name(ud->decl->code.name->data); py_setdict(obj, name, &tmp);