Patch 8.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)
Files: src/eval.c, src/testdir/test_vim9_expr.vim
*** ../vim-8.2.1188/src/eval.c 2020-07-10 22:45:35.029135161 +0200
--- src/eval.c 2020-07-12 16:27:10.076066980 +0200
***************
*** 2088,2112 ****
{
int result;
typval_T var2;
! evalarg_T nested_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;
}
- evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
result = FALSE;
if (evaluate)
{
--- 2088,2109 ----
{
int result;
typval_T var2;
! evalarg_T *evalarg_used = evalarg;
! evalarg_T local_evalarg;
int orig_flags;
int evaluate;
if (evalarg == NULL)
{
! 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);
result = FALSE;
if (evaluate)
{
***************
*** 2122,2137 ****
/*
* Get the second variable. Recursive!
*/
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
! nested_evalarg.eval_flags = result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
! if (eval1(arg, rettv, &nested_evalarg) == FAIL)
return FAIL;
/*
* Check for the ":".
*/
! p = eval_next_non_blank(*arg, evalarg, &getnext);
if (*p != ':')
{
emsg(_(e_missing_colon));
--- 2119,2134 ----
/*
* Get the second variable. Recursive!
*/
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used);
! evalarg_used->eval_flags = result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
! if (eval1(arg, rettv, evalarg_used) == FAIL)
return FAIL;
/*
* Check for the ":".
*/
! p = eval_next_non_blank(*arg, evalarg_used, &getnext);
if (*p != ':')
{
emsg(_(e_missing_colon));
***************
*** 2140,2154 ****
return FAIL;
}
if (getnext)
! *arg = eval_next_line(evalarg);
/*
* Get the third variable. Recursive!
*/
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
! nested_evalarg.eval_flags = !result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
! if (eval1(arg, &var2, &nested_evalarg) == FAIL)
{
if (evaluate && result)
clear_tv(rettv);
--- 2137,2151 ----
return FAIL;
}
if (getnext)
! *arg = eval_next_line(evalarg_used);
/*
* Get the third variable. Recursive!
*/
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used);
! evalarg_used->eval_flags = !result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
! if (eval1(arg, &var2, evalarg_used) == FAIL)
{
if (evaluate && result)
clear_tv(rettv);
***************
*** 2156,2161 ****
--- 2153,2163 ----
}
if (evaluate && !result)
*rettv = var2;
+
+ if (evalarg == NULL)
+ clear_evalarg(&local_evalarg, NULL);
+ else
+ evalarg->eval_flags = orig_flags;
}
return OK;
***************
*** 2175,2184 ****
{
char_u *p;
int getnext;
- typval_T var2;
- long result;
- int first;
- int error = FALSE;
/*
* Get the first variable.
--- 2177,2182 ----
***************
*** 2187,2256 ****
return FAIL;
/*
! * Repeat until there is no following "||".
*/
- first = TRUE;
- result = FALSE;
p = eval_next_non_blank(*arg, evalarg, &getnext);
! while (p[0] == '|' && p[1] == '|')
{
! evalarg_T nested_evalarg;
int evaluate;
int orig_flags;
!
! if (getnext)
! *arg = eval_next_line(evalarg);
if (evalarg == NULL)
{
! CLEAR_FIELD(nested_evalarg);
! orig_flags = 0;
! evaluate = FALSE;
! }
! else
! {
! nested_evalarg = *evalarg;
! orig_flags = evalarg->eval_flags;
! evaluate = orig_flags & EVAL_EVALUATE;
}
!
! if (evaluate && first)
{
if (tv_get_number_chk(rettv, &error) != 0)
result = TRUE;
clear_tv(rettv);
if (error)
return FAIL;
- first = FALSE;
}
/*
! * Get the second variable.
! */
! *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)
{
! 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, &getnext);
}
return OK;
--- 2185,2261 ----
return FAIL;
/*
! * Handle the "||" operator.
*/
p = eval_next_non_blank(*arg, evalarg, &getnext);
! if (p[0] == '|' && p[1] == '|')
{
! evalarg_T *evalarg_used = evalarg;
! evalarg_T local_evalarg;
int evaluate;
int orig_flags;
! long result = FALSE;
! typval_T var2;
! int error;
if (evalarg == NULL)
{
! CLEAR_FIELD(local_evalarg);
! evalarg_used = &local_evalarg;
}
! 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;
}
/*
! * Repeat until there is no following "||".
*/
! while (p[0] == '|' && p[1] == '|')
{
! 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 (evalarg == NULL)
! clear_evalarg(&local_evalarg, NULL);
! else
! evalarg->eval_flags = orig_flags;
}
return OK;
***************
*** 2270,2279 ****
{
char_u *p;
int getnext;
- typval_T var2;
- long result;
- int first;
- int error = FALSE;
/*
* Get the first variable.
--- 2275,2280 ----
***************
*** 2282,2350 ****
return FAIL;
/*
! * Repeat until there is no following "&&".
*/
- first = TRUE;
- result = TRUE;
p = eval_next_non_blank(*arg, evalarg, &getnext);
! while (p[0] == '&' && p[1] == '&')
{
! evalarg_T nested_evalarg;
int orig_flags;
int evaluate;
!
! if (getnext)
! *arg = eval_next_line(evalarg);
if (evalarg == NULL)
{
! CLEAR_FIELD(nested_evalarg);
! orig_flags = 0;
! evaluate = FALSE;
}
! else
! {
! nested_evalarg = *evalarg;
! orig_flags = evalarg->eval_flags;
! evaluate = orig_flags & EVAL_EVALUATE;
! }
! if (evaluate && first)
{
if (tv_get_number_chk(rettv, &error) == 0)
result = FALSE;
clear_tv(rettv);
if (error)
return FAIL;
- first = FALSE;
}
/*
! * Get the second variable.
! */
! *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)
{
! 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, &getnext);
}
return OK;
--- 2283,2359 ----
return FAIL;
/*
! * Handle the "&&" operator.
*/
p = eval_next_non_blank(*arg, evalarg, &getnext);
! if (p[0] == '&' && p[1] == '&')
{
! evalarg_T *evalarg_used = evalarg;
! evalarg_T local_evalarg;
int orig_flags;
int evaluate;
! long result = TRUE;
! typval_T var2;
! int error;
if (evalarg == NULL)
{
! CLEAR_FIELD(local_evalarg);
! evalarg_used = &local_evalarg;
}
! 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;
}
/*
! * Repeat until there is no following "&&".
*/
! while (p[0] == '&' && p[1] == '&')
{
! 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 (evalarg == NULL)
! clear_evalarg(&local_evalarg, NULL);
! else
! evalarg->eval_flags = orig_flags;
}
return OK;
*** ../vim-8.2.1188/src/testdir/test_vim9_expr.vim 2020-07-11
15:20:43.776269437 +0200
--- src/testdir/test_vim9_expr.vim 2020-07-12 15:37:08.488407961 +0200
***************
*** 1071,1076 ****
--- 1071,1097 ----
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
*** ../vim-8.2.1188/src/version.c 2020-07-12 14:33:56.019239236 +0200
--- src/version.c 2020-07-12 15:07:23.263172125 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1189,
/**/
--
hundred-and-one symptoms of being an internet addict:
12. You turn off your Wifi and get this awful empty feeling, like you just
pulled the plug on a loved one.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202007121432.06CEWjjm2501203%40masaka.moolenaar.net.