blueloveTH 1 year ago
parent
commit
5847586121
3 changed files with 121 additions and 5 deletions
  1. 23 0
      include/pocketpy/pocketpy.h
  2. 61 0
      src/interpreter/ceval.c
  3. 37 5
      src/public/py_ops.c

+ 23 - 0
include/pocketpy/pocketpy.h

@@ -149,6 +149,23 @@ bool py_getitem(const py_Ref self, const py_Ref key, py_Ref out);
 bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val);
 bool py_delitem(py_Ref self, const py_Ref key);
 
+bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop);
+
+#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
+#define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__)
+#define py_binarymul(lhs, rhs) py_binaryop(lhs, rhs, __mul__, __rmul__)
+#define py_binarytruediv(lhs, rhs) py_binaryop(lhs, rhs, __truediv__, __rtruediv__)
+#define py_binaryfloordiv(lhs, rhs) py_binaryop(lhs, rhs, __floordiv__, __rfloordiv__)
+#define py_binarymod(lhs, rhs) py_binaryop(lhs, rhs, __mod__, __rmod__)
+#define py_binarypow(lhs, rhs) py_binaryop(lhs, rhs, __pow__, __rpow__)
+
+#define py_binarylshift(lhs, rhs) py_binaryop(lhs, rhs, __lshift__, 0)
+#define py_binaryrshift(lhs, rhs) py_binaryop(lhs, rhs, __rshift__, 0)
+#define py_binaryand(lhs, rhs) py_binaryop(lhs, rhs, __and__, 0)
+#define py_binaryor(lhs, rhs) py_binaryop(lhs, rhs, __or__, 0)
+#define py_binaryxor(lhs, rhs) py_binaryop(lhs, rhs, __xor__, 0)
+#define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
+
 /// Equivalent to `*dst = *src`.
 void py_assign(py_Ref dst, const py_Ref src);
 
@@ -187,8 +204,14 @@ void py_Error__print(py_Error*);
 
 /************* Operators *************/
 bool py_bool(const py_Ref);
+
 int py_eq(const py_Ref, const py_Ref);
+int py_ne(const py_Ref, const py_Ref);
 int py_le(const py_Ref, const py_Ref);
+int py_lt(const py_Ref, const py_Ref);
+int py_ge(const py_Ref, const py_Ref);
+int py_gt(const py_Ref, const py_Ref);
+
 bool py_hash(const py_Ref, int64_t* out);
 
 /// Compare two objects without using magic methods.

+ 61 - 0
src/interpreter/ceval.c

@@ -666,3 +666,64 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
 
     return RES_RETURN;
 }
+
+bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
+    pk_VM* self = pk_current_vm;
+    PUSH(lhs);
+    PUSH(rhs);
+    // [a, b]
+    py_Ref _0 = py_tpfindmagic(SECOND()->type, op);
+    py_Ref _1;
+    if(_0) {
+        if(_0->type == tp_nativefunc) {
+            bool ok = _0->_cfunc(2, SECOND(), &self->last_retval);
+            if(!ok) return false;
+            if(self->last_retval.type != tp_not_implemented_type) {
+                STACK_SHRINK(2);
+                return true;
+            }
+        } else {
+            // standard call
+            bool ok = py_call(_0, 2, SECOND());
+            if(!ok) return false;
+            if(self->last_retval.type != tp_not_implemented_type) {
+                STACK_SHRINK(2);
+                return true;
+            }
+        }
+    }
+    // try reverse operation
+    if(rop) {
+        // [a, b] -> [b, a]
+        py_TValue tmp = *TOP();
+        *TOP() = *SECOND();
+        *SECOND() = tmp;
+        _1 = py_tpfindmagic(SECOND()->type, rop);
+        if(_1) {
+            if(_1->type == tp_nativefunc) {
+                bool ok = _1->_cfunc(2, SECOND(), &self->last_retval);
+                if(!ok) return false;
+                if(tmp.type != tp_not_implemented_type) {
+                    STACK_SHRINK(2);
+                    return true;
+                }
+            } else {
+                // standard call
+                bool ok = py_call(_1, 2, SECOND());
+                if(!ok) return false;
+                if(self->last_retval.type != tp_not_implemented_type) {
+                    STACK_SHRINK(2);
+                    return true;
+                }
+            }
+        }
+    }
+    // eq/ne op never fails
+    if(op == __eq__ || op == __ne__) {
+        STACK_SHRINK(2);
+        self->last_retval = (op == __eq__) ? self->False : self->True;
+        return true;
+    }
+    BinaryOptError(byte.arg);
+    return false;
+}

+ 37 - 5
src/public/py_ops.c

@@ -1,10 +1,6 @@
 #include "pocketpy/interpreter/vm.h"
 #include "pocketpy/pocketpy.h"
 
-int py_eq(const py_Ref lhs, const py_Ref rhs) { return 0; }
-
-int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
-
 bool py_isidentical(const py_Ref lhs, const py_Ref rhs){
     if(lhs->is_ptr && rhs->is_ptr){
         return lhs->_obj == rhs->_obj;
@@ -26,4 +22,40 @@ bool py_getitem(const py_Ref self, const py_Ref key, py_Ref out) { return -1; }
 
 bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val) { return -1; }
 
-bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
+bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
+
+int py_eq(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __eq__, __eq__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}
+
+int py_ne(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __ne__, __ne__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}
+
+int py_lt(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __lt__, __gt__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}
+
+int py_gt(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __gt__, __lt__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}
+
+int py_ge(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __ge__, __le__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}
+
+int py_le(const py_Ref lhs, const py_Ref rhs) {
+    bool ok = py_binaryop(lhs, rhs, __le__, __ge__);
+    if(!ok) return -1;
+    return py_tobool(py_lastretval());
+}