blueloveTH 1 год назад
Родитель
Сommit
f9de245bc6

+ 15 - 1
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 {

+ 16 - 10
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);

+ 7 - 28
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;
         }

+ 1 - 1
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++) {

+ 79 - 4
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", "<bind>", 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);

+ 17 - 28
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, "<bind>", 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, "<bind>", 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);