mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
6bc625dd0c
commit
f9de245bc6
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user