Mercurial > vim
diff src/evalfunc.c @ 27503:4cea92e99a5a v8.2.4279
patch 8.2.4279: Vim9: cannot change item type with map() after range()
Commit: https://github.com/vim/vim/commit/8133018f50bc447570825801e93d5ed67e8dac90
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Feb 1 12:11:58 2022 +0000
patch 8.2.4279: Vim9: cannot change item type with map() after range()
Problem: Vim9: cannot change item type with map() after range().
Solution: Split the return type in current type and declared type.
(closes #9665)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 01 Feb 2022 13:15:03 +0100 |
parents | 7480a2e2ca0f |
children | f00a7a2bee21 |
line wrap: on
line diff
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -992,127 +992,209 @@ static argcheck_T arg24_match_func[] = { * Note that "argtypes" is NULL if "argcount" is zero. */ static type_T * -ret_void(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_void(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_void; } static type_T * -ret_any(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_any(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_any; } static type_T * -ret_bool(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_bool(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_bool; } static type_T * -ret_number_bool(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_number_bool(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_number_bool; } static type_T * -ret_number(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_number(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_number; } static type_T * -ret_float(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_float(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_float; } static type_T * -ret_string(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_string(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_string; } static type_T * -ret_list_any(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_list_any(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_any; } static type_T * -ret_list_number(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_list_number(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_number; } static type_T * -ret_list_string(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_range(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type) +{ + // returning a list<number>, but it's not declared as such + *decl_type = &t_list_any; + return &t_list_number; +} + static type_T * +ret_list_string(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_string; } static type_T * -ret_list_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_list_dict_any(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_dict_any; } static type_T * -ret_list_items(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_list_items(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_list_any; } static type_T * -ret_list_string_items(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_list_string_items(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_list_list_string; } static type_T * -ret_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_dict_any(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_dict_any; } static type_T * -ret_job_info(int argcount, type2_T *argtypes UNUSED) +ret_job_info(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { if (argcount == 0) return &t_list_job; return &t_dict_any; } static type_T * -ret_dict_number(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_dict_number(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_dict_number; } static type_T * -ret_dict_string(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_dict_string(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_dict_string; } static type_T * -ret_blob(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_blob(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_blob; } static type_T * -ret_func_any(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_func_any(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_func_any; } static type_T * -ret_func_unknown(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_func_unknown(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_func_unknown; } static type_T * -ret_channel(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_channel(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_channel; } static type_T * -ret_job(int argcount UNUSED, type2_T *argtypes UNUSED) +ret_job(int argcount UNUSED, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return &t_job; } static type_T * -ret_first_arg(int argcount, type2_T *argtypes) +ret_first_arg(int argcount, + type2_T *argtypes, + type_T **decl_type) { if (argcount > 0) + { + *decl_type = argtypes[0].type_decl; return argtypes[0].type_curr; + } return &t_void; } static type_T * -ret_repeat(int argcount, type2_T *argtypes) +ret_extend(int argcount, + type2_T *argtypes, + type_T **decl_type) +{ + if (argcount > 0) + { + *decl_type = argtypes[0].type_decl; + // if the second argument has a different current type then the current + // type is "any" + if (argcount > 1 && !equal_type(argtypes[0].type_curr, + argtypes[1].type_curr, 0)) + { + if (argtypes[0].type_curr->tt_type == VAR_LIST) + return &t_list_any; + if (argtypes[0].type_curr->tt_type == VAR_DICT) + return &t_dict_any; + } + return argtypes[0].type_curr; + } + return &t_void; +} + static type_T * +ret_repeat(int argcount, + type2_T *argtypes, + type_T **decl_type UNUSED) { if (argcount == 0) return &t_any; @@ -1122,7 +1204,9 @@ ret_repeat(int argcount, type2_T *argtyp } // for map(): returns first argument but item type may differ static type_T * -ret_first_cont(int argcount, type2_T *argtypes) +ret_first_cont(int argcount, + type2_T *argtypes, + type_T **decl_type UNUSED) { if (argcount > 0) { @@ -1137,13 +1221,17 @@ ret_first_cont(int argcount, type2_T *ar } // for getline() static type_T * -ret_getline(int argcount, type2_T *argtypes UNUSED) +ret_getline(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { return argcount == 1 ? &t_string : &t_list_string; } // for finddir() static type_T * -ret_finddir(int argcount, type2_T *argtypes UNUSED) +ret_finddir(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { if (argcount < 3) return &t_string; @@ -1156,7 +1244,9 @@ ret_finddir(int argcount, type2_T *argty * one. */ static type_T * -ret_list_or_dict_0(int argcount, type2_T *argtypes UNUSED) +ret_list_or_dict_0(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { if (argcount > 0) return &t_dict_any; @@ -1168,7 +1258,9 @@ ret_list_or_dict_0(int argcount, type2_T * are two. */ static type_T * -ret_list_or_dict_1(int argcount, type2_T *argtypes UNUSED) +ret_list_or_dict_1(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { if (argcount > 1) return &t_dict_any; @@ -1176,7 +1268,9 @@ ret_list_or_dict_1(int argcount, type2_T } static type_T * -ret_argv(int argcount, type2_T *argtypes UNUSED) +ret_argv(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { // argv() returns list of strings if (argcount == 0) @@ -1187,13 +1281,20 @@ ret_argv(int argcount, type2_T *argtypes } static type_T * -ret_remove(int argcount, type2_T *argtypes) +ret_remove(int argcount, + type2_T *argtypes, + type_T **decl_type UNUSED) { if (argcount > 0) { if (argtypes[0].type_curr->tt_type == VAR_LIST || argtypes[0].type_curr->tt_type == VAR_DICT) + { + if (argtypes[0].type_curr->tt_type + == argtypes[0].type_decl->tt_type) + *decl_type = argtypes[0].type_decl->tt_member; return argtypes[0].type_curr->tt_member; + } if (argtypes[0].type_curr->tt_type == VAR_BLOB) return &t_number; } @@ -1201,7 +1302,9 @@ ret_remove(int argcount, type2_T *argtyp } static type_T * -ret_getreg(int argcount, type2_T *argtypes UNUSED) +ret_getreg(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { // Assume that if the third argument is passed it's non-zero if (argcount == 3) @@ -1210,7 +1313,9 @@ ret_getreg(int argcount, type2_T *argtyp } static type_T * -ret_maparg(int argcount, type2_T *argtypes UNUSED) +ret_maparg(int argcount, + type2_T *argtypes UNUSED, + type_T **decl_type UNUSED) { // Assume that if the fourth argument is passed it's non-zero if (argcount == 4) @@ -1229,7 +1334,8 @@ typedef struct char f_max_argc; // maximal number of arguments char f_argtype; // for method: FEARG_ values argcheck_T *f_argcheck; // list of functions to check argument types - type_T *(*f_retfunc)(int argcount, type2_T *argtypes); + type_T *(*f_retfunc)(int argcount, type2_T *argtypes, + type_T **decl_type); // return type function void (*f_func)(typval_T *args, typval_T *rvar); // implementation of function @@ -1533,7 +1639,7 @@ static funcentry_T global_functions[] = {"expandcmd", 1, 1, FEARG_1, arg1_string, ret_string, f_expandcmd}, {"extend", 2, 3, FEARG_1, arg23_extend, - ret_first_arg, f_extend}, + ret_extend, f_extend}, {"extendnew", 2, 3, FEARG_1, arg23_extendnew, ret_first_cont, f_extendnew}, {"feedkeys", 1, 2, FEARG_1, arg2_string, @@ -1991,7 +2097,7 @@ static funcentry_T global_functions[] = {"rand", 0, 1, FEARG_1, arg1_list_number, ret_number, f_rand}, {"range", 1, 3, FEARG_1, arg3_number, - ret_list_number, f_range}, + ret_range, f_range}, {"readblob", 1, 1, FEARG_1, arg1_string, ret_blob, f_readblob}, {"readdir", 1, 3, FEARG_1, arg3_string_any_dict, @@ -2622,14 +2728,25 @@ internal_func_get_argcount(int idx, int /* * Call the "f_retfunc" function to obtain the return type of function "idx". + * "decl_type" is set to the declared type. * "argtypes" is the list of argument types or NULL when there are no * arguments. * "argcount" may be less than the actual count when only getting the type. */ type_T * -internal_func_ret_type(int idx, int argcount, type2_T *argtypes) -{ - return global_functions[idx].f_retfunc(argcount, argtypes); +internal_func_ret_type( + int idx, + int argcount, + type2_T *argtypes, + type_T **decl_type) +{ + type_T *ret; + + *decl_type = NULL; + ret = global_functions[idx].f_retfunc(argcount, argtypes, decl_type); + if (*decl_type == NULL) + *decl_type = ret; + return ret; } /*