forked from aniani/vim
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)
This commit is contained in:
193
src/evalfunc.c
193
src/evalfunc.c
@@ -992,127 +992,209 @@ static argcheck_T arg24_match_func[] = {arg_string_or_list_any, arg_string, arg_
|
||||
* 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 *argtypes)
|
||||
}
|
||||
// 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 *argtypes)
|
||||
}
|
||||
// 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 *argtypes UNUSED)
|
||||
* 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 *argtypes UNUSED)
|
||||
* 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 *argtypes UNUSED)
|
||||
}
|
||||
|
||||
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 UNUSED)
|
||||
}
|
||||
|
||||
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 *argtypes)
|
||||
}
|
||||
|
||||
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 *argtypes UNUSED)
|
||||
}
|
||||
|
||||
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 *argcount, int *min_argcount)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
internal_func_ret_type(
|
||||
int idx,
|
||||
int argcount,
|
||||
type2_T *argtypes,
|
||||
type_T **decl_type)
|
||||
{
|
||||
return global_functions[idx].f_retfunc(argcount, argtypes);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user