diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 602a0397..197246e8 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -271,12 +271,14 @@ bool py_import(const char* path) PY_RAISE; bool py_exception(const char* name, const char* fmt, ...) PY_RAISE; /// Raise an expection object. Always returns false. bool py_raise(py_Ref) PY_RAISE; -/// Print the last error to the console. +/// Print the current exception. void py_printexc(); -/// Format the last error to a string. +/// Format the current exception. char* py_formatexc(); /// Check if an exception is raised. bool py_checkexc(); +/// Clear the current exception. +void py_clearexc(py_StackRef p0); #define NameError(n) py_exception("NameError", "name '%n' is not defined", (n)) #define TypeError(...) py_exception("TypeError", __VA_ARGS__) diff --git a/prebuild.py b/prebuild.py index 17901b30..f9257996 100644 --- a/prebuild.py +++ b/prebuild.py @@ -56,6 +56,7 @@ with open("src/common/_generated.c", "wt", encoding='utf-8', newline='\n') as f: f.write("\n") f.write("const char* load_kPythonLib(const char* name) {\n") + f.write(" if (strchr(name, '.') != NULL) return NULL;\n") for key in sorted(sources.keys()): if key.startswith('_'): continue diff --git a/src/common/_generated.c b/src/common/_generated.c index c471cdd6..9f3fbf64 100644 --- a/src/common/_generated.c +++ b/src/common/_generated.c @@ -19,6 +19,7 @@ const char kPythonLibs_this[] = "print(\"\"\"The Zen of Python, by Tim Peters\n\ const char kPythonLibs_typing[] = "class _Placeholder:\n def __init__(self, *args, **kwargs):\n pass\n def __getitem__(self, *args):\n return self\n def __call__(self, *args, **kwargs):\n return self\n def __and__(self, other):\n return self\n def __or__(self, other):\n return self\n def __xor__(self, other):\n return self\n\n\n_PLACEHOLDER = _Placeholder()\n\nList = _PLACEHOLDER\nDict = _PLACEHOLDER\nTuple = _PLACEHOLDER\nSet = _PLACEHOLDER\nAny = _PLACEHOLDER\nUnion = _PLACEHOLDER\nOptional = _PLACEHOLDER\nCallable = _PLACEHOLDER\nType = _PLACEHOLDER\nProtocol = _PLACEHOLDER\n\nLiteral = _PLACEHOLDER\nLiteralString = _PLACEHOLDER\n\nIterable = _PLACEHOLDER\nGenerator = _PLACEHOLDER\n\nHashable = _PLACEHOLDER\n\nTypeVar = _PLACEHOLDER\nSelf = _PLACEHOLDER\n\nclass Generic:\n pass\n\nTYPE_CHECKING = False\n\n# decorators\noverload = lambda x: x\nfinal = lambda x: x\n"; const char* load_kPythonLib(const char* name) { + if (strchr(name, '.') != NULL) return NULL; if (strcmp(name, "bisect") == 0) return kPythonLibs_bisect; if (strcmp(name, "builtins") == 0) return kPythonLibs_builtins; if (strcmp(name, "cmath") == 0) return kPythonLibs_cmath; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 924d1d6c..434d32d5 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -2477,6 +2477,7 @@ __EAT_DOTS_END: OP_IMPORT_PATH, Ctx__add_const_string(ctx(), c11_string__sv(path)), prev()->line); + c11_string__delete(path); consume(TK_IMPORT); if(match(TK_MUL)) { diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 3ca3ddd6..8dfcf398 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -920,7 +920,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { } case OP_POP_EXCEPTION: { assert(self->curr_exception.type); - self->curr_exception = *py_NIL; + py_clearexc(NULL); DISPATCH(); } ////////////////// diff --git a/src/public/modules.c b/src/public/modules.c index 415e3575..fb6ca331 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -232,21 +232,29 @@ static bool _py_builtins__abs(int argc, py_Ref argv) { static bool _py_builtins__sum(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int length; - py_TValue* p = pk_arrayview(argv, &length); - if(!p) return TypeError("sum() expects a list or tuple"); + + if(!py_iter(py_arg(0))) return false; + py_push(py_retval()); // iter py_i64 total_i64 = 0; py_f64 total_f64 = 0.0; bool is_float = false; - for(int i = 0; i < length; i++) { - switch(p[i].type) { - case tp_int: total_i64 += p[i]._i64; break; + while(true) { + int res = py_next(py_peek(-1)); + if(res == -1) { + py_pop(); + return false; + } + if(res == 0) break; + + py_Ref item = py_retval(); + switch(item->type) { + case tp_int: total_i64 += item->_i64; break; case tp_float: is_float = true; - total_f64 += p[i]._f64; + total_f64 += item->_f64; break; - default: return TypeError("sum() expects a list of numbers"); + default: return TypeError("sum() expects an iterable of numbers"); } } @@ -255,6 +263,7 @@ static bool _py_builtins__sum(int argc, py_Ref argv) { } else { py_newint(py_retval(), total_i64); } + py_pop(); return true; } diff --git a/src/public/py_exception.c b/src/public/py_exception.c index d8169926..f92f5a23 100644 --- a/src/public/py_exception.c +++ b/src/public/py_exception.c @@ -115,6 +115,15 @@ bool py_checkexc() { return !py_isnil(&vm->curr_exception); } +void py_clearexc(py_StackRef p0) { + pk_VM* vm = pk_current_vm; + vm->last_retval = *py_NIL; + vm->curr_exception = *py_NIL; + vm->is_stopiteration = false; + vm->__curr_class = NULL; + if(p0) vm->stack.sp = p0; +} + void py_printexc() { char* msg = py_formatexc(); if(!msg) return; diff --git a/src/public/py_ops.c b/src/public/py_ops.c index 8d26d398..ca6e38af 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -72,7 +72,12 @@ int py_next(py_Ref val) { vm->is_stopiteration = false; py_Ref tmp = py_tpfindmagic(val->type, __next__); if(!tmp) return TypeError("'%t' object is not an iterator", val->type); + py_StackRef p0 = py_peek(0); if(py_call(tmp, 1, val)) return true; + if(vm->curr_exception.type == tp_StopIteration) { + py_clearexc(p0); + vm->is_stopiteration = true; + } return vm->is_stopiteration ? 0 : -1; } @@ -200,12 +205,12 @@ bool py_delitem(py_Ref self, py_Ref key) { return ok; } -int py_equal(py_Ref lhs, py_Ref rhs){ +int py_equal(py_Ref lhs, py_Ref rhs) { if(!py_eq(lhs, rhs)) return -1; return py_bool(py_retval()); } -int py_less(py_Ref lhs, py_Ref rhs){ +int py_less(py_Ref lhs, py_Ref rhs) { if(!py_lt(lhs, rhs)) return -1; return py_bool(py_retval()); } \ No newline at end of file diff --git a/src/public/stack_ops.c b/src/public/stack_ops.c index b16d7bc0..4178b10d 100644 --- a/src/public/stack_ops.c +++ b/src/public/stack_ops.c @@ -57,7 +57,7 @@ void py_assign(py_Ref dst, py_Ref src) { *dst = *src; } /* Stack References */ py_Ref py_peek(int i) { - assert(i < 0); + assert(i <= 0); return pk_current_vm->stack.sp + i; } diff --git a/tests/29_iter.py b/tests/29_iter.py index 501900ea..b9557df5 100644 --- a/tests/29_iter.py +++ b/tests/29_iter.py @@ -23,7 +23,7 @@ class Task: def __next__(self): if self.i == self.n: - return StopIteration + raise StopIteration self.i += 1 return self.i