Mercurial > vim
comparison src/evalfunc.c @ 27831:0a3ab3216b75 v8.2.4441
patch 8.2.4441: Vim9: function argument of filter() not checked like map()
Commit: https://github.com/vim/vim/commit/16f6c8ac94d8412075060945aa90ba90be08656f
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Feb 22 15:12:14 2022 +0000
patch 8.2.4441: Vim9: function argument of filter() not checked like map()
Problem: Vim9: function argument of filter() not checked like map().
Solution: Also check the function argument of filter().
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 22 Feb 2022 16:15:03 +0100 |
parents | f68947167523 |
children | 780818e65dff |
comparison
equal
deleted
inserted
replaced
27830:7b5fd54428cc | 27831:0a3ab3216b75 |
---|---|
484 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); | 484 arg_type_mismatch(&t_list_any, type, context->arg_idx + 1); |
485 return FAIL; | 485 return FAIL; |
486 } | 486 } |
487 | 487 |
488 /* | 488 /* |
489 * Check second argument of map() or filter(). | |
490 */ | |
491 static int | |
492 check_map_filter_arg2(type_T *type, argcontext_T *context, int is_map) | |
493 { | |
494 type_T *expected_member = NULL; | |
495 type_T *(args[2]); | |
496 type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args}; | |
497 | |
498 if (context->arg_types[0].type_curr->tt_type == VAR_LIST | |
499 || context->arg_types[0].type_curr->tt_type == VAR_DICT) | |
500 { | |
501 // Use the declared type if possible, so that an error is given if | |
502 // a declared list changes type, but not if a constant list changes | |
503 // type. | |
504 if (context->arg_types[0].type_decl->tt_type == VAR_LIST | |
505 || context->arg_types[0].type_decl->tt_type == VAR_DICT) | |
506 expected_member = context->arg_types[0].type_decl->tt_member; | |
507 else | |
508 expected_member = context->arg_types[0].type_curr->tt_member; | |
509 } | |
510 else if (context->arg_types[0].type_curr->tt_type == VAR_STRING) | |
511 expected_member = &t_string; | |
512 else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB) | |
513 expected_member = &t_number; | |
514 | |
515 args[0] = NULL; | |
516 args[1] = &t_unknown; | |
517 if (type->tt_argcount != -1) | |
518 { | |
519 if (!(type->tt_argcount == 2 || (type->tt_argcount == 1 | |
520 && (type->tt_flags & TTFLAG_VARARGS)))) | |
521 { | |
522 emsg(_(e_invalid_number_of_arguments)); | |
523 return FAIL; | |
524 } | |
525 if (type->tt_flags & TTFLAG_VARARGS) | |
526 // check the argument types at runtime | |
527 t_func_exp.tt_argcount = -1; | |
528 else | |
529 { | |
530 if (context->arg_types[0].type_curr->tt_type == VAR_STRING | |
531 || context->arg_types[0].type_curr->tt_type == VAR_BLOB | |
532 || context->arg_types[0].type_curr->tt_type == VAR_LIST) | |
533 args[0] = &t_number; | |
534 else if (context->arg_types[0].type_decl->tt_type == VAR_DICT) | |
535 args[0] = &t_string; | |
536 if (args[0] != NULL) | |
537 args[1] = expected_member; | |
538 } | |
539 } | |
540 | |
541 if ((type->tt_member != &t_any && type->tt_member != &t_unknown) | |
542 || args[0] != NULL) | |
543 { | |
544 where_T where = WHERE_INIT; | |
545 | |
546 if (is_map) | |
547 t_func_exp.tt_member = expected_member == NULL | |
548 || type->tt_member == &t_any | |
549 || type->tt_member == &t_unknown | |
550 ? &t_any : expected_member; | |
551 else | |
552 t_func_exp.tt_member = &t_bool; | |
553 if (args[0] == NULL) | |
554 args[0] = &t_unknown; | |
555 | |
556 where.wt_index = 2; | |
557 return check_type(&t_func_exp, type, TRUE, where); | |
558 } | |
559 return OK; | |
560 } | |
561 | |
562 /* | |
489 * Check second argument of filter(): func must return a bool. | 563 * Check second argument of filter(): func must return a bool. |
490 */ | 564 */ |
491 static int | 565 static int |
492 arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) | 566 arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) |
493 { | 567 { |
496 || type == &t_unknown | 570 || type == &t_unknown |
497 || type == &t_any) | 571 || type == &t_any) |
498 return OK; | 572 return OK; |
499 | 573 |
500 if (type->tt_type == VAR_FUNC) | 574 if (type->tt_type == VAR_FUNC) |
501 { | 575 return check_map_filter_arg2(type, context, FALSE); |
502 if (!(type->tt_member->tt_type == VAR_BOOL | 576 semsg(_(e_string_or_function_required_for_argument_nr), 2); |
503 || type->tt_member->tt_type == VAR_NUMBER | 577 return FAIL; |
504 || type->tt_member->tt_type == VAR_UNKNOWN | |
505 || type->tt_member->tt_type == VAR_ANY)) | |
506 { | |
507 arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1); | |
508 return FAIL; | |
509 } | |
510 } | |
511 else | |
512 { | |
513 semsg(_(e_string_or_function_required_for_argument_nr), 2); | |
514 return FAIL; | |
515 } | |
516 return OK; | |
517 } | 578 } |
518 | 579 |
519 /* | 580 /* |
520 * Check second argument of map(), the function. | 581 * Check second argument of map(), the function. |
521 */ | 582 */ |
527 || type == &t_unknown | 588 || type == &t_unknown |
528 || type == &t_any) | 589 || type == &t_any) |
529 return OK; | 590 return OK; |
530 | 591 |
531 if (type->tt_type == VAR_FUNC) | 592 if (type->tt_type == VAR_FUNC) |
532 { | 593 return check_map_filter_arg2(type, context, TRUE); |
533 type_T *expected_ret = NULL; | 594 semsg(_(e_string_or_function_required_for_argument_nr), 2); |
534 type_T *(args[2]); | 595 return FAIL; |
535 type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args}; | |
536 | |
537 if (context->arg_types[0].type_curr->tt_type == VAR_LIST | |
538 || context->arg_types[0].type_curr->tt_type == VAR_DICT) | |
539 { | |
540 // Use the declared type if possible, so that an error is given if | |
541 // a declared list changes type, but not if a constant list changes | |
542 // type. | |
543 if (context->arg_types[0].type_decl->tt_type == VAR_LIST | |
544 || context->arg_types[0].type_decl->tt_type == VAR_DICT) | |
545 expected_ret = context->arg_types[0].type_decl->tt_member; | |
546 else | |
547 expected_ret = context->arg_types[0].type_curr->tt_member; | |
548 } | |
549 else if (context->arg_types[0].type_curr->tt_type == VAR_STRING) | |
550 expected_ret = &t_string; | |
551 else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB) | |
552 expected_ret = &t_number; | |
553 | |
554 args[0] = NULL; | |
555 args[1] = &t_unknown; | |
556 if (type->tt_argcount != -1) | |
557 { | |
558 if (!(type->tt_argcount == 2 || (type->tt_argcount == 1 | |
559 && (type->tt_flags & TTFLAG_VARARGS)))) | |
560 { | |
561 emsg(_(e_invalid_number_of_arguments)); | |
562 return FAIL; | |
563 } | |
564 if (type->tt_flags & TTFLAG_VARARGS) | |
565 // check the argument types at runtime | |
566 t_func_exp.tt_argcount = -1; | |
567 else | |
568 { | |
569 if (context->arg_types[0].type_curr->tt_type == VAR_STRING | |
570 || context->arg_types[0].type_curr->tt_type == VAR_BLOB | |
571 || context->arg_types[0].type_curr->tt_type == VAR_LIST) | |
572 args[0] = &t_number; | |
573 else if (context->arg_types[0].type_decl->tt_type == VAR_DICT) | |
574 args[0] = &t_string; | |
575 if (args[0] != NULL) | |
576 args[1] = expected_ret; | |
577 } | |
578 } | |
579 | |
580 if ((type->tt_member != &t_any && type->tt_member != &t_unknown) | |
581 || args[0] != NULL) | |
582 { | |
583 where_T where = WHERE_INIT; | |
584 | |
585 t_func_exp.tt_member = expected_ret == NULL | |
586 || type->tt_member == &t_any | |
587 || type->tt_member == &t_unknown | |
588 ? &t_any : expected_ret; | |
589 if (args[0] == NULL) | |
590 args[0] = &t_unknown; | |
591 | |
592 where.wt_index = 2; | |
593 return check_type(&t_func_exp, type, TRUE, where); | |
594 } | |
595 } | |
596 else | |
597 { | |
598 semsg(_(e_string_or_function_required_for_argument_nr), 2); | |
599 return FAIL; | |
600 } | |
601 return OK; | |
602 } | 596 } |
603 | 597 |
604 /* | 598 /* |
605 * Check an expression argument, can be a string, funcref or partial. | 599 * Check an expression argument, can be a string, funcref or partial. |
606 * Also accept a bool, a constant resulting from compiling a string argument. | 600 * Also accept a bool, a constant resulting from compiling a string argument. |