diff options
-rw-r--r-- | src/eval.c | 227 | ||||
-rw-r--r-- | src/testdir/test_vim9_expr.vim | 21 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 141 insertions, 109 deletions
diff --git a/src/eval.c b/src/eval.c index 595cd06663..9f2c503d3b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2088,25 +2088,22 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { 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; - } - else - { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; + CLEAR_FIELD(local_evalarg); + evalarg_used = &local_evalarg; } + orig_flags = evalarg_used->eval_flags; + evaluate = evalarg_used->eval_flags & EVAL_EVALUATE; + + if (getnext) + *arg = eval_next_line(evalarg_used); - evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE; result = FALSE; if (evaluate) { @@ -2122,16 +2119,16 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * 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, evalarg_T *evalarg) 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, evalarg_T *evalarg) } 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, evalarg_T *evalarg) { 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, evalarg_T *evalarg) 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 - { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; - evaluate = orig_flags & EVAL_EVALUATE; - } - - if (evaluate && first) + orig_flags = evalarg_used->eval_flags; + evaluate = orig_flags & EVAL_EVALUATE; + if (evaluate) { + 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; - } - if (evaluate) - { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = result; + + /* + * 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); } - 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, evalarg_T *evalarg) { 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, evalarg_T *evalarg) 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 - { - nested_evalarg = *evalarg; - orig_flags = evalarg->eval_flags; - evaluate = orig_flags & EVAL_EVALUATE; - } - if (evaluate && first) + orig_flags = evalarg_used->eval_flags; + evaluate = orig_flags & EVAL_EVALUATE; + if (evaluate) { + 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; - } - if (evaluate) - { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = result; + + /* + * 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); } - 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 index edc655aeac..ede464e519 100644 --- 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 index eaca91f2c9..449d402a83 100644 --- 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, |