To: vim_dev@googlegroups.com Subject: Patch 8.2.1189 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- 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 ///