Browse Source

vim-patch:8.2.0044: expression type is used inconsistently

Problem:    Expression type is used inconsistently.
Solution:   Add "ETYPE_IS" and "ETYPE_ISNOT" as separate enum values.  Rename
            "TYPE_" to "ETYPE_" to avoid confusion.
07a3db89b8
pull/14339/head
Jan Edmund Lazo 4 weeks ago
parent
commit
53cbfd0220
No known key found for this signature in database GPG Key ID: 64915E6E9F735B15
  1. 140
      src/nvim/eval.c
  2. 20
      src/nvim/eval.h
  3. 2
      src/nvim/ex_cmds2.c

140
src/nvim/eval.c

@ -3417,8 +3417,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
char_u *p;
exptype_T type = TYPE_UNKNOWN;
bool type_is = false; // true for "is" and "isnot"
exptype_T type = ETYPE_UNKNOWN;
int len = 2;
bool ic;
@ -3430,35 +3429,42 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
p = *arg;
switch (p[0]) {
case '=': if (p[1] == '=')
type = TYPE_EQUAL;
else if (p[1] == '~')
type = TYPE_MATCH;
case '=':
if (p[1] == '=') {
type = ETYPE_EQUAL;
} else if (p[1] == '~') {
type = ETYPE_MATCH;
}
break;
case '!': if (p[1] == '=')
type = TYPE_NEQUAL;
else if (p[1] == '~')
type = TYPE_NOMATCH;
case '!':
if (p[1] == '=') {
type = ETYPE_NEQUAL;
} else if (p[1] == '~') {
type = ETYPE_NOMATCH;
}
break;
case '>': if (p[1] != '=') {
type = TYPE_GREATER;
case '>':
if (p[1] != '=') {
type = ETYPE_GREATER;
len = 1;
} else
type = TYPE_GEQUAL;
} else {
type = ETYPE_GEQUAL;
}
break;
case '<': if (p[1] != '=') {
type = TYPE_SMALLER;
case '<':
if (p[1] != '=') {
type = ETYPE_SMALLER;
len = 1;
} else
type = TYPE_SEQUAL;
} else {
type = ETYPE_SEQUAL;
}
break;
case 'i': if (p[1] == 's') {
if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') {
len = 5;
}
if (!isalnum(p[len]) && p[len] != '_') {
type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
type_is = true;
type = len == 2 ? ETYPE_IS : ETYPE_ISNOT;
}
}
break;
@ -3467,7 +3473,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
/*
* If there is a comparative operator, use it.
*/
if (type != TYPE_UNKNOWN) {
if (type != ETYPE_UNKNOWN) {
// extra question mark appended: ignore case
if (p[len] == '?') {
ic = true;
@ -3486,7 +3492,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
return FAIL;
}
if (evaluate) {
const int ret = typval_compare(rettv, &var2, type, type_is, ic);
const int ret = typval_compare(rettv, &var2, type, ic);
tv_clear(&var2);
return ret;
@ -10583,26 +10589,26 @@ int typval_compare(
typval_T *typ1, // first operand
typval_T *typ2, // second operand
exptype_T type, // operator
bool type_is, // true for "is" and "isnot"
bool ic // ignore case
)
FUNC_ATTR_NONNULL_ALL
{
varnumber_T n1, n2;
const bool type_is = type == ETYPE_IS || type == ETYPE_ISNOT;
if (type_is && typ1->v_type != typ2->v_type) {
// For "is" a different type always means false, for "notis"
// it means true.
n1 = type == TYPE_NEQUAL;
n1 = type == ETYPE_ISNOT;
} else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) {
if (type_is) {
n1 = typ1->v_type == typ2->v_type
&& typ1->vval.v_list == typ2->vval.v_list;
if (type == TYPE_NEQUAL) {
if (type == ETYPE_ISNOT) {
n1 = !n1;
}
} else if (typ1->v_type != typ2->v_type
|| (type != TYPE_EQUAL && type != TYPE_NEQUAL)) {
|| (type != ETYPE_EQUAL && type != ETYPE_NEQUAL)) {
if (typ1->v_type != typ2->v_type) {
EMSG(_("E691: Can only compare List with List"));
} else {
@ -10613,7 +10619,7 @@ int typval_compare(
} else {
// Compare two Lists for being equal or unequal.
n1 = tv_list_equal(typ1->vval.v_list, typ2->vval.v_list, ic, false);
if (type == TYPE_NEQUAL) {
if (type == ETYPE_NEQUAL) {
n1 = !n1;
}
}
@ -10621,11 +10627,11 @@ int typval_compare(
if (type_is) {
n1 = typ1->v_type == typ2->v_type
&& typ1->vval.v_dict == typ2->vval.v_dict;
if (type == TYPE_NEQUAL) {
if (type == ETYPE_ISNOT) {
n1 = !n1;
}
} else if (typ1->v_type != typ2->v_type
|| (type != TYPE_EQUAL && type != TYPE_NEQUAL)) {
|| (type != ETYPE_EQUAL && type != ETYPE_NEQUAL)) {
if (typ1->v_type != typ2->v_type) {
EMSG(_("E735: Can only compare Dictionary with Dictionary"));
} else {
@ -10636,12 +10642,12 @@ int typval_compare(
} else {
// Compare two Dictionaries for being equal or unequal.
n1 = tv_dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, ic, false);
if (type == TYPE_NEQUAL) {
if (type == ETYPE_NEQUAL) {
n1 = !n1;
}
}
} else if (tv_is_func(*typ1) || tv_is_func(*typ2)) {
if (type != TYPE_EQUAL && type != TYPE_NEQUAL) {
if (type != ETYPE_EQUAL && type != ETYPE_NEQUAL) {
EMSG(_("E694: Invalid operation for Funcrefs"));
tv_clear(typ1);
return FAIL;
@ -10663,43 +10669,47 @@ int typval_compare(
} else {
n1 = tv_equal(typ1, typ2, ic, false);
}
if (type == TYPE_NEQUAL) {
if (type == ETYPE_NEQUAL || type == ETYPE_ISNOT) {
n1 = !n1;
}
} else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT)
&& type != TYPE_MATCH && type != TYPE_NOMATCH) {
&& type != ETYPE_MATCH && type != ETYPE_NOMATCH) {
// If one of the two variables is a float, compare as a float.
// When using "=~" or "!~", always compare as string.
const float_T f1 = tv_get_float(typ1);
const float_T f2 = tv_get_float(typ2);
n1 = false;
switch (type) {
case TYPE_EQUAL: n1 = f1 == f2; break;
case TYPE_NEQUAL: n1 = f1 != f2; break;
case TYPE_GREATER: n1 = f1 > f2; break;
case TYPE_GEQUAL: n1 = f1 >= f2; break;
case TYPE_SMALLER: n1 = f1 < f2; break;
case TYPE_SEQUAL: n1 = f1 <= f2; break;
case TYPE_UNKNOWN:
case TYPE_MATCH:
case TYPE_NOMATCH: break;
case ETYPE_EQUAL: n1 = f1 == f2; break;
case ETYPE_NEQUAL: n1 = f1 != f2; break;
case ETYPE_GREATER: n1 = f1 > f2; break;
case ETYPE_GEQUAL: n1 = f1 >= f2; break;
case ETYPE_SMALLER: n1 = f1 < f2; break;
case ETYPE_SEQUAL: n1 = f1 <= f2; break;
case ETYPE_UNKNOWN:
case ETYPE_IS:
case ETYPE_ISNOT:
case ETYPE_MATCH:
case ETYPE_NOMATCH: break; // avoid gcc warning
}
} else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER)
&& type != TYPE_MATCH && type != TYPE_NOMATCH) {
&& type != ETYPE_MATCH && type != ETYPE_NOMATCH) {
// If one of the two variables is a number, compare as a number.
// When using "=~" or "!~", always compare as string.
n1 = tv_get_number(typ1);
n2 = tv_get_number(typ2);
switch (type) {
case TYPE_EQUAL: n1 = n1 == n2; break;
case TYPE_NEQUAL: n1 = n1 != n2; break;
case TYPE_GREATER: n1 = n1 > n2; break;
case TYPE_GEQUAL: n1 = n1 >= n2; break;
case TYPE_SMALLER: n1 = n1 < n2; break;
case TYPE_SEQUAL: n1 = n1 <= n2; break;
case TYPE_UNKNOWN:
case TYPE_MATCH:
case TYPE_NOMATCH: break;
case ETYPE_EQUAL: n1 = n1 == n2; break;
case ETYPE_NEQUAL: n1 = n1 != n2; break;
case ETYPE_GREATER: n1 = n1 > n2; break;
case ETYPE_GEQUAL: n1 = n1 >= n2; break;
case ETYPE_SMALLER: n1 = n1 < n2; break;
case ETYPE_SEQUAL: n1 = n1 <= n2; break;
case ETYPE_UNKNOWN:
case ETYPE_IS:
case ETYPE_ISNOT:
case ETYPE_MATCH:
case ETYPE_NOMATCH: break; // avoid gcc warning
}
} else {
char buf1[NUMBUFLEN];
@ -10707,28 +10717,30 @@ int typval_compare(
const char *const s1 = tv_get_string_buf(typ1, buf1);
const char *const s2 = tv_get_string_buf(typ2, buf2);
int i;
if (type != TYPE_MATCH && type != TYPE_NOMATCH) {
if (type != ETYPE_MATCH && type != ETYPE_NOMATCH) {
i = mb_strcmp_ic(ic, s1, s2);
} else {
i = 0;
}
n1 = false;
switch (type) {
case TYPE_EQUAL: n1 = i == 0; break;
case TYPE_NEQUAL: n1 = i != 0; break;
case TYPE_GREATER: n1 = i > 0; break;
case TYPE_GEQUAL: n1 = i >= 0; break;
case TYPE_SMALLER: n1 = i < 0; break;
case TYPE_SEQUAL: n1 = i <= 0; break;
case TYPE_MATCH:
case TYPE_NOMATCH:
case ETYPE_EQUAL: n1 = i == 0; break;
case ETYPE_NEQUAL: n1 = i != 0; break;
case ETYPE_GREATER: n1 = i > 0; break;
case ETYPE_GEQUAL: n1 = i >= 0; break;
case ETYPE_SMALLER: n1 = i < 0; break;
case ETYPE_SEQUAL: n1 = i <= 0; break;
case ETYPE_MATCH:
case ETYPE_NOMATCH:
n1 = pattern_match((char_u *)s2, (char_u *)s1, ic);
if (type == TYPE_NOMATCH) {
if (type == ETYPE_NOMATCH) {
n1 = !n1;
}
break;
case TYPE_UNKNOWN: break; // Avoid gcc warning.
case ETYPE_IS:
case ETYPE_ISNOT:
case ETYPE_UNKNOWN: break; // avoid gcc warning
}
}
tv_clear(typ1);

20
src/nvim/eval.h

@ -230,15 +230,17 @@ typedef enum
/// types for expressions.
typedef enum {
TYPE_UNKNOWN = 0,
TYPE_EQUAL, ///< ==
TYPE_NEQUAL, ///< !=
TYPE_GREATER, ///< >
TYPE_GEQUAL, ///< >=
TYPE_SMALLER, ///< <
TYPE_SEQUAL, ///< <=
TYPE_MATCH, ///< =~
TYPE_NOMATCH, ///< !~
ETYPE_UNKNOWN = 0,
ETYPE_EQUAL, ///< ==
ETYPE_NEQUAL, ///< !=
ETYPE_GREATER, ///< >
ETYPE_GEQUAL, ///< >=
ETYPE_SMALLER, ///< <
ETYPE_SEQUAL, ///< <=
ETYPE_MATCH, ///< =~
ETYPE_NOMATCH, ///< !~
ETYPE_IS, ///< is
ETYPE_ISNOT, ///< isnot
} exptype_T;
/// Type for dict_list function

2
src/nvim/ex_cmds2.c

@ -876,7 +876,7 @@ debuggy_find(
debug_newval = typval_tostring(bp->dbg_val);
line = true;
} else {
if (typval_compare(tv, bp->dbg_val, TYPE_EQUAL, true, false) == OK
if (typval_compare(tv, bp->dbg_val, ETYPE_IS, false) == OK
&& tv->vval.v_number == false) {
line = true;
debug_oldval = typval_tostring(bp->dbg_val);

Loading…
Cancel
Save