Explorar el Código

add `tuple.__lt__`

blueloveTH hace 1 año
padre
commit
95d5e3e437
Se han modificado 4 ficheros con 83 adiciones y 6 borrados
  1. 28 1
      src/interpreter/ceval.c
  2. 32 0
      src/public/py_tuple.c
  3. 17 0
      tests/06_tuple.py
  4. 6 5
      tests/77_builtin_func.py

+ 28 - 1
src/interpreter/ceval.c

@@ -1040,6 +1040,33 @@ FrameResult VM__run_top_frame(VM* self) {
     return RES_RETURN;
 }
 
+const static char* op2str(py_Name op) {
+    switch(op) {
+        case __eq__: return "==";
+        case __ne__: return "!=";
+        case __lt__: return "<";
+        case __le__: return "<=";
+        case __gt__: return ">";
+        case __ge__: return ">=";
+        case __add__: return "+";
+        case __sub__: return "-";
+        case __mul__: return "*";
+        case __truediv__: return "/";
+        case __floordiv__: return "//";
+        case __mod__: return "%";
+        case __pow__: return "**";
+        case __lshift__: return "<<";
+        case __rshift__: return ">>";
+        case __and__: return "&";
+        case __or__: return "|";
+        case __xor__: return "^";
+        case __neg__: return "-";
+        case __invert__: return "~";
+        case __matmul__: return "@";
+        default: return py_name2str(op);
+    }
+}
+
 bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
     // [a, b]
     py_Ref magic = py_tpfindmagic(SECOND()->type, op);
@@ -1071,7 +1098,7 @@ bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
         py_newbool(py_retval(), !res);
         return true;
     }
-    return TypeError("unsupported operand type(s) for '%n'", op);
+    return TypeError("unsupported operand type(s) for '%s'", op2str(op));
 }
 
 bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {

+ 32 - 0
src/public/py_tuple.c

@@ -110,6 +110,37 @@ static bool tuple__ne__(int argc, py_Ref argv) {
     return true;
 }
 
+static bool tuple__lt__(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(2);
+    if(!py_istype(py_arg(1), tp_tuple)) {
+        py_newnotimplemented(py_retval());
+        return true;
+    }
+    py_TValue *p0, *p1;
+    int lhs_length = py_tuple_len(py_arg(0));
+    int rhs_length = py_tuple_len(py_arg(1));
+    p0 = py_tuple_data(py_arg(0));
+    p1 = py_tuple_data(py_arg(1));
+    int length = lhs_length < rhs_length ? lhs_length : rhs_length;
+    for(int i = 0; i < length; i++) {
+        int res_lt = py_less(p0 + i, p1 + i);
+        if(res_lt == -1) return false;
+        if(res_lt) {
+            py_newbool(py_retval(), true);
+            return true;
+        } else {
+            int res_eq = py_equal(p0 + i, p1 + i);
+            if(res_eq == -1) return false;
+            if(!res_eq) {
+                py_newbool(py_retval(), false);
+                return true;
+            }
+        }
+    }
+    py_newbool(py_retval(), lhs_length < rhs_length);
+    return true;
+}
+
 static bool tuple__iter__(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     return pk_arrayiter(argv);
@@ -144,6 +175,7 @@ py_Type pk_tuple__register() {
     py_bindmagic(type, __getitem__, tuple__getitem__);
     py_bindmagic(type, __eq__, tuple__eq__);
     py_bindmagic(type, __ne__, tuple__ne__);
+    py_bindmagic(type, __lt__, tuple__lt__);
     py_bindmagic(type, __iter__, tuple__iter__);
     py_bindmagic(type, __contains__, tuple__contains__);
     py_bindmagic(type, __hash__, tuple__hash__);

+ 17 - 0
tests/06_tuple.py

@@ -35,3 +35,20 @@ assert repr(tuple()) == '()'
 # test in and not in
 assert 1 in (1, 2, 3)
 assert 4 not in (1, 2, 3)
+
+# test < and == and !=
+assert (1,2) == (1,2)
+assert (2,1) == (2,1)
+assert (1,) == (1,)
+assert (1,2) != (1,3)
+assert (1,2) != (1,2,3)
+assert (1,2) != (1,)
+
+assert (1,2) < (1,3)
+assert (1,2) < (2,1)
+assert (1,2) < (2,2)
+assert (1,2) < (1,2,3)
+assert (1,2) < (1,2,1)
+assert (1,2) < (1,2,2)
+
+

+ 6 - 5
tests/77_builtin_func.py

@@ -574,11 +574,12 @@ assert max(1, 2, 3) == 3
 assert max([1, 2]) == 2
 assert max([1, 2, 3], key=lambda x: -x) == 1
 
-# assert min([
-#     (1, 2),
-#     (1, 3),
-#     (1, 4),
-# ]) == (1, 2)
+assert min([
+    (3, 1),
+    (1, 2),
+    (1, 3),
+    (1, 4),
+]) == (1, 2)
 
 assert min(1, 2) == 1
 assert max(1, 2) == 2