Mercurial > vim
comparison src/typval.c @ 26644:2fc1e528e0e1 v8.2.3851
patch 8.2.3851: Vim9: overhead when comparing string, dict or function
Commit: https://github.com/vim/vim/commit/265f811f5a2dac81d9698f5202a661a04ed095f1
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Dec 19 12:33:05 2021 +0000
patch 8.2.3851: Vim9: overhead when comparing string, dict or function
Problem: Vim9: overhead when comparing string, dict or function.
Solution: Call the intented compare function directly. Refactor to avoid
duplicated code.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 19 Dec 2021 13:45:03 +0100 |
parents | 6fd15d82e898 |
children | 1cee572f2fd7 |
comparison
equal
deleted
inserted
replaced
26643:c1613719988c | 26644:2fc1e528e0e1 |
---|---|
1118 break; | 1118 break; |
1119 } | 1119 } |
1120 } | 1120 } |
1121 | 1121 |
1122 /* | 1122 /* |
1123 * Compare "typ1" and "typ2". Put the result in "typ1". | 1123 * Compare "tv1" and "tv2". |
1124 * Put the result in "tv1". Caller should clear "tv2". | |
1124 */ | 1125 */ |
1125 int | 1126 int |
1126 typval_compare( | 1127 typval_compare( |
1127 typval_T *typ1, // first operand | 1128 typval_T *tv1, // first operand |
1128 typval_T *typ2, // second operand | 1129 typval_T *tv2, // second operand |
1129 exprtype_T type, // operator | 1130 exprtype_T type, // operator |
1130 int ic) // ignore case | 1131 int ic) // ignore case |
1131 { | 1132 { |
1132 int i; | |
1133 varnumber_T n1, n2; | 1133 varnumber_T n1, n2; |
1134 char_u *s1, *s2; | 1134 int res = 0; |
1135 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; | |
1136 int type_is = type == EXPR_IS || type == EXPR_ISNOT; | 1135 int type_is = type == EXPR_IS || type == EXPR_ISNOT; |
1137 | 1136 |
1138 if (type_is && typ1->v_type != typ2->v_type) | 1137 if (type_is && tv1->v_type != tv2->v_type) |
1139 { | 1138 { |
1140 // For "is" a different type always means FALSE, for "notis" | 1139 // For "is" a different type always means FALSE, for "notis" |
1141 // it means TRUE. | 1140 // it means TRUE. |
1142 n1 = (type == EXPR_ISNOT); | 1141 n1 = (type == EXPR_ISNOT); |
1143 } | 1142 } |
1144 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB) | 1143 else if (tv1->v_type == VAR_BLOB || tv2->v_type == VAR_BLOB) |
1145 { | 1144 { |
1146 if (type_is) | 1145 if (typval_compare_blob(tv1, tv2, type, &res) == FAIL) |
1147 { | 1146 { |
1148 n1 = (typ1->v_type == typ2->v_type | 1147 clear_tv(tv1); |
1149 && typ1->vval.v_blob == typ2->vval.v_blob); | |
1150 if (type == EXPR_ISNOT) | |
1151 n1 = !n1; | |
1152 } | |
1153 else if (typ1->v_type != typ2->v_type | |
1154 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1155 { | |
1156 if (typ1->v_type != typ2->v_type) | |
1157 emsg(_("E977: Can only compare Blob with Blob")); | |
1158 else | |
1159 emsg(_(e_invalblob)); | |
1160 clear_tv(typ1); | |
1161 return FAIL; | 1148 return FAIL; |
1162 } | 1149 } |
1163 else | 1150 n1 = res; |
1164 { | 1151 } |
1165 // Compare two Blobs for being equal or unequal. | 1152 else if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST) |
1166 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob); | 1153 { |
1167 if (type == EXPR_NEQUAL) | 1154 if (typval_compare_list(tv1, tv2, type, ic, &res) == FAIL) |
1168 n1 = !n1; | 1155 { |
1169 } | 1156 clear_tv(tv1); |
1170 } | |
1171 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) | |
1172 { | |
1173 if (type_is) | |
1174 { | |
1175 n1 = (typ1->v_type == typ2->v_type | |
1176 && typ1->vval.v_list == typ2->vval.v_list); | |
1177 if (type == EXPR_ISNOT) | |
1178 n1 = !n1; | |
1179 } | |
1180 else if (typ1->v_type != typ2->v_type | |
1181 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1182 { | |
1183 if (typ1->v_type != typ2->v_type) | |
1184 emsg(_("E691: Can only compare List with List")); | |
1185 else | |
1186 emsg(_("E692: Invalid operation for List")); | |
1187 clear_tv(typ1); | |
1188 return FAIL; | 1157 return FAIL; |
1189 } | 1158 } |
1190 else | 1159 n1 = res; |
1191 { | 1160 } |
1192 // Compare two Lists for being equal or unequal. | 1161 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT) |
1193 n1 = list_equal(typ1->vval.v_list, typ2->vval.v_list, | 1162 { |
1194 ic, FALSE); | 1163 if (typval_compare_dict(tv1, tv2, type, ic, &res) == FAIL) |
1195 if (type == EXPR_NEQUAL) | 1164 { |
1196 n1 = !n1; | 1165 clear_tv(tv1); |
1197 } | |
1198 } | |
1199 | |
1200 else if (typ1->v_type == VAR_DICT || typ2->v_type == VAR_DICT) | |
1201 { | |
1202 if (type_is) | |
1203 { | |
1204 n1 = (typ1->v_type == typ2->v_type | |
1205 && typ1->vval.v_dict == typ2->vval.v_dict); | |
1206 if (type == EXPR_ISNOT) | |
1207 n1 = !n1; | |
1208 } | |
1209 else if (typ1->v_type != typ2->v_type | |
1210 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1211 { | |
1212 if (typ1->v_type != typ2->v_type) | |
1213 emsg(_("E735: Can only compare Dictionary with Dictionary")); | |
1214 else | |
1215 emsg(_("E736: Invalid operation for Dictionary")); | |
1216 clear_tv(typ1); | |
1217 return FAIL; | 1166 return FAIL; |
1218 } | 1167 } |
1219 else | 1168 n1 = res; |
1220 { | 1169 } |
1221 // Compare two Dictionaries for being equal or unequal. | 1170 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC |
1222 n1 = dict_equal(typ1->vval.v_dict, typ2->vval.v_dict, | 1171 || tv1->v_type == VAR_PARTIAL || tv2->v_type == VAR_PARTIAL) |
1223 ic, FALSE); | 1172 { |
1224 if (type == EXPR_NEQUAL) | 1173 if (typval_compare_func(tv1, tv2, type, ic, &res) == FAIL) |
1225 n1 = !n1; | 1174 { |
1226 } | 1175 clear_tv(tv1); |
1227 } | |
1228 | |
1229 else if (typ1->v_type == VAR_FUNC || typ2->v_type == VAR_FUNC | |
1230 || typ1->v_type == VAR_PARTIAL || typ2->v_type == VAR_PARTIAL) | |
1231 { | |
1232 if (type != EXPR_EQUAL && type != EXPR_NEQUAL | |
1233 && type != EXPR_IS && type != EXPR_ISNOT) | |
1234 { | |
1235 emsg(_("E694: Invalid operation for Funcrefs")); | |
1236 clear_tv(typ1); | |
1237 return FAIL; | 1176 return FAIL; |
1238 } | 1177 } |
1239 if ((typ1->v_type == VAR_PARTIAL | 1178 n1 = res; |
1240 && typ1->vval.v_partial == NULL) | |
1241 || (typ2->v_type == VAR_PARTIAL | |
1242 && typ2->vval.v_partial == NULL)) | |
1243 // When both partials are NULL, then they are equal. | |
1244 // Otherwise they are not equal. | |
1245 n1 = (typ1->vval.v_partial == typ2->vval.v_partial); | |
1246 else if (type_is) | |
1247 { | |
1248 if (typ1->v_type == VAR_FUNC && typ2->v_type == VAR_FUNC) | |
1249 // strings are considered the same if their value is | |
1250 // the same | |
1251 n1 = tv_equal(typ1, typ2, ic, FALSE); | |
1252 else if (typ1->v_type == VAR_PARTIAL | |
1253 && typ2->v_type == VAR_PARTIAL) | |
1254 n1 = (typ1->vval.v_partial == typ2->vval.v_partial); | |
1255 else | |
1256 n1 = FALSE; | |
1257 } | |
1258 else | |
1259 n1 = tv_equal(typ1, typ2, ic, FALSE); | |
1260 if (type == EXPR_NEQUAL || type == EXPR_ISNOT) | |
1261 n1 = !n1; | |
1262 } | 1179 } |
1263 | 1180 |
1264 #ifdef FEAT_FLOAT | 1181 #ifdef FEAT_FLOAT |
1265 // If one of the two variables is a float, compare as a float. | 1182 // If one of the two variables is a float, compare as a float. |
1266 // When using "=~" or "!~", always compare as string. | 1183 // When using "=~" or "!~", always compare as string. |
1267 else if ((typ1->v_type == VAR_FLOAT || typ2->v_type == VAR_FLOAT) | 1184 else if ((tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) |
1268 && type != EXPR_MATCH && type != EXPR_NOMATCH) | 1185 && type != EXPR_MATCH && type != EXPR_NOMATCH) |
1269 { | 1186 { |
1270 float_T f1, f2; | 1187 float_T f1, f2; |
1271 | 1188 |
1272 f1 = tv_get_float(typ1); | 1189 f1 = tv_get_float(tv1); |
1273 f2 = tv_get_float(typ2); | 1190 f2 = tv_get_float(tv2); |
1274 n1 = FALSE; | 1191 n1 = FALSE; |
1275 switch (type) | 1192 switch (type) |
1276 { | 1193 { |
1277 case EXPR_IS: | 1194 case EXPR_IS: |
1278 case EXPR_EQUAL: n1 = (f1 == f2); break; | 1195 case EXPR_EQUAL: n1 = (f1 == f2); break; |
1289 } | 1206 } |
1290 #endif | 1207 #endif |
1291 | 1208 |
1292 // If one of the two variables is a number, compare as a number. | 1209 // If one of the two variables is a number, compare as a number. |
1293 // When using "=~" or "!~", always compare as string. | 1210 // When using "=~" or "!~", always compare as string. |
1294 else if ((typ1->v_type == VAR_NUMBER || typ2->v_type == VAR_NUMBER) | 1211 else if ((tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER) |
1295 && type != EXPR_MATCH && type != EXPR_NOMATCH) | 1212 && type != EXPR_MATCH && type != EXPR_NOMATCH) |
1296 { | 1213 { |
1297 n1 = tv_get_number(typ1); | 1214 n1 = tv_get_number(tv1); |
1298 n2 = tv_get_number(typ2); | 1215 n2 = tv_get_number(tv2); |
1299 switch (type) | 1216 switch (type) |
1300 { | 1217 { |
1301 case EXPR_IS: | 1218 case EXPR_IS: |
1302 case EXPR_EQUAL: n1 = (n1 == n2); break; | 1219 case EXPR_EQUAL: n1 = (n1 == n2); break; |
1303 case EXPR_ISNOT: | 1220 case EXPR_ISNOT: |
1309 case EXPR_UNKNOWN: | 1226 case EXPR_UNKNOWN: |
1310 case EXPR_MATCH: | 1227 case EXPR_MATCH: |
1311 default: break; // avoid gcc warning | 1228 default: break; // avoid gcc warning |
1312 } | 1229 } |
1313 } | 1230 } |
1314 else if (in_vim9script() && (typ1->v_type == VAR_BOOL | 1231 else if (in_vim9script() && (tv1->v_type == VAR_BOOL |
1315 || typ2->v_type == VAR_BOOL | 1232 || tv2->v_type == VAR_BOOL |
1316 || (typ1->v_type == VAR_SPECIAL | 1233 || (tv1->v_type == VAR_SPECIAL |
1317 && typ2->v_type == VAR_SPECIAL))) | 1234 && tv2->v_type == VAR_SPECIAL))) |
1318 { | 1235 { |
1319 if (typ1->v_type != typ2->v_type) | 1236 if (tv1->v_type != tv2->v_type) |
1320 { | 1237 { |
1321 semsg(_(e_cannot_compare_str_with_str), | 1238 semsg(_(e_cannot_compare_str_with_str), |
1322 vartype_name(typ1->v_type), vartype_name(typ2->v_type)); | 1239 vartype_name(tv1->v_type), vartype_name(tv2->v_type)); |
1323 clear_tv(typ1); | 1240 clear_tv(tv1); |
1324 return FAIL; | 1241 return FAIL; |
1325 } | 1242 } |
1326 n1 = typ1->vval.v_number; | 1243 n1 = tv1->vval.v_number; |
1327 n2 = typ2->vval.v_number; | 1244 n2 = tv2->vval.v_number; |
1328 switch (type) | 1245 switch (type) |
1329 { | 1246 { |
1330 case EXPR_IS: | 1247 case EXPR_IS: |
1331 case EXPR_EQUAL: n1 = (n1 == n2); break; | 1248 case EXPR_EQUAL: n1 = (n1 == n2); break; |
1332 case EXPR_ISNOT: | 1249 case EXPR_ISNOT: |
1333 case EXPR_NEQUAL: n1 = (n1 != n2); break; | 1250 case EXPR_NEQUAL: n1 = (n1 != n2); break; |
1334 default: | 1251 default: |
1335 semsg(_(e_invalid_operation_for_str), | 1252 semsg(_(e_invalid_operation_for_str), |
1336 vartype_name(typ1->v_type)); | 1253 vartype_name(tv1->v_type)); |
1337 clear_tv(typ1); | 1254 clear_tv(tv1); |
1338 return FAIL; | 1255 return FAIL; |
1339 } | 1256 } |
1340 } | 1257 } |
1341 else | 1258 else |
1342 { | 1259 { |
1343 if (in_vim9script() | 1260 if (typval_compare_string(tv1, tv2, type, ic, &res) == FAIL) |
1344 && ((typ1->v_type != VAR_STRING && typ1->v_type != VAR_SPECIAL) | 1261 { |
1345 || (typ2->v_type != VAR_STRING && typ2->v_type != VAR_SPECIAL))) | 1262 clear_tv(tv1); |
1346 { | |
1347 semsg(_(e_cannot_compare_str_with_str), | |
1348 vartype_name(typ1->v_type), vartype_name(typ2->v_type)); | |
1349 clear_tv(typ1); | |
1350 return FAIL; | 1263 return FAIL; |
1351 } | 1264 } |
1352 s1 = tv_get_string_buf(typ1, buf1); | 1265 n1 = res; |
1353 s2 = tv_get_string_buf(typ2, buf2); | 1266 } |
1354 if (type != EXPR_MATCH && type != EXPR_NOMATCH) | 1267 clear_tv(tv1); |
1355 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); | 1268 if (in_vim9script()) |
1269 { | |
1270 tv1->v_type = VAR_BOOL; | |
1271 tv1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE; | |
1272 } | |
1273 else | |
1274 { | |
1275 tv1->v_type = VAR_NUMBER; | |
1276 tv1->vval.v_number = n1; | |
1277 } | |
1278 | |
1279 return OK; | |
1280 } | |
1281 | |
1282 /* | |
1283 * Compare "tv1" to "tv2" as lists acording to "type" and "ic". | |
1284 * Put the result, false or true, in "res". | |
1285 * Return FAIL and give an error message when the comparison can't be done. | |
1286 */ | |
1287 int | |
1288 typval_compare_list( | |
1289 typval_T *tv1, | |
1290 typval_T *tv2, | |
1291 exprtype_T type, | |
1292 int ic, | |
1293 int *res) | |
1294 { | |
1295 int val = 0; | |
1296 | |
1297 if (type == EXPR_IS || type == EXPR_ISNOT) | |
1298 { | |
1299 val = (tv1->v_type == tv2->v_type | |
1300 && tv1->vval.v_list == tv2->vval.v_list); | |
1301 if (type == EXPR_ISNOT) | |
1302 val = !val; | |
1303 } | |
1304 else if (tv1->v_type != tv2->v_type | |
1305 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1306 { | |
1307 if (tv1->v_type != tv2->v_type) | |
1308 emsg(_("E691: Can only compare List with List")); | |
1356 else | 1309 else |
1357 i = 0; | 1310 emsg(_("E692: Invalid operation for List")); |
1358 n1 = FALSE; | 1311 return FAIL; |
1359 switch (type) | |
1360 { | |
1361 case EXPR_IS: | |
1362 case EXPR_EQUAL: n1 = (i == 0); break; | |
1363 case EXPR_ISNOT: | |
1364 case EXPR_NEQUAL: n1 = (i != 0); break; | |
1365 case EXPR_GREATER: n1 = (i > 0); break; | |
1366 case EXPR_GEQUAL: n1 = (i >= 0); break; | |
1367 case EXPR_SMALLER: n1 = (i < 0); break; | |
1368 case EXPR_SEQUAL: n1 = (i <= 0); break; | |
1369 | |
1370 case EXPR_MATCH: | |
1371 case EXPR_NOMATCH: | |
1372 n1 = pattern_match(s2, s1, ic); | |
1373 if (type == EXPR_NOMATCH) | |
1374 n1 = !n1; | |
1375 break; | |
1376 | |
1377 default: break; // avoid gcc warning | |
1378 } | |
1379 } | |
1380 clear_tv(typ1); | |
1381 if (in_vim9script()) | |
1382 { | |
1383 typ1->v_type = VAR_BOOL; | |
1384 typ1->vval.v_number = n1 ? VVAL_TRUE : VVAL_FALSE; | |
1385 } | 1312 } |
1386 else | 1313 else |
1387 { | 1314 { |
1388 typ1->v_type = VAR_NUMBER; | 1315 val = list_equal(tv1->vval.v_list, tv2->vval.v_list, |
1389 typ1->vval.v_number = n1; | 1316 ic, FALSE); |
1390 } | 1317 if (type == EXPR_NEQUAL) |
1391 | 1318 val = !val; |
1392 return OK; | 1319 } |
1393 } | 1320 *res = val; |
1394 | 1321 return OK; |
1322 } | |
1323 | |
1324 /* | |
1325 * Compare "tv1" to "tv2" as blobs acording to "type". | |
1326 * Put the result, false or true, in "res". | |
1327 * Return FAIL and give an error message when the comparison can't be done. | |
1328 */ | |
1329 int | |
1330 typval_compare_blob( | |
1331 typval_T *tv1, | |
1332 typval_T *tv2, | |
1333 exprtype_T type, | |
1334 int *res) | |
1335 { | |
1336 int val = 0; | |
1337 | |
1338 if (type == EXPR_IS || type == EXPR_ISNOT) | |
1339 { | |
1340 val = (tv1->v_type == tv2->v_type | |
1341 && tv1->vval.v_blob == tv2->vval.v_blob); | |
1342 if (type == EXPR_ISNOT) | |
1343 val = !val; | |
1344 } | |
1345 else if (tv1->v_type != tv2->v_type | |
1346 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1347 { | |
1348 if (tv1->v_type != tv2->v_type) | |
1349 emsg(_("E977: Can only compare Blob with Blob")); | |
1350 else | |
1351 emsg(_(e_invalblob)); | |
1352 return FAIL; | |
1353 } | |
1354 else | |
1355 { | |
1356 val = blob_equal(tv1->vval.v_blob, tv2->vval.v_blob); | |
1357 if (type == EXPR_NEQUAL) | |
1358 val = !val; | |
1359 } | |
1360 *res = val; | |
1361 return OK; | |
1362 } | |
1363 | |
1364 /* | |
1365 * Compare "tv1" to "tv2" as dictionaries acording to "type" and "ic". | |
1366 * Put the result, false or true, in "res". | |
1367 * Return FAIL and give an error message when the comparison can't be done. | |
1368 */ | |
1369 int | |
1370 typval_compare_dict( | |
1371 typval_T *tv1, | |
1372 typval_T *tv2, | |
1373 exprtype_T type, | |
1374 int ic, | |
1375 int *res) | |
1376 { | |
1377 int val; | |
1378 | |
1379 if (type == EXPR_IS || type == EXPR_ISNOT) | |
1380 { | |
1381 val = (tv1->v_type == tv2->v_type | |
1382 && tv1->vval.v_dict == tv2->vval.v_dict); | |
1383 if (type == EXPR_ISNOT) | |
1384 val = !val; | |
1385 } | |
1386 else if (tv1->v_type != tv2->v_type | |
1387 || (type != EXPR_EQUAL && type != EXPR_NEQUAL)) | |
1388 { | |
1389 if (tv1->v_type != tv2->v_type) | |
1390 emsg(_("E735: Can only compare Dictionary with Dictionary")); | |
1391 else | |
1392 emsg(_("E736: Invalid operation for Dictionary")); | |
1393 return FAIL; | |
1394 } | |
1395 else | |
1396 { | |
1397 val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, FALSE); | |
1398 if (type == EXPR_NEQUAL) | |
1399 val = !val; | |
1400 } | |
1401 *res = val; | |
1402 return OK; | |
1403 } | |
1404 | |
1405 /* | |
1406 * Compare "tv1" to "tv2" as funcrefs acording to "type" and "ic". | |
1407 * Put the result, false or true, in "res". | |
1408 * Return FAIL and give an error message when the comparison can't be done. | |
1409 */ | |
1410 int | |
1411 typval_compare_func( | |
1412 typval_T *tv1, | |
1413 typval_T *tv2, | |
1414 exprtype_T type, | |
1415 int ic, | |
1416 int *res) | |
1417 { | |
1418 int val = 0; | |
1419 | |
1420 if (type != EXPR_EQUAL && type != EXPR_NEQUAL | |
1421 && type != EXPR_IS && type != EXPR_ISNOT) | |
1422 { | |
1423 emsg(_("E694: Invalid operation for Funcrefs")); | |
1424 return FAIL; | |
1425 } | |
1426 if ((tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial == NULL) | |
1427 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial == NULL)) | |
1428 // When both partials are NULL, then they are equal. | |
1429 // Otherwise they are not equal. | |
1430 val = (tv1->vval.v_partial == tv2->vval.v_partial); | |
1431 else if (type == EXPR_IS || type == EXPR_ISNOT) | |
1432 { | |
1433 if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC) | |
1434 // strings are considered the same if their value is | |
1435 // the same | |
1436 val = tv_equal(tv1, tv2, ic, FALSE); | |
1437 else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL) | |
1438 val = (tv1->vval.v_partial == tv2->vval.v_partial); | |
1439 else | |
1440 val = FALSE; | |
1441 } | |
1442 else | |
1443 val = tv_equal(tv1, tv2, ic, FALSE); | |
1444 if (type == EXPR_NEQUAL || type == EXPR_ISNOT) | |
1445 val = !val; | |
1446 *res = val; | |
1447 return OK; | |
1448 } | |
1449 | |
1450 /* | |
1451 * Compare "tv1" to "tv2" as strings according to "type" and "ic". | |
1452 * Put the result, false or true, in "res". | |
1453 * Return FAIL and give an error message when the comparison can't be done. | |
1454 */ | |
1455 int | |
1456 typval_compare_string( | |
1457 typval_T *tv1, | |
1458 typval_T *tv2, | |
1459 exprtype_T type, | |
1460 int ic, | |
1461 int *res) | |
1462 { | |
1463 int i = 0; | |
1464 int val = FALSE; | |
1465 char_u *s1, *s2; | |
1466 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; | |
1467 | |
1468 if (in_vim9script() | |
1469 && ((tv1->v_type != VAR_STRING && tv1->v_type != VAR_SPECIAL) | |
1470 || (tv2->v_type != VAR_STRING && tv2->v_type != VAR_SPECIAL))) | |
1471 { | |
1472 semsg(_(e_cannot_compare_str_with_str), | |
1473 vartype_name(tv1->v_type), vartype_name(tv2->v_type)); | |
1474 return FAIL; | |
1475 } | |
1476 s1 = tv_get_string_buf(tv1, buf1); | |
1477 s2 = tv_get_string_buf(tv2, buf2); | |
1478 if (type != EXPR_MATCH && type != EXPR_NOMATCH) | |
1479 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); | |
1480 switch (type) | |
1481 { | |
1482 case EXPR_IS: | |
1483 case EXPR_EQUAL: val = (i == 0); break; | |
1484 case EXPR_ISNOT: | |
1485 case EXPR_NEQUAL: val = (i != 0); break; | |
1486 case EXPR_GREATER: val = (i > 0); break; | |
1487 case EXPR_GEQUAL: val = (i >= 0); break; | |
1488 case EXPR_SMALLER: val = (i < 0); break; | |
1489 case EXPR_SEQUAL: val = (i <= 0); break; | |
1490 | |
1491 case EXPR_MATCH: | |
1492 case EXPR_NOMATCH: | |
1493 val = pattern_match(s2, s1, ic); | |
1494 if (type == EXPR_NOMATCH) | |
1495 val = !val; | |
1496 break; | |
1497 | |
1498 default: break; // avoid gcc warning | |
1499 } | |
1500 *res = val; | |
1501 return OK; | |
1502 } | |
1395 /* | 1503 /* |
1396 * Convert any type to a string, never give an error. | 1504 * Convert any type to a string, never give an error. |
1397 * When "quotes" is TRUE add quotes to a string. | 1505 * When "quotes" is TRUE add quotes to a string. |
1398 * Returns an allocated string. | 1506 * Returns an allocated string. |
1399 */ | 1507 */ |