Patch 8.2.1110
Problem: Vim9: line continuation does not work in function arguments.
Solution: Pass "evalarg" to get_func_tv(). Fix seeing double quoted string
as comment.
Files: src/userfunc.c, src/proto/
userfunc.pro, src/eval.c, src/ex_eval.c,
src/list.c, src/dict.c, src/proto/
eval.pro,
src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_func.vim
*** ../vim-8.2.1109/src/userfunc.c 2020-06-29 20:20:28.047899632 +0200
--- src/userfunc.c 2020-07-01 16:17:08.795558275 +0200
***************
*** 601,616 ****
int len, // length of "name" or -1 to use strlen()
typval_T *rettv,
char_u **arg, // argument, pointing to the '('
funcexe_T *funcexe) // various values
{
char_u *argp;
int ret = OK;
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
int argcount = 0; // number of arguments found
- evalarg_T evalarg;
-
- CLEAR_FIELD(evalarg);
- evalarg.eval_flags = funcexe->evaluate ? EVAL_EVALUATE : 0;
/*
* Get the arguments.
--- 601,613 ----
int len, // length of "name" or -1 to use strlen()
typval_T *rettv,
char_u **arg, // argument, pointing to the '('
+ evalarg_T *evalarg, // for line continuation
funcexe_T *funcexe) // various values
{
char_u *argp;
int ret = OK;
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
int argcount = 0; // number of arguments found
/*
* Get the arguments.
***************
*** 619,628 ****
while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0
: funcexe->partial->pt_argc))
{
! argp = skipwhite(argp + 1); // skip the '(' or ','
if (*argp == ')' || *argp == ',' || *argp == NUL)
break;
! if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL)
{
ret = FAIL;
break;
--- 616,627 ----
while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0
: funcexe->partial->pt_argc))
{
! // skip the '(' or ',' and possibly line breaks
! argp = skipwhite_and_linebreak(argp + 1, evalarg);
!
if (*argp == ')' || *argp == ',' || *argp == NUL)
break;
! if (eval1(&argp, &argvars[argcount], evalarg) == FAIL)
{
ret = FAIL;
break;
***************
*** 631,636 ****
--- 630,636 ----
if (*argp != ',')
break;
}
+ argp = skipwhite_and_linebreak(argp, evalarg);
if (*argp == ')')
++argp;
else
***************
*** 3832,3847 ****
int failed = FALSE;
funcdict_T fudi;
partial_T *partial = NULL;
if (eap->skip)
{
// trans_function_name() doesn't work well when skipping, use eval0()
// instead to skip to any following command, e.g. for:
// :if 0 | call dict.foo().bar() | endif
++emsg_skip;
! if (eval0(eap->arg, &rettv, eap, NULL) != FAIL)
clear_tv(&rettv);
--emsg_skip;
return;
}
--- 3832,3850 ----
int failed = FALSE;
funcdict_T fudi;
partial_T *partial = NULL;
+ evalarg_T evalarg;
+ fill_evalarg_from_eap(&evalarg, eap, eap->skip);
if (eap->skip)
{
// trans_function_name() doesn't work well when skipping, use eval0()
// instead to skip to any following command, e.g. for:
// :if 0 | call dict.foo().bar() | endif
++emsg_skip;
! if (eval0(eap->arg, &rettv, eap, &evalarg) != FAIL)
clear_tv(&rettv);
--emsg_skip;
+ clear_evalarg(&evalarg, eap);
return;
}
***************
*** 3918,3924 ****
funcexe.evaluate = !eap->skip;
funcexe.partial = partial;
funcexe.selfdict = fudi.fd_dict;
! if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL)
{
failed = TRUE;
break;
--- 3921,3927 ----
funcexe.evaluate = !eap->skip;
funcexe.partial = partial;
funcexe.selfdict = fudi.fd_dict;
! if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL)
{
failed = TRUE;
break;
***************
*** 3947,3952 ****
--- 3950,3956 ----
}
if (eap->skip)
--emsg_skip;
+ clear_evalarg(&evalarg, eap);
// When inside :try we need to check for following "| catch".
if (!failed || eap->cstack->cs_trylevel > 0)
*** ../vim-8.2.1109/src/proto/
userfunc.pro 2020-06-27 18:06:42.152575113 +0200
--- src/proto/
userfunc.pro 2020-07-01 16:15:05.368237127 +0200
***************
*** 7,13 ****
int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
void emsg_funcname(char *ermsg, char_u *name);
! int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
--- 7,13 ----
int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
void emsg_funcname(char *ermsg, char_u *name);
! int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
*** ../vim-8.2.1109/src/eval.c 2020-07-01 13:07:34.261146025 +0200
--- src/eval.c 2020-07-01 17:07:29.031461006 +0200
***************
*** 153,159 ****
}
#endif
! static void
fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
{
CLEAR_FIELD(*evalarg);
--- 153,159 ----
}
#endif
! void
fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
{
CLEAR_FIELD(*evalarg);
***************
*** 1804,1809 ****
--- 1804,1810 ----
static int
eval_func(
char_u **arg, // points to "(", will be advanced
+ evalarg_T *evalarg,
char_u *name,
int name_len,
typval_T *rettv,
***************
*** 1839,1845 ****
funcexe.evaluate = evaluate;
funcexe.partial = partial;
funcexe.basetv = basetv;
! ret = get_func_tv(s, len, rettv, arg, &funcexe);
}
vim_free(s);
--- 1840,1846 ----
funcexe.evaluate = evaluate;
funcexe.partial = partial;
funcexe.basetv = basetv;
! ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
}
vim_free(s);
***************
*** 1917,1922 ****
--- 1918,1926 ----
return skipwhite(line);
}
+ /*
+ * Call eval_next_non_blank() and get the next line if needed.
+ */
char_u *
skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg)
{
***************
*** 1930,1935 ****
--- 1934,1953 ----
}
/*
+ * Call eval_next_non_blank() and get the next line if needed, but not when a
+ * double quote follows. Used inside an expression.
+ */
+ char_u *
+ skipwhite_and_linebreak_keep_string(char_u *arg, evalarg_T *evalarg)
+ {
+ char_u *p = skipwhite(arg);
+
+ if (*p == '"')
+ return p;
+ return skipwhite_and_linebreak(arg, evalarg);
+ }
+
+ /*
* After using "evalarg" filled from "eap" free the memory.
*/
void
***************
*** 2995,3001 ****
else
{
if (**arg == '(') // recursive!
! ret = eval_func(arg, s, len, rettv, flags, NULL);
else if (flags & EVAL_CONSTANT)
ret = FAIL;
else if (evaluate)
--- 3013,3019 ----
else
{
if (**arg == '(') // recursive!
! ret = eval_func(arg, evalarg, s, len, rettv, flags, NULL);
else if (flags & EVAL_CONSTANT)
ret = FAIL;
else if (evaluate)
***************
*** 3106,3111 ****
--- 3124,3130 ----
static int
call_func_rettv(
char_u **arg,
+ evalarg_T *evalarg,
typval_T *rettv,
int evaluate,
dict_T *selfdict,
***************
*** 3142,3148 ****
funcexe.partial = pt;
funcexe.selfdict = selfdict;
funcexe.basetv = basetv;
! ret = get_func_tv(s, -1, rettv, arg, &funcexe);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
--- 3161,3167 ----
funcexe.partial = pt;
funcexe.selfdict = selfdict;
funcexe.basetv = basetv;
! ret = get_func_tv(s, -1, rettv, arg, evalarg, &funcexe);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
***************
*** 3189,3195 ****
ret = FAIL;
}
else
! ret = call_func_rettv(arg, rettv, evaluate, NULL, &base);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
--- 3208,3214 ----
ret = FAIL;
}
else
! ret = call_func_rettv(arg, evalarg, rettv, evaluate, NULL, &base);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
***************
*** 3208,3214 ****
eval_method(
char_u **arg,
typval_T *rettv,
! int evaluate,
int verbose) // give error messages
{
char_u *name;
--- 3227,3233 ----
eval_method(
char_u **arg,
typval_T *rettv,
! evalarg_T *evalarg,
int verbose) // give error messages
{
char_u *name;
***************
*** 3216,3221 ****
--- 3235,3242 ----
char_u *alias;
typval_T base = *rettv;
int ret;
+ int evaluate = evalarg != NULL
+ && (evalarg->eval_flags & EVAL_EVALUATE);
// Skip over the ->.
*arg += 2;
***************
*** 3247,3253 ****
ret = FAIL;
}
else
! ret = eval_func(arg, name, len, rettv,
evaluate ? EVAL_EVALUATE : 0, &base);
}
--- 3268,3274 ----
ret = FAIL;
}
else
! ret = eval_func(arg, evalarg, name, len, rettv,
evaluate ? EVAL_EVALUATE : 0, &base);
}
***************
*** 5035,5041 ****
{
if (**arg == '(')
{
! ret = call_func_rettv(arg, rettv, evaluate, selfdict, NULL);
// Stop the expression evaluation when immediately aborting on
// error, or when an interrupt occurred or an exception was thrown
--- 5056,5063 ----
{
if (**arg == '(')
{
! ret = call_func_rettv(arg, evalarg, rettv, evaluate,
! selfdict, NULL);
// Stop the expression evaluation when immediately aborting on
// error, or when an interrupt occurred or an exception was thrown
***************
*** 5058,5064 ****
ret = eval_lambda(arg, rettv, evalarg, verbose);
else
// expr->name()
! ret = eval_method(arg, rettv, evaluate, verbose);
}
}
else // **arg == '[' || **arg == '.'
--- 5080,5086 ----
ret = eval_lambda(arg, rettv, evalarg, verbose);
else
// expr->name()
! ret = eval_method(arg, rettv, evalarg, verbose);
}
}
else // **arg == '[' || **arg == '.'
*** ../vim-8.2.1109/src/ex_eval.c 2020-06-28 18:43:36.296992324 +0200
--- src/ex_eval.c 2020-07-01 16:37:14.715189132 +0200
***************
*** 897,909 ****
typval_T tv;
evalarg_T evalarg;
! CLEAR_FIELD(evalarg);
! evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
! if (getline_equal(eap->getline, eap->cookie, getsourceline))
! {
! evalarg.eval_getline = eap->getline;
! evalarg.eval_cookie = eap->cookie;
! }
if (eval0(eap->arg, &tv, eap, &evalarg) == OK)
clear_tv(&tv);
--- 897,903 ----
typval_T tv;
evalarg_T evalarg;
! fill_evalarg_from_eap(&evalarg, eap, eap->skip);
if (eval0(eap->arg, &tv, eap, &evalarg) == OK)
clear_tv(&tv);
*** ../vim-8.2.1109/src/list.c 2020-06-29 20:09:33.266762870 +0200
--- src/list.c 2020-07-01 17:19:20.750886757 +0200
***************
*** 1177,1183 ****
return FAIL;
}
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
while (**arg != ']' && **arg != NUL)
{
if (eval1(arg, &tv, evalarg) == FAIL) // recursive!
--- 1177,1183 ----
return FAIL;
}
! *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
while (**arg != ']' && **arg != NUL)
{
if (eval1(arg, &tv, evalarg) == FAIL) // recursive!
***************
*** 1207,1214 ****
*arg = skipwhite(*arg + 1);
}
! // the "]" can be on the next line
! *arg = skipwhite_and_linebreak(*arg, evalarg);
if (**arg == ']')
break;
--- 1207,1215 ----
*arg = skipwhite(*arg + 1);
}
! // The "]" can be on the next line. But a double quoted string may
! // follow, not a comment.
! *arg = skipwhite_and_linebreak_keep_string(*arg, evalarg);
if (**arg == ']')
break;
***************
*** 2356,2362 ****
}
if (l != NULL)
{
! list_insert_tv(l, &argvars[1], item);
copy_tv(&argvars[0], rettv);
}
}
--- 2357,2363 ----
}
if (l != NULL)
{
! (void)list_insert_tv(l, &argvars[1], item);
copy_tv(&argvars[0], rettv);
}
}
*** ../vim-8.2.1109/src/dict.c 2020-06-27 21:17:55.359214424 +0200
--- src/dict.c 2020-07-01 17:21:16.610157312 +0200
***************
*** 830,836 ****
tvkey.v_type = VAR_UNKNOWN;
tv.v_type = VAR_UNKNOWN;
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
while (**arg != '}' && **arg != NUL)
{
if ((literal
--- 830,836 ----
tvkey.v_type = VAR_UNKNOWN;
tv.v_type = VAR_UNKNOWN;
! *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
while (**arg != '}' && **arg != NUL)
{
if ((literal
***************
*** 862,868 ****
goto failret;
}
! *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
if (eval1(arg, &tv, evalarg) == FAIL) // recursive!
{
if (evaluate)
--- 862,868 ----
goto failret;
}
! *arg = skipwhite_and_linebreak_keep_string(*arg + 1, evalarg);
if (eval1(arg, &tv, evalarg) == FAIL) // recursive!
{
if (evaluate)
***************
*** 904,910 ****
}
// the "}" can be on the next line
! *arg = skipwhite_and_linebreak(*arg, evalarg);
if (**arg == '}')
break;
if (!had_comma)
--- 904,910 ----
}
// the "}" can be on the next line
! *arg = skipwhite_and_linebreak_keep_string(*arg, evalarg);
if (**arg == '}')
break;
if (!had_comma)
*** ../vim-8.2.1109/src/proto/
eval.pro 2020-06-28 18:43:36.296992324 +0200
--- src/proto/
eval.pro 2020-07-01 17:12:53.277350109 +0200
***************
*** 3,8 ****
--- 3,9 ----
varnumber_T num_modulus(varnumber_T n1, varnumber_T n2);
void eval_init(void);
void eval_clear(void);
+ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip);
int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip);
int eval_expr_valid_arg(typval_T *tv);
int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv);
***************
*** 31,36 ****
--- 32,38 ----
char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext);
char_u *eval_next_line(evalarg_T *evalarg);
char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg);
+ char_u *skipwhite_and_linebreak_keep_string(char_u *arg, evalarg_T *evalarg);
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
*** ../vim-8.2.1109/src/testdir/test_vim9_expr.vim 2020-06-27 21:17:55.359214424 +0200
--- src/testdir/test_vim9_expr.vim 2020-07-01 17:11:54.829726236 +0200
***************
*** 1101,1106 ****
--- 1101,1113 ----
lines =<< trim END
vim9script
+ let d = { "one": "one", "two": "two", }
+ assert_equal({'one': 'one', 'two': 'two'}, d)
+ END
+ CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
let d = #{one: 1,
two: 2,
}
*** ../vim-8.2.1109/src/testdir/test_vim9_func.vim 2020-06-30 13:37:57.931017122 +0200
--- src/testdir/test_vim9_func.vim 2020-07-01 16:29:48.046272595 +0200
***************
*** 353,358 ****
--- 353,374 ----
assert_equal('text', var)
("some")->MyFunc()
assert_equal('some', var)
+
+ MyFunc(
+ 'continued'
+ )
+ assert_equal('continued',
+ var
+ )
+
+ call MyFunc(
+ 'more'
+ ..
+ 'lines'
+ )
+ assert_equal(
+ 'morelines',
+ var)
END
writefile(lines, 'Xcall.vim')
source Xcall.vim
*** ../vim-8.2.1109/src/version.c 2020-07-01 16:00:39.936953109 +0200
--- src/version.c 2020-07-01 17:27:14.211918264 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1110,
/**/
--
I used to wonder about the meaning of life. But I looked it
up in the dictionary under "L" and there it was - the meaning
of life. It was less than I expected. - Dogbert
/// Bram Moolenaar -- Br...@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 ///