summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-12-25 15:24:23 +0100
committerBram Moolenaar <Bram@vim.org>2020-12-25 15:24:23 +0100
commitc754b4cc98253e1935d3ea5790bc60869c7bc091 (patch)
tree53fd5fec3b9c4e849d552473c7bceaf033add07f
parentb2f9e0e2c537bcde16dab3b62687a17e17849ce1 (diff)
downloadvim-git-c754b4cc98253e1935d3ea5790bc60869c7bc091.tar.gz
patch 8.2.2212: Vim9: lambda with => does not work at the script levelv8.2.2212
Problem: Vim9: lambda with => does not work at the script level. Solution: Make it work.
-rw-r--r--src/eval.c7
-rw-r--r--src/testdir/test_vim9_assign.vim6
-rw-r--r--src/testdir/test_vim9_expr.vim18
-rw-r--r--src/userfunc.c37
-rw-r--r--src/version.c2
-rw-r--r--src/vim9type.c2
6 files changed, 56 insertions, 16 deletions
diff --git a/src/eval.c b/src/eval.c
index e3a3592c8..df5b8427d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3349,8 +3349,13 @@ eval7(
/*
* nested expression: (expression).
+ * lambda: (arg) => expr
*/
- case '(': {
+ case '(': ret = NOTDONE;
+ if (in_vim9script())
+ ret = get_lambda_tv(arg, rettv, TRUE, evalarg);
+ if (ret == NOTDONE)
+ {
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
ret = eval1(arg, rettv, evalarg); // recursive!
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index d5e1b3337..ea344fe63 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1027,11 +1027,11 @@ def Test_assign_lambda()
# check if assign a lambda to a variable which type is func or any.
var lines =<< trim END
vim9script
- var FuncRef = {->123}
+ var FuncRef = {-> 123}
assert_equal(123, FuncRef())
- var FuncRef_Func: func = {->123}
+ var FuncRef_Func: func = {-> 123}
assert_equal(123, FuncRef_Func())
- var FuncRef_Any: any = {->123}
+ var FuncRef_Any: any = {-> 123}
assert_equal(123, FuncRef_Any())
END
CheckScriptSuccess(lines)
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index c48172997..73fdb98fc 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -1953,15 +1953,25 @@ def Test_expr7_new_lambda()
# Lambda returning a dict
var Lmb = () => ({key: 42})
assert_equal({key: 42}, Lmb())
+
+ var RefOne: func(number): string = (a: number): string => 'x'
+ var RefTwo: func(number): any = (a: number): any => 'x'
+
+ var Fx = (a) => ({k1: 0,
+ k2: 1})
+ var Fy = (a) => [0,
+ 1]
END
- CheckDefSuccess(lines)
+ CheckDefAndScriptSuccess(lines)
CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1001:')
CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1001:')
CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1001:')
- CheckDefSuccess(["var Ref: func(number): string = (a: number): string => 'x'"])
- CheckDefSuccess(["var Ref: func(number): any = (a: number): any => 'x'"])
+ CheckScriptFailure(["vim9script", "var Ref = (a)=>a + 1"], 'E1004:')
+ CheckScriptFailure(["vim9script", "var Ref = (a)=> a + 1"], 'E1004:')
+ CheckScriptFailure(["vim9script", "var Ref = (a) =>a + 1"], 'E1004:')
+
CheckDefFailure(["var Ref: func(number): number = (a: number): string => 'x'"], 'E1012:')
CheckDefFailure(["var Ref: func(number): string = (a: number): string => 99"], 'E1012:')
@@ -1978,11 +1988,9 @@ def Test_expr7_new_lambda()
# 'E1106: 2 arguments too many')
# CheckDefFailure(["echo 'asdf'->{a -> a}(x)"], 'E1001:', 1)
- CheckDefSuccess(['var Fx = (a) => ({k1: 0,', ' k2: 1})'])
CheckDefFailure(['var Fx = (a) => ({k1: 0', ' k2: 1})'], 'E722:', 2)
CheckDefFailure(['var Fx = (a) => ({k1: 0,', ' k2 1})'], 'E720:', 2)
- CheckDefSuccess(['var Fx = (a) => [0,', ' 1]'])
CheckDefFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2)
enddef
diff --git a/src/userfunc.c b/src/userfunc.c
index 5ba90ae83..ea6fa10d8 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -461,21 +461,35 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
/*
* Skip over "->" or "=>" after the arguments of a lambda.
* If ": type" is found make "ret_type" point to "type".
+ * If "white_error" is not NULL check for correct use of white space and set
+ * "white_error" to TRUE if there is an error.
* Return NULL if no valid arrow found.
*/
static char_u *
-skip_arrow(char_u *start, int equal_arrow, char_u **ret_type)
+skip_arrow(
+ char_u *start,
+ int equal_arrow,
+ char_u **ret_type,
+ int *white_error)
{
- char_u *s = start;
+ char_u *s = start;
+ char_u *bef = start - 2; // "start" points to > of ->
if (equal_arrow)
{
if (*s == ':')
{
+ if (white_error != NULL && !VIM_ISWHITE(s[1]))
+ {
+ *white_error = TRUE;
+ semsg(_(e_white_space_required_after_str), ":");
+ return NULL;
+ }
s = skipwhite(s + 1);
*ret_type = s;
s = skip_type(s, TRUE);
}
+ bef = s;
s = skipwhite(s);
if (*s != '=')
return NULL;
@@ -483,6 +497,14 @@ skip_arrow(char_u *start, int equal_arrow, char_u **ret_type)
}
if (*s != '>')
return NULL;
+ if (white_error != NULL && ((!VIM_ISWHITE(*bef) && *bef != '{')
+ || !IS_WHITE_OR_NUL(s[1])))
+ {
+ *white_error = TRUE;
+ semsg(_(e_white_space_required_before_and_after_str),
+ equal_arrow ? "=>" : "->");
+ return NULL;
+ }
return skipwhite(s + 1);
}
@@ -516,6 +538,7 @@ get_lambda_tv(
int eval_lavars = FALSE;
char_u *tofree = NULL;
int equal_arrow = **arg == '(';
+ int white_error = FALSE;
if (equal_arrow && !in_vim9script())
return NOTDONE;
@@ -529,7 +552,7 @@ get_lambda_tv(
ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
types_optional ? &argtypes : NULL, types_optional,
NULL, NULL, TRUE, NULL, NULL);
- if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type) == NULL)
+ if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
{
if (types_optional)
ga_clear_strings(&argtypes);
@@ -546,12 +569,14 @@ get_lambda_tv(
types_optional ? &argtypes : NULL, types_optional,
&varargs, NULL, FALSE, NULL, NULL);
if (ret == FAIL
- || (*arg = skip_arrow(*arg, equal_arrow, &ret_type)) == NULL)
+ || (s = skip_arrow(*arg, equal_arrow, &ret_type,
+ &white_error)) == NULL)
{
if (types_optional)
ga_clear_strings(&argtypes);
- return NOTDONE;
+ return white_error ? FAIL : NOTDONE;
}
+ *arg = s;
// Set up a flag for checking local variables and arguments.
if (evaluate)
@@ -647,8 +672,6 @@ get_lambda_tv(
if (register_closure(fp) == FAIL)
goto errret;
}
- else
- fp->uf_scoped = NULL;
#ifdef FEAT_PROFILE
if (prof_def_func())
diff --git a/src/version.c b/src/version.c
index 762e91263..75a1e4b2d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2212,
+/**/
2211,
/**/
2210,
diff --git a/src/vim9type.c b/src/vim9type.c
index 7d8df695f..6ea362cb7 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -338,6 +338,8 @@ typval2type_int(typval_T *tv, garray_T *type_gap)
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
&& compile_def_function(ufunc, TRUE, NULL) == FAIL)
return NULL;
+ if (ufunc->uf_func_type == NULL)
+ set_function_type(ufunc);
if (ufunc->uf_func_type != NULL)
return ufunc->uf_func_type;
}