This commit is contained in:
blueloveTH 2024-07-08 13:16:27 +08:00 committed by blueloveTH
parent 6bc625dd0c
commit f9de245bc6
6 changed files with 135 additions and 72 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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;
}

View File

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

View File

@ -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);

View File

@ -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);