blueloveTH 2 years ago
parent
commit
8c85881d14
4 changed files with 26 additions and 13 deletions
  1. 2 1
      docs/features/ub.md
  2. 24 6
      src/ceval.h
  3. 0 5
      src/pocketpy.h
  4. 0 1
      src/vm.h

+ 2 - 1
docs/features/ub.md

@@ -10,4 +10,5 @@ These are the undefined behaviours of pkpy. The behaviour of pkpy is undefined i
 3. Use goto statement to jump out of a context block.
 4. Type `T`'s `__new__` returns an object that is not an instance of `T`.
 5. Call `__new__` with a type that is not a subclass of `type`.
-6. `__eq__`, `__ne__` or `__contains__`, etc.. returns a value that is not a boolean.
+6. `__eq__`, `__ne__` or `__contains__`, etc.. returns a value that is not a boolean.
+7. Division by zero.

+ 24 - 6
src/ceval.h

@@ -271,6 +271,14 @@ __NEXT_STEP:;
         PUSH(VAR(ss.str()));
     } DISPATCH();
     /*****************************************/
+#define PREDICT_INT_OP(op)                              \
+    if(is_both_int(TOP(), SECOND())){                   \
+        _1 = POPX();                                    \
+        _0 = TOP();                                     \
+        TOP() = VAR(_CAST(i64, _0) op _CAST(i64, _1));  \
+        DISPATCH();                                     \
+    }
+
 #define BINARY_OP_SPECIAL(func)                         \
         _1 = POPX();                                    \
         _0 = TOP();                                     \
@@ -282,30 +290,35 @@ __NEXT_STEP:;
         }
 
     TARGET(BINARY_TRUEDIV)
+        if(is_tagged(SECOND())){
+            f64 lhs = num_to_float(SECOND());
+            f64 rhs = num_to_float(TOP());
+            POP();
+            TOP() = VAR(lhs / rhs);
+            DISPATCH();
+        }
         BINARY_OP_SPECIAL(__truediv__);
         DISPATCH();
     TARGET(BINARY_POW)
         BINARY_OP_SPECIAL(__pow__);
         DISPATCH();
     TARGET(BINARY_ADD)
-        if(is_both_int(TOP(), SECOND())){
-            _1 = POPX();
-            _0 = TOP();
-            TOP() = VAR(_CAST(i64, _0) + _CAST(i64, _1));
-            DISPATCH();
-        }
+        PREDICT_INT_OP(+);
         BINARY_OP_SPECIAL(__add__);
         DISPATCH()
     TARGET(BINARY_SUB)
+        PREDICT_INT_OP(-);
         BINARY_OP_SPECIAL(__sub__);
         DISPATCH()
     TARGET(BINARY_MUL)
         BINARY_OP_SPECIAL(__mul__);
         DISPATCH()
     TARGET(BINARY_FLOORDIV)
+        PREDICT_INT_OP(/);
         BINARY_OP_SPECIAL(__floordiv__);
         DISPATCH()
     TARGET(BINARY_MOD)
+        PREDICT_INT_OP(%);
         BINARY_OP_SPECIAL(__mod__);
         DISPATCH()
     TARGET(COMPARE_LT)
@@ -331,18 +344,23 @@ __NEXT_STEP:;
         BINARY_OP_SPECIAL(__ge__);
         DISPATCH()
     TARGET(BITWISE_LSHIFT)
+        PREDICT_INT_OP(<<);
         BINARY_OP_SPECIAL(__lshift__);
         DISPATCH()
     TARGET(BITWISE_RSHIFT)
+        PREDICT_INT_OP(>>);
         BINARY_OP_SPECIAL(__rshift__);
         DISPATCH()
     TARGET(BITWISE_AND)
+        PREDICT_INT_OP(&);
         BINARY_OP_SPECIAL(__and__);
         DISPATCH()
     TARGET(BITWISE_OR)
+        PREDICT_INT_OP(|);
         BINARY_OP_SPECIAL(__or__);
         DISPATCH()
     TARGET(BITWISE_XOR)
+        PREDICT_INT_OP(^);
         BINARY_OP_SPECIAL(__xor__);
         DISPATCH()
     TARGET(BINARY_MATMUL)

+ 0 - 5
src/pocketpy.h

@@ -107,7 +107,6 @@ inline void init_builtins(VM* _vm) {
     _vm->bind_builtin_func<2>("divmod", [](VM* vm, ArgsView args) {
         i64 lhs = CAST(i64, args[0]);
         i64 rhs = CAST(i64, args[1]);
-        if(rhs == 0) vm->ZeroDivisionError();
         return VAR(Tuple({VAR(lhs/rhs), VAR(lhs%rhs)}));
     });
 
@@ -233,13 +232,11 @@ inline void init_builtins(VM* _vm) {
 
     _vm->bind__truediv__(_vm->tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) {
         f64 value = VAR_F(rhs);
-        if (value == 0) vm->ZeroDivisionError();
         return VAR(_CAST(f64, lhs) / value);
     });
 
     _vm->bind__truediv__(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) {
         f64 value = VAR_F(rhs);
-        if (value == 0) vm->ZeroDivisionError();
         return VAR(_CAST(i64, lhs) / value);
     });
 
@@ -287,13 +284,11 @@ inline void init_builtins(VM* _vm) {
 
     _vm->bind__floordiv__(_vm->tp_int, [](VM* vm, PyObject* lhs_, PyObject* rhs_) {
         i64 rhs = CAST(i64, rhs_);
-        if(rhs == 0) vm->ZeroDivisionError();
         return VAR(_CAST(i64, lhs_) / rhs);
     });
 
     _vm->bind__mod__(_vm->tp_int, [](VM* vm, PyObject* lhs_, PyObject* rhs_) {
         i64 rhs = CAST(i64, rhs_);
-        if(rhs == 0) vm->ZeroDivisionError();
         return VAR(_CAST(i64, lhs_) % rhs);
     });
 

+ 0 - 1
src/vm.h

@@ -518,7 +518,6 @@ public:
     void IOError(const Str& msg) { _error("IOError", msg); }
     void NotImplementedError(){ _error("NotImplementedError", ""); }
     void TypeError(const Str& msg){ _error("TypeError", msg); }
-    void ZeroDivisionError(){ _error("ZeroDivisionError", "division by zero"); }
     void IndexError(const Str& msg){ _error("IndexError", msg); }
     void ValueError(const Str& msg){ _error("ValueError", msg); }
     void NameError(StrName name){ _error("NameError", fmt("name ", name.escape() + " is not defined")); }