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.