Mercurial > vim
comparison src/eval.c @ 18966:6bd715870e32 v8.2.0044
patch 8.2.0044: expression type is used inconsistently
Commit: https://github.com/vim/vim/commit/07a3db89b8953bd0964895badb3b662f7514bc10
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Dec 25 18:14:14 2019 +0100
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 25 Dec 2019 18:15:04 +0100 |
parents | 25ebc35e104f |
children | 24941a950cc7 |
comparison
equal
deleted
inserted
replaced
18965:0eb2333df312 | 18966:6bd715870e32 |
---|---|
1995 eval4(char_u **arg, typval_T *rettv, int evaluate) | 1995 eval4(char_u **arg, typval_T *rettv, int evaluate) |
1996 { | 1996 { |
1997 typval_T var2; | 1997 typval_T var2; |
1998 char_u *p; | 1998 char_u *p; |
1999 int i; | 1999 int i; |
2000 exptype_T type = TYPE_UNKNOWN; | 2000 exptype_T type = ETYPE_UNKNOWN; |
2001 int type_is = FALSE; // TRUE for "is" and "isnot" | |
2002 int len = 2; | 2001 int len = 2; |
2003 int ic; | 2002 int ic; |
2004 | 2003 |
2005 /* | 2004 /* |
2006 * Get the first variable. | 2005 * Get the first variable. |
2010 | 2009 |
2011 p = *arg; | 2010 p = *arg; |
2012 switch (p[0]) | 2011 switch (p[0]) |
2013 { | 2012 { |
2014 case '=': if (p[1] == '=') | 2013 case '=': if (p[1] == '=') |
2015 type = TYPE_EQUAL; | 2014 type = ETYPE_EQUAL; |
2016 else if (p[1] == '~') | 2015 else if (p[1] == '~') |
2017 type = TYPE_MATCH; | 2016 type = ETYPE_MATCH; |
2018 break; | 2017 break; |
2019 case '!': if (p[1] == '=') | 2018 case '!': if (p[1] == '=') |
2020 type = TYPE_NEQUAL; | 2019 type = ETYPE_NEQUAL; |
2021 else if (p[1] == '~') | 2020 else if (p[1] == '~') |
2022 type = TYPE_NOMATCH; | 2021 type = ETYPE_NOMATCH; |
2023 break; | 2022 break; |
2024 case '>': if (p[1] != '=') | 2023 case '>': if (p[1] != '=') |
2025 { | 2024 { |
2026 type = TYPE_GREATER; | 2025 type = ETYPE_GREATER; |
2027 len = 1; | 2026 len = 1; |
2028 } | 2027 } |
2029 else | 2028 else |
2030 type = TYPE_GEQUAL; | 2029 type = ETYPE_GEQUAL; |
2031 break; | 2030 break; |
2032 case '<': if (p[1] != '=') | 2031 case '<': if (p[1] != '=') |
2033 { | 2032 { |
2034 type = TYPE_SMALLER; | 2033 type = ETYPE_SMALLER; |
2035 len = 1; | 2034 len = 1; |
2036 } | 2035 } |
2037 else | 2036 else |
2038 type = TYPE_SEQUAL; | 2037 type = ETYPE_SEQUAL; |
2039 break; | 2038 break; |
2040 case 'i': if (p[1] == 's') | 2039 case 'i': if (p[1] == 's') |
2041 { | 2040 { |
2042 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') | 2041 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') |
2043 len = 5; | 2042 len = 5; |
2044 i = p[len]; | 2043 i = p[len]; |
2045 if (!isalnum(i) && i != '_') | 2044 if (!isalnum(i) && i != '_') |
2046 { | 2045 type = len == 2 ? ETYPE_IS : ETYPE_ISNOT; |
2047 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL; | |
2048 type_is = TRUE; | |
2049 } | |
2050 } | 2046 } |
2051 break; | 2047 break; |
2052 } | 2048 } |
2053 | 2049 |
2054 /* | 2050 /* |
2055 * If there is a comparative operator, use it. | 2051 * If there is a comparative operator, use it. |
2056 */ | 2052 */ |
2057 if (type != TYPE_UNKNOWN) | 2053 if (type != ETYPE_UNKNOWN) |
2058 { | 2054 { |
2059 // extra question mark appended: ignore case | 2055 // extra question mark appended: ignore case |
2060 if (p[len] == '?') | 2056 if (p[len] == '?') |
2061 { | 2057 { |
2062 ic = TRUE; | 2058 ic = TRUE; |
2081 clear_tv(rettv); | 2077 clear_tv(rettv); |
2082 return FAIL; | 2078 return FAIL; |
2083 } | 2079 } |
2084 if (evaluate) | 2080 if (evaluate) |
2085 { | 2081 { |
2086 int ret = typval_compare(rettv, &var2, type, type_is, ic); | 2082 int ret = typval_compare(rettv, &var2, type, ic); |
2087 | 2083 |
2088 clear_tv(&var2); | 2084 clear_tv(&var2); |
2089 return ret; | 2085 return ret; |
2090 } | 2086 } |
2091 } | 2087 } |
6161 int | 6157 int |
6162 typval_compare( | 6158 typval_compare( |
6163 typval_T *typ1, // first operand | 6159 typval_T *typ1, // first operand |
6164 typval_T *typ2, // second operand | 6160 typval_T *typ2, // second operand |
6165 exptype_T type, // operator | 6161 exptype_T type, // operator |
6166 int type_is, // TRUE for "is" and "isnot" | |
6167 int ic) // ignore case | 6162 int ic) // ignore case |
6168 { | 6163 { |
6169 int i; | 6164 int i; |
6170 varnumber_T n1, n2; | 6165 varnumber_T n1, n2; |
6171 char_u *s1, *s2; | 6166 char_u *s1, *s2; |
6172 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; | 6167 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; |
6168 int type_is = type == ETYPE_IS || type == ETYPE_ISNOT; | |
6173 | 6169 |
6174 if (type_is && typ1->v_type != typ2->v_type) | 6170 if (type_is && typ1->v_type != typ2->v_type) |
6175 { | 6171 { |
6176 // For "is" a different type always means FALSE, for "notis" | 6172 // For "is" a different type always means FALSE, for "notis" |
6177 // it means TRUE. | 6173 // it means TRUE. |
6178 n1 = (type == TYPE_NEQUAL); | 6174 n1 = (type == ETYPE_ISNOT); |
6179 } | 6175 } |
6180 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB) | 6176 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB) |
6181 { | 6177 { |
6182 if (type_is) | 6178 if (type_is) |
6183 { | 6179 { |
6184 n1 = (typ1->v_type == typ2->v_type | 6180 n1 = (typ1->v_type == typ2->v_type |
6185 && typ1->vval.v_blob == typ2->vval.v_blob); | 6181 && typ1->vval.v_blob == typ2->vval.v_blob); |
6186 if (type == TYPE_NEQUAL) | 6182 if (type == ETYPE_ISNOT) |
6187 n1 = !n1; | 6183 n1 = !n1; |
6188 } | 6184 } |
6189 else if (typ1->v_type != typ2->v_type | 6185 else if (typ1->v_type != typ2->v_type |
6190 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) | 6186 || (type != ETYPE_EQUAL && type != ETYPE_NEQUAL)) |
6191 { | 6187 { |
6192 if (typ1->v_type != typ2->v_type) | 6188 if (typ1->v_type != typ2->v_type) |
6193 emsg(_("E977: Can only compare Blob with Blob")); | 6189 emsg(_("E977: Can only compare Blob with Blob")); |
6194 else | 6190 else |
6195 emsg(_(e_invalblob)); | 6191 emsg(_(e_invalblob)); |
6198 } | 6194 } |
6199 else | 6195 else |
6200 { | 6196 { |
6201 // Compare two Blobs for being equal or unequal. | 6197 // Compare two Blobs for being equal or unequal. |
6202 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob); | 6198 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob); |
6203 if (type == TYPE_NEQUAL) | 6199 if (type == ETYPE_NEQUAL) |
6204 n1 = !n1; | 6200 n1 = !n1; |
6205 } | 6201 } |
6206 } | 6202 } |
6207 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) | 6203 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) |
6208 { | 6204 { |
6209 if (type_is) | 6205 if (type_is) |
6210 { | 6206 { |
6211 n1 = (typ1->v_type == typ2->v_type | 6207 n1 = (typ1->v_type == typ2->v_type |
6212 && typ1->vval.v_list == typ2->vval.v_list); | 6208 && typ1->vval.v_list == typ2->vval.v_list); |
6213 if (type == TYPE_NEQUAL) | 6209 if (type == ETYPE_ISNOT) |
6214 n1 = !n1; | 6210 n1 = !n1; |
6215 } | 6211 } |
6216 else if (typ1->v_type != typ2->v_type | 6212 else if (typ1->v_type != typ2->v_type |
6217 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) | 6213 || (type != ETYPE_EQUAL && type != ETYPE_NEQUAL)) |
6218 { | 6214 { |
6219 if (typ1->v_type != typ2->v_type) | 6215 if (typ1->v_type != typ2->v_type) |
6220 emsg(_("E691: Can only compare List with List")); | 6216 emsg(_("E691: Can only compare List with List")); |
6221 else | 6217 else |
6222 emsg(_("E692: Invalid operation for List")); | 6218 emsg(_("E692: Invalid operation for List")); |
6226 else | 6222 else |
6227 { | 6223 { |
6228 // Compare two Lists for being equal or unequal. | 6224 // Compare two Lists for being equal or unequal. |
6229 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list, | 6225 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list, |
6230 ic, FALSE); | 6226 ic, FALSE); |
6231 if (type == TYPE_NEQUAL) | 6227 if (type == ETYPE_NEQUAL) |
6232 n1 = !n1; | 6228 n1 = !n1; |
6233 } | 6229 } |
6234 } | 6230 } |
6235 | 6231 |
6236 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) | 6232 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) |
6237 { | 6233 { |
6238 if (type_is) | 6234 if (type_is) |
6239 { | 6235 { |
6240 n1 = (typ1->v_type == typ2->v_type | 6236 n1 = (typ1->v_type == typ2->v_type |
6241 && typ1->vval.v_dict == typ2->vval.v_dict); | 6237 && typ1->vval.v_dict == typ2->vval.v_dict); |
6242 if (type == TYPE_NEQUAL) | 6238 if (type == ETYPE_ISNOT) |
6243 n1 = !n1; | 6239 n1 = !n1; |
6244 } | 6240 } |
6245 else if (typ1->v_type != typ2->v_type | 6241 else if (typ1->v_type != typ2->v_type |
6246 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) | 6242 || (type != ETYPE_EQUAL && type != ETYPE_NEQUAL)) |
6247 { | 6243 { |
6248 if (typ1->v_type != typ2->v_type) | 6244 if (typ1->v_type != typ2->v_type) |
6249 emsg(_("E735: Can only compare Dictionary with Dictionary")); | 6245 emsg(_("E735: Can only compare Dictionary with Dictionary")); |
6250 else | 6246 else |
6251 emsg(_("E736: Invalid operation for Dictionary")); | 6247 emsg(_("E736: Invalid operation for Dictionary")); |
6255 else | 6251 else |
6256 { | 6252 { |
6257 // Compare two Dictionaries for being equal or unequal. | 6253 // Compare two Dictionaries for being equal or unequal. |
6258 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, | 6254 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, |
6259 ic, FALSE); | 6255 ic, FALSE); |
6260 if (type == TYPE_NEQUAL) | 6256 if (type == ETYPE_NEQUAL) |
6261 n1 = !n1; | 6257 n1 = !n1; |
6262 } | 6258 } |
6263 } | 6259 } |
6264 | 6260 |
6265 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC | 6261 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC |
6266 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL) | 6262 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL) |
6267 { | 6263 { |
6268 if (type != TYPE_EQUAL && type != TYPE_NEQUAL) | 6264 if (type != ETYPE_EQUAL && type != ETYPE_NEQUAL) |
6269 { | 6265 { |
6270 emsg(_("E694: Invalid operation for Funcrefs")); | 6266 emsg(_("E694: Invalid operation for Funcrefs")); |
6271 clear_tv(typ1); | 6267 clear_tv(typ1); |
6272 return FAIL; | 6268 return FAIL; |
6273 } | 6269 } |
6289 else | 6285 else |
6290 n1 = FALSE; | 6286 n1 = FALSE; |
6291 } | 6287 } |
6292 else | 6288 else |
6293 n1 = tv_equal(typ1, typ2, ic, FALSE); | 6289 n1 = tv_equal(typ1, typ2, ic, FALSE); |
6294 if (type == TYPE_NEQUAL) | 6290 if (type == ETYPE_NEQUAL || type == ETYPE_ISNOT) |
6295 n1 = !n1; | 6291 n1 = !n1; |
6296 } | 6292 } |
6297 | 6293 |
6298 #ifdef FEAT_FLOAT | 6294 #ifdef FEAT_FLOAT |
6299 /* | 6295 /* |
6300 * If one of the two variables is a float, compare as a float. | 6296 * If one of the two variables is a float, compare as a float. |
6301 * When using "=~" or "!~", always compare as string. | 6297 * When using "=~" or "!~", always compare as string. |
6302 */ | 6298 */ |
6303 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT) | 6299 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT) |
6304 && type != TYPE_MATCH && type != TYPE_NOMATCH) | 6300 && type != ETYPE_MATCH && type != ETYPE_NOMATCH) |
6305 { | 6301 { |
6306 float_T f1, f2; | 6302 float_T f1, f2; |
6307 | 6303 |
6308 f1 = tv_get_float(typ1); | 6304 f1 = tv_get_float(typ1); |
6309 f2 = tv_get_float(typ2); | 6305 f2 = tv_get_float(typ2); |
6310 n1 = FALSE; | 6306 n1 = FALSE; |
6311 switch (type) | 6307 switch (type) |
6312 { | 6308 { |
6313 case TYPE_EQUAL: n1 = (f1 == f2); break; | 6309 case ETYPE_EQUAL: n1 = (f1 == f2); break; |
6314 case TYPE_NEQUAL: n1 = (f1 != f2); break; | 6310 case ETYPE_NEQUAL: n1 = (f1 != f2); break; |
6315 case TYPE_GREATER: n1 = (f1 > f2); break; | 6311 case ETYPE_GREATER: n1 = (f1 > f2); break; |
6316 case TYPE_GEQUAL: n1 = (f1 >= f2); break; | 6312 case ETYPE_GEQUAL: n1 = (f1 >= f2); break; |
6317 case TYPE_SMALLER: n1 = (f1 < f2); break; | 6313 case ETYPE_SMALLER: n1 = (f1 < f2); break; |
6318 case TYPE_SEQUAL: n1 = (f1 <= f2); break; | 6314 case ETYPE_SEQUAL: n1 = (f1 <= f2); break; |
6319 case TYPE_UNKNOWN: | 6315 case ETYPE_UNKNOWN: |
6320 case TYPE_MATCH: | 6316 case ETYPE_IS: |
6321 case TYPE_NOMATCH: break; // avoid gcc warning | 6317 case ETYPE_ISNOT: |
6318 case ETYPE_MATCH: | |
6319 case ETYPE_NOMATCH: break; // avoid gcc warning | |
6322 } | 6320 } |
6323 } | 6321 } |
6324 #endif | 6322 #endif |
6325 | 6323 |
6326 /* | 6324 /* |
6327 * If one of the two variables is a number, compare as a number. | 6325 * If one of the two variables is a number, compare as a number. |
6328 * When using "=~" or "!~", always compare as string. | 6326 * When using "=~" or "!~", always compare as string. |
6329 */ | 6327 */ |
6330 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER) | 6328 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER) |
6331 && type != TYPE_MATCH && type != TYPE_NOMATCH) | 6329 && type != ETYPE_MATCH && type != ETYPE_NOMATCH) |
6332 { | 6330 { |
6333 n1 = tv_get_number(typ1); | 6331 n1 = tv_get_number(typ1); |
6334 n2 = tv_get_number(typ2); | 6332 n2 = tv_get_number(typ2); |
6335 switch (type) | 6333 switch (type) |
6336 { | 6334 { |
6337 case TYPE_EQUAL: n1 = (n1 == n2); break; | 6335 case ETYPE_EQUAL: n1 = (n1 == n2); break; |
6338 case TYPE_NEQUAL: n1 = (n1 != n2); break; | 6336 case ETYPE_NEQUAL: n1 = (n1 != n2); break; |
6339 case TYPE_GREATER: n1 = (n1 > n2); break; | 6337 case ETYPE_GREATER: n1 = (n1 > n2); break; |
6340 case TYPE_GEQUAL: n1 = (n1 >= n2); break; | 6338 case ETYPE_GEQUAL: n1 = (n1 >= n2); break; |
6341 case TYPE_SMALLER: n1 = (n1 < n2); break; | 6339 case ETYPE_SMALLER: n1 = (n1 < n2); break; |
6342 case TYPE_SEQUAL: n1 = (n1 <= n2); break; | 6340 case ETYPE_SEQUAL: n1 = (n1 <= n2); break; |
6343 case TYPE_UNKNOWN: | 6341 case ETYPE_UNKNOWN: |
6344 case TYPE_MATCH: | 6342 case ETYPE_IS: |
6345 case TYPE_NOMATCH: break; // avoid gcc warning | 6343 case ETYPE_ISNOT: |
6344 case ETYPE_MATCH: | |
6345 case ETYPE_NOMATCH: break; // avoid gcc warning | |
6346 } | 6346 } |
6347 } | 6347 } |
6348 else | 6348 else |
6349 { | 6349 { |
6350 s1 = tv_get_string_buf(typ1, buf1); | 6350 s1 = tv_get_string_buf(typ1, buf1); |
6351 s2 = tv_get_string_buf(typ2, buf2); | 6351 s2 = tv_get_string_buf(typ2, buf2); |
6352 if (type != TYPE_MATCH && type != TYPE_NOMATCH) | 6352 if (type != ETYPE_MATCH && type != ETYPE_NOMATCH) |
6353 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); | 6353 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); |
6354 else | 6354 else |
6355 i = 0; | 6355 i = 0; |
6356 n1 = FALSE; | 6356 n1 = FALSE; |
6357 switch (type) | 6357 switch (type) |
6358 { | 6358 { |
6359 case TYPE_EQUAL: n1 = (i == 0); break; | 6359 case ETYPE_EQUAL: n1 = (i == 0); break; |
6360 case TYPE_NEQUAL: n1 = (i != 0); break; | 6360 case ETYPE_NEQUAL: n1 = (i != 0); break; |
6361 case TYPE_GREATER: n1 = (i > 0); break; | 6361 case ETYPE_GREATER: n1 = (i > 0); break; |
6362 case TYPE_GEQUAL: n1 = (i >= 0); break; | 6362 case ETYPE_GEQUAL: n1 = (i >= 0); break; |
6363 case TYPE_SMALLER: n1 = (i < 0); break; | 6363 case ETYPE_SMALLER: n1 = (i < 0); break; |
6364 case TYPE_SEQUAL: n1 = (i <= 0); break; | 6364 case ETYPE_SEQUAL: n1 = (i <= 0); break; |
6365 | 6365 |
6366 case TYPE_MATCH: | 6366 case ETYPE_MATCH: |
6367 case TYPE_NOMATCH: | 6367 case ETYPE_NOMATCH: |
6368 n1 = pattern_match(s2, s1, ic); | 6368 n1 = pattern_match(s2, s1, ic); |
6369 if (type == TYPE_NOMATCH) | 6369 if (type == ETYPE_NOMATCH) |
6370 n1 = !n1; | 6370 n1 = !n1; |
6371 break; | 6371 break; |
6372 | 6372 |
6373 case TYPE_UNKNOWN: break; // avoid gcc warning | 6373 case ETYPE_IS: |
6374 case ETYPE_ISNOT: | |
6375 case ETYPE_UNKNOWN: break; // avoid gcc warning | |
6374 } | 6376 } |
6375 } | 6377 } |
6376 clear_tv(typ1); | 6378 clear_tv(typ1); |
6377 typ1->v_type = VAR_NUMBER; | 6379 typ1->v_type = VAR_NUMBER; |
6378 typ1->vval.v_number = n1; | 6380 typ1->vval.v_number = n1; |