# HG changeset patch # User Bram Moolenaar # Date 1594565104 -7200 # Node ID 1e5c29d4e5b3c4920f3a3403d1afae4f6ba47645 # Parent 18bfb4c4732ed9de89ecad3ffacb5ce2ccfcaeae patch 8.2.1189: Vim9: line continuation in lambda doesn't always work Commit: https://github.com/vim/vim/commit/8af81d656a4c501611f6211b6379ea9dd650c545 Author: Bram Moolenaar Date: Sun Jul 12 16:32:19 2020 +0200 patch 8.2.1189: Vim9: line continuation in lambda doesn't always work Problem: Vim9: line continuation in lambda doesn't always work. Solution: Do not use a local evalarg unless there isn't one. (closes https://github.com/vim/vim/issues/6439) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -2088,25 +2088,22 @@ eval1(char_u **arg, typval_T *rettv, eva { int result; typval_T var2; - evalarg_T nested_evalarg; + evalarg_T *evalarg_used = evalarg; + evalarg_T local_evalarg; int orig_flags; int evaluate; - if (getnext) - *arg = eval_next_line(evalarg); - if (evalarg == NULL) { - CLEAR_FIELD(nested_evalarg); - orig_flags = 0; + CLEAR_FIELD(local_evalarg); + evalarg_used = &local_evalarg; } - else - { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; - } - - evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE; + orig_flags = evalarg_used->eval_flags; + evaluate = evalarg_used->eval_flags & EVAL_EVALUATE; + + if (getnext) + *arg = eval_next_line(evalarg_used); + result = FALSE; if (evaluate) { @@ -2122,16 +2119,16 @@ eval1(char_u **arg, typval_T *rettv, eva /* * Get the second variable. Recursive! */ - *arg = skipwhite_and_linebreak(*arg + 1, evalarg); - nested_evalarg.eval_flags = result ? orig_flags + *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); + evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE; - if (eval1(arg, rettv, &nested_evalarg) == FAIL) + if (eval1(arg, rettv, evalarg_used) == FAIL) return FAIL; /* * Check for the ":". */ - p = eval_next_non_blank(*arg, evalarg, &getnext); + p = eval_next_non_blank(*arg, evalarg_used, &getnext); if (*p != ':') { emsg(_(e_missing_colon)); @@ -2140,15 +2137,15 @@ eval1(char_u **arg, typval_T *rettv, eva return FAIL; } if (getnext) - *arg = eval_next_line(evalarg); + *arg = eval_next_line(evalarg_used); /* * Get the third variable. Recursive! */ - *arg = skipwhite_and_linebreak(*arg + 1, evalarg); - nested_evalarg.eval_flags = !result ? orig_flags + *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); + evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE; - if (eval1(arg, &var2, &nested_evalarg) == FAIL) + if (eval1(arg, &var2, evalarg_used) == FAIL) { if (evaluate && result) clear_tv(rettv); @@ -2156,6 +2153,11 @@ eval1(char_u **arg, typval_T *rettv, eva } if (evaluate && !result) *rettv = var2; + + if (evalarg == NULL) + clear_evalarg(&local_evalarg, NULL); + else + evalarg->eval_flags = orig_flags; } return OK; @@ -2175,10 +2177,6 @@ eval2(char_u **arg, typval_T *rettv, eva { char_u *p; int getnext; - typval_T var2; - long result; - int first; - int error = FALSE; /* * Get the first variable. @@ -2187,70 +2185,77 @@ eval2(char_u **arg, typval_T *rettv, eva return FAIL; /* - * Repeat until there is no following "||". + * Handle the "||" operator. */ - first = TRUE; - result = FALSE; p = eval_next_non_blank(*arg, evalarg, &getnext); - while (p[0] == '|' && p[1] == '|') + if (p[0] == '|' && p[1] == '|') { - evalarg_T nested_evalarg; + evalarg_T *evalarg_used = evalarg; + evalarg_T local_evalarg; int evaluate; int orig_flags; - - if (getnext) - *arg = eval_next_line(evalarg); + long result = FALSE; + typval_T var2; + int error; if (evalarg == NULL) { - CLEAR_FIELD(nested_evalarg); - orig_flags = 0; - evaluate = FALSE; + CLEAR_FIELD(local_evalarg); + evalarg_used = &local_evalarg; } - else + orig_flags = evalarg_used->eval_flags; + evaluate = orig_flags & EVAL_EVALUATE; + if (evaluate) { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; - evaluate = orig_flags & EVAL_EVALUATE; - } - - if (evaluate && first) - { + error = FALSE; if (tv_get_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); if (error) return FAIL; - first = FALSE; } /* - * Get the second variable. + * Repeat until there is no following "||". */ - *arg = skipwhite_and_linebreak(*arg + 2, evalarg); - nested_evalarg.eval_flags = !result ? orig_flags - : orig_flags & ~EVAL_EVALUATE; - if (eval3(arg, &var2, &nested_evalarg) == FAIL) - return FAIL; - - /* - * Compute the result. - */ - if (evaluate && !result) + while (p[0] == '|' && p[1] == '|') { - if (tv_get_number_chk(&var2, &error) != 0) - result = TRUE; - clear_tv(&var2); - if (error) + if (getnext) + *arg = eval_next_line(evalarg_used); + + /* + * Get the second variable. + */ + *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used); + evalarg_used->eval_flags = !result ? orig_flags + : orig_flags & ~EVAL_EVALUATE; + if (eval3(arg, &var2, evalarg_used) == FAIL) return FAIL; + + /* + * Compute the result. + */ + if (evaluate && !result) + { + if (tv_get_number_chk(&var2, &error) != 0) + result = TRUE; + clear_tv(&var2); + if (error) + return FAIL; + } + if (evaluate) + { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = result; + } + + p = eval_next_non_blank(*arg, evalarg_used, &getnext); } - if (evaluate) - { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = result; - } - - p = eval_next_non_blank(*arg, evalarg, &getnext); + + if (evalarg == NULL) + clear_evalarg(&local_evalarg, NULL); + else + evalarg->eval_flags = orig_flags; } return OK; @@ -2270,10 +2275,6 @@ eval3(char_u **arg, typval_T *rettv, eva { char_u *p; int getnext; - typval_T var2; - long result; - int first; - int error = FALSE; /* * Get the first variable. @@ -2282,69 +2283,77 @@ eval3(char_u **arg, typval_T *rettv, eva return FAIL; /* - * Repeat until there is no following "&&". + * Handle the "&&" operator. */ - first = TRUE; - result = TRUE; p = eval_next_non_blank(*arg, evalarg, &getnext); - while (p[0] == '&' && p[1] == '&') + if (p[0] == '&' && p[1] == '&') { - evalarg_T nested_evalarg; + evalarg_T *evalarg_used = evalarg; + evalarg_T local_evalarg; int orig_flags; int evaluate; - - if (getnext) - *arg = eval_next_line(evalarg); + long result = TRUE; + typval_T var2; + int error; if (evalarg == NULL) { - CLEAR_FIELD(nested_evalarg); - orig_flags = 0; - evaluate = FALSE; + CLEAR_FIELD(local_evalarg); + evalarg_used = &local_evalarg; } - else + orig_flags = evalarg_used->eval_flags; + evaluate = orig_flags & EVAL_EVALUATE; + if (evaluate) { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; - evaluate = orig_flags & EVAL_EVALUATE; - } - if (evaluate && first) - { + error = FALSE; if (tv_get_number_chk(rettv, &error) == 0) result = FALSE; clear_tv(rettv); if (error) return FAIL; - first = FALSE; } /* - * Get the second variable. + * Repeat until there is no following "&&". */ - *arg = skipwhite_and_linebreak(*arg + 2, evalarg); - nested_evalarg.eval_flags = result ? orig_flags - : orig_flags & ~EVAL_EVALUATE; - if (eval4(arg, &var2, &nested_evalarg) == FAIL) - return FAIL; - - /* - * Compute the result. - */ - if (evaluate && result) + while (p[0] == '&' && p[1] == '&') { - if (tv_get_number_chk(&var2, &error) == 0) - result = FALSE; - clear_tv(&var2); - if (error) + if (getnext) + *arg = eval_next_line(evalarg_used); + + /* + * Get the second variable. + */ + *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used); + evalarg_used->eval_flags = result ? orig_flags + : orig_flags & ~EVAL_EVALUATE; + if (eval4(arg, &var2, evalarg_used) == FAIL) return FAIL; + + /* + * Compute the result. + */ + if (evaluate && result) + { + if (tv_get_number_chk(&var2, &error) == 0) + result = FALSE; + clear_tv(&var2); + if (error) + return FAIL; + } + if (evaluate) + { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = result; + } + + p = eval_next_non_blank(*arg, evalarg_used, &getnext); } - if (evaluate) - { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = result; - } - - p = eval_next_non_blank(*arg, evalarg, &getnext); + + if (evalarg == NULL) + clear_evalarg(&local_evalarg, NULL); + else + evalarg->eval_flags = orig_flags; } return OK; diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1071,6 +1071,27 @@ def Test_expr7_lambda() assert_equal('result', La()) assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val})) + " line continuation inside lambda with "cond ? expr : expr" works + let ll = range(3) + map(ll, {k, v -> v % 2 ? { + '111': 111 } : {} + }) + assert_equal([{}, {'111': 111}, {}], ll) + + ll = range(3) + map(ll, {k, v -> v == 8 || v + == 9 + || v % 2 ? 111 : 222 + }) + assert_equal([222, 111, 222], ll) + + ll = range(3) + map(ll, {k, v -> v != 8 && v + != 9 + && v % 2 == 0 ? 111 : 222 + }) + assert_equal([111, 222, 111], ll) + call CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:') enddef diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1189, +/**/ 1188, /**/ 1187,