Jelajahi Sumber

fix #440 (#457)

* fix #440

* fix #440

* fix #440

* fix #440

* fix #440

* fix #440

* fix #440

* add test

* add test
killcerr 1 bulan lalu
induk
melakukan
82b4fff934
2 mengubah file dengan 52 tambahan dan 4 penghapusan
  1. 33 4
      src/interpreter/ceval.c
  2. 19 0
      tests/280_exception.py

+ 33 - 4
src/interpreter/ceval.c

@@ -1142,10 +1142,39 @@ __NEXT_STEP:
             DISPATCH();
         }
         case OP_EXCEPTION_MATCH: {
-            if(!py_checktype(TOP(), tp_type)) goto __ERROR;
-            bool ok = py_isinstance(&self->unhandled_exc, py_totype(TOP()));
-            py_newbool(TOP(), ok);
-            DISPATCH();
+            bool ok = false;
+            bool has_invalid = false;
+            if(TOP()->type == tp_type) {
+                ok = py_isinstance(&self->unhandled_exc, py_totype(TOP()));
+            } else if(TOP()->type == tp_tuple) {
+                int len = py_tuple_len(TOP());
+                py_ObjectRef data = py_tuple_data(TOP());
+                for(int i = 0; i < len; i++) {
+                    if((data + i)->type != tp_type) {
+                        has_invalid = true;
+                        break;
+                    }
+                }
+                if(!has_invalid) {
+                    for(int i = 0; i < len; i++) {
+                        if(py_isinstance(&self->unhandled_exc, py_totype(data + i))) {
+                            ok = true;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                has_invalid = true;
+            }
+            if(has_invalid) {
+                py_newnil(&self->unhandled_exc);
+                TypeError("catching classes that do not inherit from BaseException is not allowed");
+                c11_vector__pop(&frame->exc_stack);
+                goto __ERROR;
+            } else {
+                py_newbool(TOP(), ok);
+                DISPATCH();
+            }
         }
         case OP_HANDLE_EXCEPTION: {
             FrameExcInfo* info = Frame__top_exc_info(frame);

+ 19 - 0
tests/280_exception.py

@@ -201,6 +201,25 @@ for i in range(6):
             a.append(i)
 assert a == [0, 1, 3, 4, 5]
 
+try:
+    result = 10 / 0
+    exit(1)
+except (ZeroDivisionError, TypeError) as e:
+    if type(e) != ZeroDivisionError:
+        exit(1)
+
+try:
+    try:
+        result = 10 / 0
+        exit(1)
+    except (ZeroDivisionError, 1) as e:
+        exit(1)
+    except (TypeError) as e:
+        exit(1)
+except Exception as e:
+    if type(e) != TypeError:
+        exit(1)
+
 """
 # finally, only
 def finally_only():