Mercurial > vim
diff src/userfunc.c @ 24400:62e978382fa0 v8.2.2740
patch 8.2.2740: Vim9: lambda with varargs doesn't work
Commit: https://github.com/vim/vim/commit/2a38908b05c1d3973a8edbeb5b3e05a11332faf0
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Apr 9 20:24:31 2021 +0200
patch 8.2.2740: Vim9: lambda with varargs doesn't work
Problem: Vim9: lambda with varargs doesn't work.
Solution: Make "...name" work. Require type to be a list.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 09 Apr 2021 20:30:03 +0200 |
parents | bed5ec739304 |
children | 25db91a3281b |
line wrap: on
line diff
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -68,6 +68,7 @@ one_function_arg( garray_T *argtypes, int types_optional, evalarg_T *evalarg, + int is_vararg, int skip) { char_u *p = arg; @@ -155,7 +156,8 @@ one_function_arg( { if (type == NULL && types_optional) // lambda arguments default to "any" type - type = vim_strsave((char_u *)"any"); + type = vim_strsave((char_u *) + (is_vararg ? "list<any>" : "any")); ((char_u **)argtypes->ga_data)[argtypes->ga_len++] = type; } } @@ -250,7 +252,7 @@ get_function_args( arg = p; p = one_function_arg(p, newargs, argtypes, types_optional, - evalarg, skip); + evalarg, TRUE, skip); if (p == arg) break; if (*skipwhite(p) == '=') @@ -264,7 +266,7 @@ get_function_args( { arg = p; p = one_function_arg(p, newargs, argtypes, types_optional, - evalarg, skip); + evalarg, FALSE, skip); if (p == arg) break; @@ -360,12 +362,14 @@ err_ret: static int parse_argument_types(ufunc_T *fp, garray_T *argtypes, int varargs) { + int len = 0; + ga_init2(&fp->uf_type_list, sizeof(type_T *), 10); if (argtypes->ga_len > 0) { // When "varargs" is set the last name/type goes into uf_va_name // and uf_va_type. - int len = argtypes->ga_len - (varargs ? 1 : 0); + len = argtypes->ga_len - (varargs ? 1 : 0); if (len > 0) fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len); @@ -388,25 +392,35 @@ parse_argument_types(ufunc_T *fp, garray fp->uf_arg_types[i] = type; } } - if (varargs) + } + + if (varargs) + { + char_u *p; + + // Move the last argument "...name: type" to uf_va_name and + // uf_va_type. + fp->uf_va_name = ((char_u **)fp->uf_args.ga_data) + [fp->uf_args.ga_len - 1]; + --fp->uf_args.ga_len; + p = ((char_u **)argtypes->ga_data)[len]; + if (p == NULL) + // TODO: get type from default value + fp->uf_va_type = &t_list_any; + else { - char_u *p; - - // Move the last argument "...name: type" to uf_va_name and - // uf_va_type. - fp->uf_va_name = ((char_u **)fp->uf_args.ga_data) - [fp->uf_args.ga_len - 1]; - --fp->uf_args.ga_len; - p = ((char_u **)argtypes->ga_data)[len]; - if (p == NULL) - // todo: get type from default value - fp->uf_va_type = &t_any; - else - fp->uf_va_type = parse_type(&p, &fp->uf_type_list, TRUE); - if (fp->uf_va_type == NULL) + fp->uf_va_type = parse_type(&p, &fp->uf_type_list, TRUE); + if (fp->uf_va_type != NULL && fp->uf_va_type->tt_type != VAR_LIST) + { + semsg(_(e_variable_arguments_type_must_be_list_str), + ((char_u **)argtypes->ga_data)[len]); return FAIL; + } } + if (fp->uf_va_type == NULL) + return FAIL; } + return OK; } @@ -1236,7 +1250,8 @@ get_lambda_tv( ga_init(&fp->uf_def_args); if (types_optional) { - if (parse_argument_types(fp, &argtypes, FALSE) == FAIL) + if (parse_argument_types(fp, &argtypes, + in_vim9script() && varargs) == FAIL) goto errret; if (ret_type != NULL) { @@ -1264,8 +1279,8 @@ get_lambda_tv( if (sandbox) flags |= FC_SANDBOX; // In legacy script a lambda can be called with more args than - // uf_args.ga_len. - fp->uf_varargs = !in_vim9script(); + // uf_args.ga_len. In Vim9 script "...name" has to be used. + fp->uf_varargs = !in_vim9script() || varargs; fp->uf_flags = flags; fp->uf_calls = 0; fp->uf_script_ctx = current_sctx; @@ -3190,7 +3205,7 @@ list_func_head(ufunc_T *fp, int indent) msg_puts(", "); msg_puts("..."); msg_puts((char *)fp->uf_va_name); - if (fp->uf_va_type) + if (fp->uf_va_type != NULL) { char *tofree;