Mercurial > vim
comparison src/evalfunc.c @ 22766:a7082e865ffd v8.2.1931
patch 8.2.1931: Vim9: arguments of extend() not checked at compile time
Commit: https://github.com/vim/vim/commit/fbcbffe1ad327f4f0da518abfd5fd7be7fec22b5
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Oct 31 19:33:38 2020 +0100
patch 8.2.1931: Vim9: arguments of extend() not checked at compile time
Problem: Vim9: arguments of extend() not checked at compile time.
Solution: Add argument type checking for extend().
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 31 Oct 2020 19:45:03 +0100 |
parents | ad54acb1bf2c |
children | 3996539f38b4 |
comparison
equal
deleted
inserted
replaced
22765:e484fdc8ca20 | 22766:a7082e865ffd |
---|---|
274 // A function to check one argument type. The first argument is the type to | 274 // A function to check one argument type. The first argument is the type to |
275 // check. If needed, other argument types can be obtained with the context. | 275 // check. If needed, other argument types can be obtained with the context. |
276 // E.g. if "arg_idx" is 1, then (type - 1) is the first argument type. | 276 // E.g. if "arg_idx" is 1, then (type - 1) is the first argument type. |
277 typedef int (*argcheck_T)(type_T *, argcontext_T *); | 277 typedef int (*argcheck_T)(type_T *, argcontext_T *); |
278 | 278 |
279 /* | |
280 * Check "type" is a float or a number. | |
281 */ | |
279 static int | 282 static int |
280 arg_float_or_nr(type_T *type, argcontext_T *context) | 283 arg_float_or_nr(type_T *type, argcontext_T *context) |
281 { | 284 { |
282 if (type->tt_type == VAR_ANY | 285 if (type->tt_type == VAR_ANY |
283 || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER) | 286 || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER) |
284 return OK; | 287 return OK; |
285 arg_type_mismatch(&t_number, type, context->arg_idx + 1); | 288 arg_type_mismatch(&t_number, type, context->arg_idx + 1); |
286 return FAIL; | 289 return FAIL; |
287 } | 290 } |
288 | 291 |
292 /* | |
293 * Check "type" is a number. | |
294 */ | |
289 static int | 295 static int |
290 arg_number(type_T *type, argcontext_T *context) | 296 arg_number(type_T *type, argcontext_T *context) |
291 { | 297 { |
292 return check_type(&t_number, type, TRUE, context->arg_idx + 1); | 298 return check_type(&t_number, type, TRUE, context->arg_idx + 1); |
293 } | 299 } |
294 | 300 |
301 /* | |
302 * Check "type" is a string. | |
303 */ | |
304 static int | |
305 arg_string(type_T *type, argcontext_T *context) | |
306 { | |
307 return check_type(&t_string, type, TRUE, context->arg_idx + 1); | |
308 } | |
309 | |
310 /* | |
311 * Check "type" is a list or a blob. | |
312 */ | |
295 static int | 313 static int |
296 arg_list_or_blob(type_T *type, argcontext_T *context) | 314 arg_list_or_blob(type_T *type, argcontext_T *context) |
297 { | 315 { |
298 if (type->tt_type == VAR_ANY | 316 if (type->tt_type == VAR_ANY |
299 || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB) | 317 || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB) |
301 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); | 319 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); |
302 return FAIL; | 320 return FAIL; |
303 } | 321 } |
304 | 322 |
305 /* | 323 /* |
306 * Check the type is an item of the list or blob of the previous arg. | 324 * Check "type" is a list or a dict. |
325 */ | |
326 static int | |
327 arg_list_or_dict(type_T *type, argcontext_T *context) | |
328 { | |
329 if (type->tt_type == VAR_ANY | |
330 || type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) | |
331 return OK; | |
332 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); | |
333 return FAIL; | |
334 } | |
335 | |
336 /* | |
337 * Check "type" is the same type as the previous argument | |
338 * Must not be used for the first argcheck_T entry. | |
339 */ | |
340 static int | |
341 arg_same_as_prev(type_T *type, argcontext_T *context) | |
342 { | |
343 type_T *prev_type = context->arg_types[context->arg_idx - 1]; | |
344 | |
345 return check_type(prev_type, type, TRUE, context->arg_idx + 1); | |
346 } | |
347 | |
348 /* | |
349 * Check "type" is an item of the list or blob of the previous arg. | |
307 * Must not be used for the first argcheck_T entry. | 350 * Must not be used for the first argcheck_T entry. |
308 */ | 351 */ |
309 static int | 352 static int |
310 arg_item_of_prev(type_T *type, argcontext_T *context) | 353 arg_item_of_prev(type_T *type, argcontext_T *context) |
311 { | 354 { |
322 | 365 |
323 return check_type(expected, type, TRUE, context->arg_idx + 1); | 366 return check_type(expected, type, TRUE, context->arg_idx + 1); |
324 } | 367 } |
325 | 368 |
326 /* | 369 /* |
370 * Check "type" which is the third argument of extend(). | |
371 */ | |
372 static int | |
373 arg_extend3(type_T *type, argcontext_T *context) | |
374 { | |
375 type_T *first_type = context->arg_types[context->arg_idx - 2]; | |
376 | |
377 if (first_type->tt_type == VAR_LIST) | |
378 return arg_number(type, context); | |
379 if (first_type->tt_type == VAR_DICT) | |
380 return arg_string(type, context); | |
381 return OK; | |
382 } | |
383 | |
384 | |
385 /* | |
327 * Lists of functions that check the argument types of a builtin function. | 386 * Lists of functions that check the argument types of a builtin function. |
328 */ | 387 */ |
329 argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; | 388 argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; |
389 argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; | |
390 argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; | |
330 argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; | 391 argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; |
331 | 392 |
332 /* | 393 /* |
333 * Functions that return the return type of a builtin function. | 394 * Functions that return the return type of a builtin function. |
334 * Note that "argtypes" is NULL if "argcount" is zero. | 395 * Note that "argtypes" is NULL if "argcount" is zero. |
565 { | 626 { |
566 {"abs", 1, 1, FEARG_1, arg1_float_or_nr, | 627 {"abs", 1, 1, FEARG_1, arg1_float_or_nr, |
567 ret_any, FLOAT_FUNC(f_abs)}, | 628 ret_any, FLOAT_FUNC(f_abs)}, |
568 {"acos", 1, 1, FEARG_1, NULL, | 629 {"acos", 1, 1, FEARG_1, NULL, |
569 ret_float, FLOAT_FUNC(f_acos)}, | 630 ret_float, FLOAT_FUNC(f_acos)}, |
570 {"add", 2, 2, FEARG_1, NULL, | 631 {"add", 2, 2, FEARG_1, NULL /* arg2_listblob_item */, |
571 ret_first_arg, f_add}, | 632 ret_first_arg, f_add}, |
572 {"and", 2, 2, FEARG_1, NULL, | 633 {"and", 2, 2, FEARG_1, NULL, |
573 ret_number, f_and}, | 634 ret_number, f_and}, |
574 {"append", 2, 2, FEARG_2, NULL, | 635 {"append", 2, 2, FEARG_2, NULL, |
575 ret_number, f_append}, | 636 ret_number, f_append}, |
791 ret_float, FLOAT_FUNC(f_exp)}, | 852 ret_float, FLOAT_FUNC(f_exp)}, |
792 {"expand", 1, 3, FEARG_1, NULL, | 853 {"expand", 1, 3, FEARG_1, NULL, |
793 ret_any, f_expand}, | 854 ret_any, f_expand}, |
794 {"expandcmd", 1, 1, FEARG_1, NULL, | 855 {"expandcmd", 1, 1, FEARG_1, NULL, |
795 ret_string, f_expandcmd}, | 856 ret_string, f_expandcmd}, |
796 {"extend", 2, 3, FEARG_1, NULL, | 857 {"extend", 2, 3, FEARG_1, arg23_extend, |
797 ret_first_arg, f_extend}, | 858 ret_first_arg, f_extend}, |
798 {"feedkeys", 1, 2, FEARG_1, NULL, | 859 {"feedkeys", 1, 2, FEARG_1, NULL, |
799 ret_void, f_feedkeys}, | 860 ret_void, f_feedkeys}, |
800 {"file_readable", 1, 1, FEARG_1, NULL, // obsolete | 861 {"file_readable", 1, 1, FEARG_1, NULL, // obsolete |
801 ret_number, f_filereadable}, | 862 ret_number, f_filereadable}, |