0
0
mirror of https://github.com/vim/vim.git synced 2025-10-27 09:24:23 -04:00

patch 9.1.1684: min()/max() does not handle float data types

Problem:  min()/max() does not handle float data types
          (ubaldot)
Solution: Extend min() and max() to every comparable type
          (LemonBoy)

Re-use the logic used for plain old comparison operators, this way we
gain support for float values and unify the logic handling the
comparisons.

fixes: #18052
closes: 18055

Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
LemonBoy
2025-08-24 13:09:04 +02:00
committed by Christian Brabandt
parent b922b30cfe
commit 3b3b936125
13 changed files with 167 additions and 145 deletions

View File

@@ -1475,30 +1475,26 @@ copy_tv(typval_T *from, typval_T *to)
/*
* Compare "tv1" and "tv2".
* Put the result in "tv1". Caller should clear "tv2".
*/
int
typval_compare(
typval_compare2(
typval_T *tv1, // first operand
typval_T *tv2, // second operand
exprtype_T type, // operator
int ic) // ignore case
exprtype_T type, // operator
int ic, // ignore case
int *res) // comparison result
{
varnumber_T n1, n2;
int res = 0;
int type_is = type == EXPR_IS || type == EXPR_ISNOT;
if (check_typval_is_value(tv1) == FAIL
|| check_typval_is_value(tv2) == FAIL)
{
clear_tv(tv1);
return FAIL;
}
else if (type_is && tv1->v_type != tv2->v_type)
{
// For "is" a different type always means FALSE, for "isnot"
// it means TRUE.
n1 = (type == EXPR_ISNOT);
*res = (type == EXPR_ISNOT);
}
else if (((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
|| (tv2->v_type == VAR_SPECIAL
@@ -1508,67 +1504,41 @@ typval_compare(
{
n1 = typval_compare_null(tv1, tv2);
if (n1 == MAYBE)
{
clear_tv(tv1);
return FAIL;
}
if (type == EXPR_NEQUAL)
n1 = !n1;
*res = n1;
}
else if (tv1->v_type == VAR_BLOB || tv2->v_type == VAR_BLOB)
{
if (typval_compare_blob(tv1, tv2, type, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_blob(tv1, tv2, type, res) == FAIL)
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
{
if (typval_compare_list(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_list(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_TUPLE || tv2->v_type == VAR_TUPLE)
{
if (typval_compare_tuple(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_tuple(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
{
if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_object(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
{
if (typval_compare_dict(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_dict(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC
|| tv1->v_type == VAR_PARTIAL || tv2->v_type == VAR_PARTIAL)
{
if (typval_compare_func(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_func(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
// If one of the two variables is a float, compare as a float.
@@ -1583,10 +1553,7 @@ typval_compare(
if (!error)
f2 = tv_get_float_chk(tv2, &error);
if (error)
{
clear_tv(tv1);
return FAIL;
}
n1 = FALSE;
switch (type)
{
@@ -1602,6 +1569,7 @@ typval_compare(
case EXPR_MATCH:
default: break; // avoid gcc warning
}
*res = n1;
}
// If one of the two variables is a number, compare as a number.
@@ -1615,10 +1583,7 @@ typval_compare(
if (!error)
n2 = tv_get_number_chk(tv2, &error);
if (error)
{
clear_tv(tv1);
return FAIL;
}
switch (type)
{
case EXPR_IS:
@@ -1633,6 +1598,7 @@ typval_compare(
case EXPR_MATCH:
default: break; // avoid gcc warning
}
*res = n1;
}
else if (in_vim9script() && (tv1->v_type == VAR_BOOL
|| tv2->v_type == VAR_BOOL
@@ -1643,7 +1609,6 @@ typval_compare(
{
semsg(_(e_cannot_compare_str_with_str),
vartype_name(tv1->v_type), vartype_name(tv2->v_type));
clear_tv(tv1);
return FAIL;
}
n1 = tv1->vval.v_number;
@@ -1657,9 +1622,9 @@ typval_compare(
default:
semsg(_(e_invalid_operation_for_str),
vartype_name(tv1->v_type));
clear_tv(tv1);
return FAIL;
}
*res = n1;
}
#ifdef FEAT_JOB_CHANNEL
else if (tv1->v_type == tv2->v_type
@@ -1672,27 +1637,47 @@ typval_compare(
n1 = tv1->vval.v_job == tv2->vval.v_job;
if (type == EXPR_NEQUAL)
n1 = !n1;
*res = n1;
}
#endif
else
{
if (typval_compare_string(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
if (typval_compare_string(tv1, tv2, type, ic, res) == FAIL)
return FAIL;
}
n1 = res;
}
return OK;
}
/*
* Compare "tv1" and "tv2".
* Put the result in "tv1". Caller should clear "tv2".
*/
int
typval_compare(
typval_T *tv1, // first operand
typval_T *tv2, // second operand
exprtype_T type, // operator
int ic) // ignore case
{
int res;
if (typval_compare2(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
return FAIL;
}
clear_tv(tv1);
if (in_vim9script())
{
tv1->v_type = VAR_BOOL;
tv1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE;
tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
}
else
{
tv1->v_type = VAR_NUMBER;
tv1->vval.v_number = n1;
tv1->vval.v_number = res;
}
return OK;