From 95d5e3e437d0fb3264c55df3a5ff5737dbb54445 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 29 Sep 2024 13:06:07 +0800 Subject: [PATCH] add `tuple.__lt__` --- src/interpreter/ceval.c | 29 ++++++++++++++++++++++++++++- src/public/py_tuple.c | 32 ++++++++++++++++++++++++++++++++ tests/06_tuple.py | 17 +++++++++++++++++ tests/77_builtin_func.py | 11 ++++++----- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 03d39c2f..8a8df2c2 100644 --- a/src/interpreter/ceval.c +++ b/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) { diff --git a/src/public/py_tuple.c b/src/public/py_tuple.c index ba504276..8a9a3d55 100644 --- a/src/public/py_tuple.c +++ b/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__); diff --git a/tests/06_tuple.py b/tests/06_tuple.py index 1a45eb49..c7fd1b4b 100644 --- a/tests/06_tuple.py +++ b/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) + + diff --git a/tests/77_builtin_func.py b/tests/77_builtin_func.py index 96427fd2..b6abce3c 100644 --- a/tests/77_builtin_func.py +++ b/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