blueloveTH il y a 1 an
Parent
commit
b1a8c6db8e

+ 4 - 2
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__)

+ 1 - 0
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

+ 1 - 0
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;

+ 1 - 0
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)) {

+ 1 - 1
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();
             }
             //////////////////

+ 17 - 8
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;
 }
 

+ 9 - 0
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;

+ 7 - 2
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());
 }

+ 1 - 1
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;
 }
 

+ 1 - 1
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