diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 4e965510..03a9aa64 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -329,8 +329,6 @@ bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE; /// The result will be set to `py_retval()`. /// The stack remains unchanged after the operation. bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) PY_RAISE; -/// Call a `py_CFunction` in a safe way. -bool py_callcfunc(py_StackRef p0, py_CFunction cfunc, int argc, py_Ref argv) PY_RAISE; bool py_str(py_Ref val) PY_RAISE; bool py_repr(py_Ref val) PY_RAISE; diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 33d6b8b3..72fa35ee 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -268,8 +268,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__); if(magic) { if(magic->type == tp_nativefunc) { - py_TValue* p0 = TOP(); - if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR; + if(!magic->_cfunc(2, SECOND())) goto __ERROR; + POP(); *TOP() = self->last_retval; } else { INSERT_THIRD(); // [?, a, b] @@ -321,8 +321,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { if(magic) { PUSH(THIRD()); // [val, a, b, val] if(magic->type == tp_nativefunc) { - py_TValue* p0 = FOURTH(); - if(!py_callcfunc(p0, magic->_cfunc, 3, THIRD())) goto __ERROR; + if(!magic->_cfunc(3, THIRD())) goto __ERROR; + STACK_SHRINK(4); } else { *FOURTH() = *magic; // [__selitem__, a, b, val] if(!py_vectorcall(2, 0)) goto __ERROR; @@ -388,8 +388,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__); if(magic) { if(magic->type == tp_nativefunc) { - py_TValue* p0 = SECOND(); - if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR; + if(!magic->_cfunc(2, SECOND())) goto __ERROR; + STACK_SHRINK(2); } else { INSERT_THIRD(); // [?, a, b] *THIRD() = *magic; // [__delitem__, a, b] @@ -528,8 +528,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__); if(magic) { if(magic->type == tp_nativefunc) { - py_TValue* p0 = TOP(); - if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR; + if(!magic->_cfunc(2, SECOND())) goto __ERROR; + POP(); *TOP() = self->last_retval; } else { INSERT_THIRD(); // [?, b, a] diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 326baee7..a1aff509 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -347,8 +347,8 @@ static bool c11_sv key_sv = py_name2sv(key); py_newstrn(tmp, key_sv.data, key_sv.size); py_dict__setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]); - if(py_checkexc()) return false; py_pop(); + if(py_checkexc()) return false; } } } @@ -401,7 +401,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo pk_VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co)); return opcall ? RES_CALL : pk_VM__run_top_frame(self); } else { - bool ok = py_callcfunc(p0, fn->cfunc, co->nlocals, argv); + bool ok = fn->cfunc(co->nlocals, argv); + self->stack.sp = p0; return ok ? RES_RETURN : RES_ERROR; } } @@ -440,8 +441,9 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo } if(p0->type == tp_nativefunc) { - if(!py_callcfunc(p0, p0->_cfunc, p1 - argv, argv)) return RES_ERROR; - return RES_RETURN; + bool ok = p0->_cfunc(p1 - argv, argv); + self->stack.sp = p0; + return ok ? RES_RETURN : RES_ERROR; } if(p0->type == tp_type) { diff --git a/src/public/internal.c b/src/public/internal.c index f855f0b8..c16ed9bc 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -203,8 +203,7 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, bool py_call(py_Ref f, int argc, py_Ref argv) { if(f->type == tp_nativefunc) { - py_TValue* p0 = pk_current_vm->stack.sp; - return py_callcfunc(p0, f->_cfunc, argc, argv); + return f->_cfunc(argc, argv); } else { py_push(f); py_pushnil(); @@ -316,12 +315,6 @@ bool pk_callmagic(py_Name name, int argc, py_Ref argv) { return py_call(tmp, argc, argv); } -bool py_callcfunc(py_StackRef p0, py_CFunction cfunc, int argc, py_Ref argv) { - bool ok = cfunc(argc, argv); - pk_current_vm->stack.sp = p0; - return ok; -} - bool StopIteration() { pk_VM* vm = pk_current_vm; assert(!vm->is_stopiteration); // flag is already set diff --git a/src/public/modules.c b/src/public/modules.c index 762d29ae..bbdc6ae4 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -133,13 +133,13 @@ static bool _py_builtins__sorted(int argc, py_Ref argv) { PY_CHECK_ARGC(3); // convert _0 to list object if(!py_tpcall(tp_list, 1, py_arg(0))) return false; - py_push(py_retval()); // duptop - py_push(py_retval()); // [| ] - bool ok = py_pushmethod(py_name("sort")); // [| list.sort, ] + py_push(py_retval()); // duptop + py_push(py_retval()); // [| ] + bool ok = py_pushmethod(py_name("sort")); // [| list.sort, ] if(!ok) return false; - py_push(py_arg(1)); // [| list.sort, , key] - py_push(py_arg(2)); // [| list.sort, , key, reverse] - ok = py_vectorcall(2, 0); // [| ] + py_push(py_arg(1)); // [| list.sort, , key] + py_push(py_arg(2)); // [| list.sort, , key, reverse] + ok = py_vectorcall(2, 0); // [| ] if(!ok) return false; py_assign(py_retval(), py_peek(-1)); py_pop(); @@ -165,14 +165,25 @@ static bool _py_builtins__sum(int argc, py_Ref argv) { py_TValue* p = pk_arrayview(argv, &length); if(!p) return TypeError("sum() expects a list or tuple"); - py_Ref tmp = py_pushtmp(); - py_newint(tmp, 0); + py_i64 total_i64 = 0; + py_f64 total_f64 = 0.0; + bool is_float = false; for(int i = 0; i < length; i++) { - if(!py_binaryadd(tmp, &p[i])) return false; - *tmp = *py_retval(); + switch(p[i].type) { + case tp_int: total_i64 += p[i]._i64; break; + case tp_float: + is_float = true; + total_f64 += p[i]._f64; + break; + default: return TypeError("sum() expects a list of numbers"); + } } - *py_retval() = *tmp; + if(is_float) { + py_newfloat(py_retval(), total_f64 + total_i64); + } else { + py_newint(py_retval(), total_i64); + } return true; } diff --git a/src/public/py_list.c b/src/public/py_list.c index 250f10ef..6af84251 100644 --- a/src/public/py_list.c +++ b/src/public/py_list.c @@ -120,14 +120,15 @@ static bool _py_list__new__(int argc, py_Ref argv) { py_newlist(list); while(true) { int res = py_next(iter); - if(res == -1) return false; - if(res) { - py_list__append(list, py_retval()); - } else { - break; + if(res == -1){ + py_shrink(2); + return false; } + if(!res) break; + py_list__append(list, py_retval()); } *py_retval() = *list; + py_shrink(2); return true; } return TypeError("list() takes at most 1 argument"); diff --git a/src/public/py_tuple.c b/src/public/py_tuple.c index cd264905..6cec6d8c 100644 --- a/src/public/py_tuple.c +++ b/src/public/py_tuple.c @@ -65,6 +65,7 @@ static bool _py_tuple__new__(int argc, py_Ref argv) { for(int i = 0; i < py_tuple__len(py_retval()); i++) { py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i)); } + py_pop(); return true; } return TypeError("tuple() takes at most 1 argument"); @@ -91,6 +92,7 @@ static bool _py_tuple__getitem__(int argc, py_Ref argv) { for(int i = 0; i < py_tuple__len(py_retval()); i++) { py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i)); } + py_pop(); return true; } else { return TypeError("tuple indices must be integers");