summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-07-12 16:32:19 +0200
committerBram Moolenaar <Bram@vim.org>2020-07-12 16:32:19 +0200
commit8af81d656a4c501611f6211b6379ea9dd650c545 (patch)
tree7c360b336a2f89aef1a36b774ea4b76584204a7a
parent6d3a7213f58da834b0fc869d05f87e86010c66cf (diff)
patch 8.2.1189: Vim9: line continuation in lambda doesn't always workv8.2.1189
Problem: Vim9: line continuation in lambda doesn't always work. Solution: Do not use a local evalarg unless there isn't one. (closes #6439)
-rw-r--r--src/eval.c227
-rw-r--r--src/testdir/test_vim9_expr.vim21
-rw-r--r--src/version.c2
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,