This commit is contained in:
blueloveTH 2024-07-07 16:28:59 +08:00
parent 5f98f916a9
commit ed02a2b172

View File

@ -246,11 +246,9 @@ bool pk__parse_int_slice(const py_Ref slice, int length, int* start, int* stop,
return true;
}
bool pk__normalize_index(int *index, int length){
bool pk__normalize_index(int* index, int length) {
if(*index < 0) *index += length;
if(*index < 0 || *index >= length){
return IndexError("index out of range");
}
if(*index < 0 || *index >= length) { return IndexError("index out of range"); }
return true;
}
@ -265,6 +263,73 @@ py_Type pk_VM__new_type(pk_VM* self,
return index;
}
bool __prepare_py_call(py_TValue* buffer,
py_Ref argv,
py_Ref p1,
int kwargc,
const FuncDecl* decl) {
const CodeObject* co = &decl->code;
int decl_argc = decl->args.count;
if(p1 - argv < decl_argc) {
return TypeError("%s() takes %d positional arguments but %d were given",
co->name->data,
decl_argc,
p1 - argv);
}
py_TValue* t = argv;
// prepare args
memset(buffer, 0, co->nlocals * sizeof(py_TValue));
c11__foreach(int, &decl->args, index) buffer[*index] = *t++;
// prepare kwdefaults
c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) buffer[kv->index] = kv->value;
// handle *args
if(decl->starred_arg != -1) {
int exceed_argc = p1 - t;
py_Ref vargs = &buffer[decl->starred_arg];
py_newtuple(vargs, exceed_argc);
for(int j = 0; j < exceed_argc; j++) {
py_tuple__setitem(vargs, j, t++);
}
} else {
// kwdefaults override
// def f(a, b, c=None)
// f(1, 2, 3) -> c=3
c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
if(t >= p1) break;
buffer[kv->index] = *t++;
}
// not able to consume all args
if(t < p1) return TypeError("too many arguments (%s)", co->name->data);
}
if(decl->starred_kwarg != -1) py_newdict(&buffer[decl->starred_kwarg]);
for(int j = 0; j < kwargc; j += 2) {
py_Name key = py_toint(&p1[j]);
int index = c11_smallmap_n2i__get(&decl->kw_to_index, key, -1);
// if key is an explicit key, set as local variable
if(index >= 0) {
buffer[index] = p1[j + 1];
} else {
// otherwise, set as **kwargs if possible
if(decl->starred_kwarg == -1) {
return TypeError("'%n' is an invalid keyword argument for %s()",
key,
co->name->data);
} else {
// add to **kwargs
// Dict& dict = _CAST(Dict&, vkwargs);
// dict.set(this, VAR(key.sv()), kwargs[j + 1]);
assert(false);
}
}
}
return true;
}
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
py_Ref p1 = self->stack.sp - kwargc * 2;
py_Ref p0 = p1 - argc - 2;
@ -298,14 +363,15 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
const CodeObject* co = &fn->decl->code;
switch(fn->decl->type) {
case FuncType_NORMAL:
assert(false);
// __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
// // copy buffer back to stack
// self->stack.sp = argv + co->nlocals;
// for(int j = 0; j < co->nlocals; j++)
// argv[j] = self->__vectorcall_buffer[j];
case FuncType_NORMAL: {
bool ok = __prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR;
// copy buffer back to stack
self->stack.sp = argv + co->nlocals;
for(int j = 0; j < co->nlocals; j++)
argv[j] = self->__vectorcall_buffer[j];
break;
}
case FuncType_SIMPLE:
if(argc2 != fn->decl->args.count) {
const char* fmt = "%s() takes %d positional arguments but %d were given";