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__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name);
|
||||||
void CodeObject__dtor(CodeObject* self);
|
void CodeObject__dtor(CodeObject* self);
|
||||||
|
int CodeObject__add_varname(CodeObject* self, py_Name name);
|
||||||
void CodeObject__gc_mark(const CodeObject* self);
|
void CodeObject__gc_mark(const CodeObject* self);
|
||||||
|
|
||||||
typedef struct FuncDeclKwArg {
|
typedef struct FuncDeclKwArg {
|
||||||
@ -118,7 +119,20 @@ typedef struct FuncDecl {
|
|||||||
typedef FuncDecl* FuncDecl_;
|
typedef FuncDecl* FuncDecl_;
|
||||||
|
|
||||||
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name);
|
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
|
// runtime function
|
||||||
typedef struct Function {
|
typedef struct Function {
|
||||||
|
@ -81,15 +81,6 @@ bool py_ismagicname(py_Name);
|
|||||||
void py_newdict(py_Ref);
|
void py_newdict(py_Ref);
|
||||||
void py_newset(py_Ref);
|
void py_newset(py_Ref);
|
||||||
void py_newslice(py_Ref, const py_Ref start, const py_Ref stop, const py_Ref step);
|
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
|
// old style argc-based function
|
||||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
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
|
// new style decl-based bindings
|
||||||
void py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
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,
|
const char* sig,
|
||||||
py_CFunction f,
|
py_CFunction f,
|
||||||
enum BindType bt,
|
enum BindType bt,
|
||||||
const char* docstring,
|
const char* docstring,
|
||||||
int slots);
|
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
|
// old style argc-based bindings
|
||||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
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);
|
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) {
|
static int Ctx__add_varname(Ctx* self, py_Name name) {
|
||||||
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
|
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
|
||||||
int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1);
|
return CodeObject__add_varname(self->co, name);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Ctx__add_const_string(Ctx* self, c11_sv key) {
|
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()));
|
py_Name name = py_name2(Token__sv(prev()));
|
||||||
|
|
||||||
// check duplicate argument name
|
// check duplicate argument name
|
||||||
py_Name tmp_name;
|
if(FuncDecl__is_duplicated_arg(decl, name)) {
|
||||||
c11__foreach(int, &decl->args, j) {
|
return SyntaxError("duplicate argument name");
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eat type hints
|
// eat type hints
|
||||||
if(enable_type_hints && match(TK_COLON)) check(consume_type_hints(self));
|
if(enable_type_hints && match(TK_COLON)) check(consume_type_hints(self));
|
||||||
if(state == 0 && curr()->type == TK_ASSIGN) state = 2;
|
if(state == 0 && curr()->type == TK_ASSIGN) state = 2;
|
||||||
int index = Ctx__add_varname(ctx(), name);
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case 0: c11_vector__push(int, &decl->args, index); break;
|
case 0: FuncDecl__add_arg(decl, name); break;
|
||||||
case 1:
|
case 1:
|
||||||
decl->starred_arg = index;
|
FuncDecl__add_starred_arg(decl, name);
|
||||||
state += 1;
|
state += 1;
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2: {
|
||||||
@ -2277,10 +2256,10 @@ static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool enable_type_h
|
|||||||
py_TValue value;
|
py_TValue value;
|
||||||
check(read_literal(self, &value));
|
check(read_literal(self, &value));
|
||||||
if(py_isnil(&value)) return SyntaxError("default argument must be a literal");
|
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;
|
} break;
|
||||||
case 3:
|
case 3:
|
||||||
decl->starred_kwarg = index;
|
FuncDecl__add_starred_kwarg(decl, name);
|
||||||
state += 1;
|
state += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
__NEXT_STEP:
|
__NEXT_STEP:
|
||||||
byte = *frame->ip;
|
byte = *frame->ip;
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
c11_sbuf buf;
|
c11_sbuf buf;
|
||||||
c11_sbuf__ctor(&buf);
|
c11_sbuf__ctor(&buf);
|
||||||
for(py_Ref p = self->stack.begin; p != SP(); p++) {
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const py_TValue* value) {
|
bool FuncDecl__is_duplicated_arg(const FuncDecl* decl, py_Name name) {
|
||||||
c11_smallmap_n2i__set(&self->kw_to_index, key, index);
|
py_Name tmp_name;
|
||||||
FuncDeclKwArg item = {index, key, *value};
|
c11__foreach(int, &decl->args, j) {
|
||||||
c11_vector__push(FuncDeclKwArg, &self->kwargs, item);
|
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) {
|
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;
|
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) {
|
void Function__dtor(Function* self) {
|
||||||
PK_DECREF(self->decl);
|
PK_DECREF(self->decl);
|
||||||
if(self->closure) pk_NameDict__delete(self->closure);
|
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_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) {
|
void py_newnativefunc(py_Ref out, py_CFunction f) {
|
||||||
out->type = tp_nativefunc;
|
out->type = tp_nativefunc;
|
||||||
out->is_ptr = false;
|
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) {
|
void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
|
||||||
py_TValue tmp;
|
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);
|
Function* ud = py_touserdata(&tmp);
|
||||||
py_Name name = py_name(ud->decl->code.name->data);
|
py_Name name = py_name(ud->decl->code.name->data);
|
||||||
py_setdict(obj, name, &tmp);
|
py_setdict(obj, name, &tmp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user