diff src/eval.c @ 20992:7ee565134d4a v8.2.1047

patch 8.2.1047: Vim9: script cannot use line continuation like :def function Commit: https://github.com/vim/vim/commit/5409f5d8c95007216ae1190565a7a8ee9ebd7100 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jun 24 18:37:35 2020 +0200 patch 8.2.1047: Vim9: script cannot use line continuation like :def function Problem: Vim9: script cannot use line continuation like in a :def function. Solution: Pass the getline function pointer to the eval() functions. Use it for addition and multiplication operators.
author Bram Moolenaar <Bram@vim.org>
date Wed, 24 Jun 2020 18:45:04 +0200
parents 1693ca876049
children 3af71cbcfdbe
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -45,12 +45,12 @@ typedef struct
 } forinfo_T;
 
 static int tv_op(typval_T *tv1, typval_T *tv2, char_u  *op);
-static int eval2(char_u **arg, typval_T *rettv, int flags);
-static int eval3(char_u **arg, typval_T *rettv, int flags);
-static int eval4(char_u **arg, typval_T *rettv, int flags);
-static int eval5(char_u **arg, typval_T *rettv, int flags);
-static int eval6(char_u **arg, typval_T *rettv, int flags, int want_string);
-static int eval7(char_u **arg, typval_T *rettv, int flags, int want_string);
+static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
+static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
+static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
+static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
+static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
+static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
 static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
 
 static int free_unref_items(int copyID);
@@ -169,7 +169,7 @@ eval_to_bool(
 
     if (skip)
 	++emsg_skip;
-    if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL)
+    if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL)
 	*error = TRUE;
     else
     {
@@ -197,7 +197,7 @@ eval1_emsg(char_u **arg, typval_T *rettv
     int		did_emsg_before = did_emsg;
     int		called_emsg_before = called_emsg;
 
-    ret = eval1(arg, rettv, evaluate ? EVAL_EVALUATE : 0);
+    ret = eval1(arg, rettv, evaluate ? &EVALARG_EVALUATE : NULL);
     if (ret == FAIL)
     {
 	// Report the invalid expression unless the expression evaluation has
@@ -325,7 +325,8 @@ eval_to_string_skip(
 
     if (skip)
 	++emsg_skip;
-    if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL || skip)
+    if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE)
+							       == FAIL || skip)
 	retval = NULL;
     else
     {
@@ -348,7 +349,7 @@ skip_expr(char_u **pp)
     typval_T	rettv;
 
     *pp = skipwhite(*pp);
-    return eval1(pp, &rettv, 0);
+    return eval1(pp, &rettv, NULL);
 }
 
 /*
@@ -370,7 +371,7 @@ eval_to_string(
     char_u	numbuf[NUMBUFLEN];
 #endif
 
-    if (eval0(arg, &tv, nextcmd, EVAL_EVALUATE) == FAIL)
+    if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
 	retval = NULL;
     else
     {
@@ -440,7 +441,7 @@ eval_to_number(char_u *expr)
 
     ++emsg_off;
 
-    if (eval1(&p, &rettv, EVAL_EVALUATE) == FAIL)
+    if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL)
 	retval = -1;
     else
     {
@@ -463,7 +464,7 @@ eval_expr(char_u *arg, char_u **nextcmd)
     typval_T	*tv;
 
     tv = ALLOC_ONE(typval_T);
-    if (tv != NULL && eval0(arg, tv, nextcmd, EVAL_EVALUATE) == FAIL)
+    if (tv != NULL && eval0(arg, tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
 	VIM_CLEAR(tv);
 
     return tv;
@@ -588,7 +589,7 @@ eval_foldexpr(char_u *arg, int *cp)
 	++sandbox;
     ++textwinlock;
     *cp = NUL;
-    if (eval0(arg, &tv, NULL, EVAL_EVALUATE) == FAIL)
+    if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
 	retval = 0;
     else
     {
@@ -776,7 +777,7 @@ get_lval(
 	    else
 	    {
 		empty1 = FALSE;
-		if (eval1(&p, &var1, EVAL_EVALUATE) == FAIL)  // recursive!
+		if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL)  // recursive!
 		    return NULL;
 		if (tv_get_string_chk(&var1) == NULL)
 		{
@@ -814,7 +815,7 @@ get_lval(
 		{
 		    lp->ll_empty2 = FALSE;
 		    // recursive!
-		    if (eval1(&p, &var2, EVAL_EVALUATE) == FAIL)
+		    if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
 		    {
 			clear_tv(&var1);
 			return NULL;
@@ -1424,7 +1425,10 @@ eval_for_line(
     char_u	*expr;
     typval_T	tv;
     list_T	*l;
-
+    evalarg_T	evalarg;
+
+    CLEAR_FIELD(evalarg);
+    evalarg.eval_flags = skip ? 0 : EVAL_EVALUATE;
     *errp = TRUE;	// default: there is an error
 
     fi = ALLOC_CLEAR_ONE(forinfo_T);
@@ -1444,8 +1448,7 @@ eval_for_line(
 
     if (skip)
 	++emsg_skip;
-    if (eval0(skipwhite(expr + 2), &tv, nextcmdp, skip ? 0 : EVAL_EVALUATE)
-									 == OK)
+    if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK)
     {
 	*errp = FALSE;
 	if (!skip)
@@ -1764,6 +1767,35 @@ eval_func(
 }
 
 /*
+ * If inside Vim9 script, "arg" points to the end of a line (ignoring comments)
+ * and there is a next line, return the next line (skipping blanks) and set
+ * "getnext".
+ * Otherwise just return "arg" unmodified and set "getnext" to FALSE.
+ * "arg" must point somewhere inside a line, not at the start.
+ */
+    static char_u *
+eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
+{
+    *getnext = FALSE;
+    if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
+	    && evalarg != NULL
+	    && evalarg->eval_cookie != NULL
+	    && (*arg == NUL || (VIM_ISWHITE(arg[-1])
+					     && (*arg == '"' || *arg == '#')))
+	    && source_nextline(evalarg->eval_cookie) != NULL)
+    {
+	char_u *p = source_nextline(evalarg->eval_cookie);
+
+	if (p != NULL)
+	{
+	    *getnext = TRUE;
+	    return skipwhite(p);
+	}
+    }
+    return arg;
+}
+
+/*
  * The "evaluate" argument: When FALSE, the argument is only parsed but not
  * executed.  The function may return OK, but the rettv will be of type
  * VAR_UNKNOWN.  The function still returns FAIL for a syntax error.
@@ -1774,7 +1806,7 @@ eval_func(
  * This calls eval1() and handles error message and nextcmd.
  * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
  * Note: "rettv.v_lock" is not set.
- * "flags" has EVAL_EVALUATE and similar flags.
+ * "evalarg" can be NULL, EVALARG_EVALUATE or a pointer.
  * Return OK or FAIL.
  */
     int
@@ -1782,15 +1814,16 @@ eval0(
     char_u	*arg,
     typval_T	*rettv,
     char_u	**nextcmd,
-    int		flags)
+    evalarg_T	*evalarg)
 {
     int		ret;
     char_u	*p;
     int		did_emsg_before = did_emsg;
     int		called_emsg_before = called_emsg;
+    int		flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 
     p = skipwhite(arg);
-    ret = eval1(&p, rettv, flags);
+    ret = eval1(&p, rettv, evalarg);
     if (ret == FAIL || !ends_excmd2(arg, p))
     {
 	if (ret != FAIL)
@@ -1826,23 +1859,36 @@ eval0(
  * Return OK or FAIL.
  */
     int
-eval1(char_u **arg, typval_T *rettv, int flags)
+eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 {
-    int		result;
-    typval_T	var2;
-
     /*
      * Get the first variable.
      */
-    if (eval2(arg, rettv, flags) == FAIL)
+    if (eval2(arg, rettv, evalarg) == FAIL)
 	return FAIL;
 
     if ((*arg)[0] == '?')
     {
-	int evaluate = flags & EVAL_EVALUATE;
+	int		result;
+	typval_T	var2;
+	evalarg_T	nested_evalarg;
+	int		orig_flags;
+
+	if (evalarg == NULL)
+	{
+	    CLEAR_FIELD(nested_evalarg);
+	    orig_flags = 0;
+	}
+	else
+	{
+	    nested_evalarg = *evalarg;
+	    orig_flags = evalarg->eval_flags;
+	}
+
+	int evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
 
 	result = FALSE;
-	if (flags & EVAL_EVALUATE)
+	if (evaluate)
 	{
 	    int		error = FALSE;
 
@@ -1857,7 +1903,9 @@ eval1(char_u **arg, typval_T *rettv, int
 	 * Get the second variable.  Recursive!
 	 */
 	*arg = skipwhite(*arg + 1);
-	if (eval1(arg, rettv, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
+	nested_evalarg.eval_flags = result ? orig_flags
+						 : orig_flags & ~EVAL_EVALUATE;
+	if (eval1(arg, rettv, &nested_evalarg) == FAIL)
 	    return FAIL;
 
 	/*
@@ -1875,7 +1923,9 @@ eval1(char_u **arg, typval_T *rettv, int
 	 * Get the third variable.  Recursive!
 	 */
 	*arg = skipwhite(*arg + 1);
-	if (eval1(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
+	nested_evalarg.eval_flags = !result ? orig_flags
+						 : orig_flags & ~EVAL_EVALUATE;
+	if (eval1(arg, &var2, &nested_evalarg) == FAIL)
 	{
 	    if (evaluate && result)
 		clear_tv(rettv);
@@ -1898,7 +1948,7 @@ eval1(char_u **arg, typval_T *rettv, int
  * Return OK or FAIL.
  */
     static int
-eval2(char_u **arg, typval_T *rettv, int flags)
+eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 {
     typval_T	var2;
     long	result;
@@ -1908,7 +1958,7 @@ eval2(char_u **arg, typval_T *rettv, int
     /*
      * Get the first variable.
      */
-    if (eval3(arg, rettv, flags) == FAIL)
+    if (eval3(arg, rettv, evalarg) == FAIL)
 	return FAIL;
 
     /*
@@ -1918,7 +1968,22 @@ eval2(char_u **arg, typval_T *rettv, int
     result = FALSE;
     while ((*arg)[0] == '|' && (*arg)[1] == '|')
     {
-	int evaluate = flags & EVAL_EVALUATE;
+	evalarg_T   nested_evalarg;
+	int	    evaluate;
+	int	    orig_flags;
+
+	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)
 	{
@@ -1934,8 +1999,9 @@ eval2(char_u **arg, typval_T *rettv, int
 	 * Get the second variable.
 	 */
 	*arg = skipwhite(*arg + 2);
-	if (eval3(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE)
-								       == FAIL)
+	nested_evalarg.eval_flags = !result ? orig_flags
+						 : orig_flags & ~EVAL_EVALUATE;
+	if (eval3(arg, &var2, &nested_evalarg) == FAIL)
 	    return FAIL;
 
 	/*
@@ -1969,7 +2035,7 @@ eval2(char_u **arg, typval_T *rettv, int
  * Return OK or FAIL.
  */
     static int
-eval3(char_u **arg, typval_T *rettv, int flags)
+eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 {
     typval_T	var2;
     long	result;
@@ -1979,7 +2045,7 @@ eval3(char_u **arg, typval_T *rettv, int
     /*
      * Get the first variable.
      */
-    if (eval4(arg, rettv, flags) == FAIL)
+    if (eval4(arg, rettv, evalarg) == FAIL)
 	return FAIL;
 
     /*
@@ -1989,8 +2055,22 @@ eval3(char_u **arg, typval_T *rettv, int
     result = TRUE;
     while ((*arg)[0] == '&' && (*arg)[1] == '&')
     {
-	int evaluate = flags & EVAL_EVALUATE;
-
+	evalarg_T   nested_evalarg;
+	int	    orig_flags;
+	int	    evaluate;
+
+	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)
@@ -2005,7 +2085,9 @@ eval3(char_u **arg, typval_T *rettv, int
 	 * Get the second variable.
 	 */
 	*arg = skipwhite(*arg + 2);
-	if (eval4(arg, &var2, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
+	nested_evalarg.eval_flags = result ? orig_flags
+						 : orig_flags & ~EVAL_EVALUATE;
+	if (eval4(arg, &var2, &nested_evalarg) == FAIL)
 	    return FAIL;
 
 	/*
@@ -2048,7 +2130,7 @@ eval3(char_u **arg, typval_T *rettv, int
  * Return OK or FAIL.
  */
     static int
-eval4(char_u **arg, typval_T *rettv, int flags)
+eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 {
     typval_T	var2;
     char_u	*p;
@@ -2060,7 +2142,7 @@ eval4(char_u **arg, typval_T *rettv, int
     /*
      * Get the first variable.
      */
-    if (eval5(arg, rettv, flags) == FAIL)
+    if (eval5(arg, rettv, evalarg) == FAIL)
 	return FAIL;
 
     p = *arg;
@@ -2128,12 +2210,12 @@ eval4(char_u **arg, typval_T *rettv, int
 	 * Get the second variable.
 	 */
 	*arg = skipwhite(p + len);
-	if (eval5(arg, &var2, flags) == FAIL)
+	if (eval5(arg, &var2, evalarg) == FAIL)
 	{
 	    clear_tv(rettv);
 	    return FAIL;
 	}
-	if (flags & EVAL_EVALUATE)
+	if (evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE))
 	{
 	    int ret = typval_compare(rettv, &var2, type, ic);
 
@@ -2195,23 +2277,14 @@ eval_addlist(typval_T *tv1, typval_T *tv
  * Return OK or FAIL.
  */
     static int
-eval5(char_u **arg, typval_T *rettv, int flags)
+eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
 {
-    typval_T	var2;
-    int		op;
-    varnumber_T	n1, n2;
-#ifdef FEAT_FLOAT
-    float_T	f1 = 0, f2 = 0;
-#endif
-    char_u	*s1, *s2;
-    char_u	buf1[NUMBUFLEN], buf2[NUMBUFLEN];
-    char_u	*p;
-    int		concat;
+    int	evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
 
     /*
      * Get the first variable.
      */
-    if (eval6(arg, rettv, flags, FALSE) == FAIL)
+    if (eval6(arg, rettv, evalarg, FALSE) == FAIL)
 	return FAIL;
 
     /*
@@ -2219,12 +2292,20 @@ eval5(char_u **arg, typval_T *rettv, int
      */
     for (;;)
     {
+	int	    getnext;
+	char_u	    *p;
+	int	    op;
+	int	    concat;
+	typval_T    var2;
+
 	// "." is only string concatenation when scriptversion is 1
-	op = **arg;
-	concat = op == '.'
-			&& (*(*arg + 1) == '.' || current_sctx.sc_version < 2);
+	p = eval_next_non_blank(*arg, evalarg, &getnext);
+	op = *p;
+	concat = op == '.' && (*(p + 1) == '.' || current_sctx.sc_version < 2);
 	if (op != '+' && op != '-' && !concat)
 	    break;
+	if (getnext)
+	    *arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
 
 	if ((op != '+' || (rettv->v_type != VAR_LIST
 						 && rettv->v_type != VAR_BLOB))
@@ -2240,7 +2321,7 @@ eval5(char_u **arg, typval_T *rettv, int
 	    // we know that the first operand needs to be a string or number
 	    // without evaluating the 2nd operand.  So check before to avoid
 	    // side effects after an error.
-	    if ((flags & EVAL_EVALUATE) && tv_get_string_chk(rettv) == NULL)
+	    if (evaluate && tv_get_string_chk(rettv) == NULL)
 	    {
 		clear_tv(rettv);
 		return FAIL;
@@ -2253,21 +2334,23 @@ eval5(char_u **arg, typval_T *rettv, int
 	if (op == '.' && *(*arg + 1) == '.')  // .. string concatenation
 	    ++*arg;
 	*arg = skipwhite(*arg + 1);
-	if (eval6(arg, &var2, flags, op == '.') == FAIL)
+	if (eval6(arg, &var2, evalarg, op == '.') == FAIL)
 	{
 	    clear_tv(rettv);
 	    return FAIL;
 	}
 
-	if (flags & EVAL_EVALUATE)
+	if (evaluate)
 	{
 	    /*
 	     * Compute the result.
 	     */
 	    if (op == '.')
 	    {
-		s1 = tv_get_string_buf(rettv, buf1);	// already checked
-		s2 = tv_get_string_buf_chk(&var2, buf2);
+		char_u	buf1[NUMBUFLEN], buf2[NUMBUFLEN];
+		char_u	*s1 = tv_get_string_buf(rettv, buf1);
+		char_u	*s2 = tv_get_string_buf_chk(&var2, buf2);
+
 		if (s2 == NULL)		// type error ?
 		{
 		    clear_tv(rettv);
@@ -2290,9 +2373,11 @@ eval5(char_u **arg, typval_T *rettv, int
 	    }
 	    else
 	    {
-		int	    error = FALSE;
-
+		int		error = FALSE;
+		varnumber_T	n1, n2;
 #ifdef FEAT_FLOAT
+		float_T	    f1 = 0, f2 = 0;
+
 		if (rettv->v_type == VAR_FLOAT)
 		{
 		    f1 = rettv->vval.v_float;
@@ -2381,7 +2466,7 @@ eval5(char_u **arg, typval_T *rettv, int
 eval6(
     char_u	**arg,
     typval_T	*rettv,
-    int		flags,
+    evalarg_T	*evalarg,
     int		want_string)  // after "." operator
 {
     typval_T	var2;
@@ -2396,7 +2481,7 @@ eval6(
     /*
      * Get the first variable.
      */
-    if (eval7(arg, rettv, flags, want_string) == FAIL)
+    if (eval7(arg, rettv, evalarg, want_string) == FAIL)
 	return FAIL;
 
     /*
@@ -2404,11 +2489,17 @@ eval6(
      */
     for (;;)
     {
-	op = **arg;
+	int	evaluate = evalarg == NULL ? 0
+				       : (evalarg->eval_flags & EVAL_EVALUATE);
+	int	getnext;
+
+	op = *eval_next_non_blank(*arg, evalarg, &getnext);
 	if (op != '*' && op != '/' && op != '%')
 	    break;
-
-	if (flags & EVAL_EVALUATE)
+	if (getnext)
+	    *arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
+
+	if (evaluate)
 	{
 #ifdef FEAT_FLOAT
 	    if (rettv->v_type == VAR_FLOAT)
@@ -2431,10 +2522,10 @@ eval6(
 	 * Get the second variable.
 	 */
 	*arg = skipwhite(*arg + 1);
-	if (eval7(arg, &var2, flags, FALSE) == FAIL)
+	if (eval7(arg, &var2, evalarg, FALSE) == FAIL)
 	    return FAIL;
 
-	if (flags & EVAL_EVALUATE)
+	if (evaluate)
 	{
 #ifdef FEAT_FLOAT
 	    if (var2.v_type == VAR_FLOAT)
@@ -2551,10 +2642,12 @@ eval6(
 eval7(
     char_u	**arg,
     typval_T	*rettv,
-    int		flags,
+    evalarg_T	*evalarg,
     int		want_string)	// after "." operator
 {
-    int		evaluate = flags & EVAL_EVALUATE;
+    int		flags = evalarg == NULL ? 0 : evalarg->eval_flags;
+    int		evaluate = evalarg != NULL
+				      && (evalarg->eval_flags & EVAL_EVALUATE);
     int		len;
     char_u	*s;
     char_u	*start_leader, *end_leader;
@@ -2672,15 +2765,17 @@ eval7(
     /*
      * nested expression: (expression).
      */
-    case '(':	*arg = skipwhite(*arg + 1);
-		ret = eval1(arg, rettv, flags);	// recursive!
-		if (**arg == ')')
-		    ++*arg;
-		else if (ret == OK)
-		{
-		    emsg(_(e_missing_close));
-		    clear_tv(rettv);
-		    ret = FAIL;
+    case '(':	{
+		    *arg = skipwhite(*arg + 1);
+		    ret = eval1(arg, rettv, evalarg);	// recursive!
+		    if (**arg == ')')
+			++*arg;
+		    else if (ret == OK)
+		    {
+			emsg(_(e_missing_close));
+			clear_tv(rettv);
+			ret = FAIL;
+		    }
 		}
 		break;
 
@@ -3030,6 +3125,11 @@ eval_index(
     }
     else
     {
+	evalarg_T	evalarg;
+
+	CLEAR_FIELD(evalarg);
+	evalarg.eval_flags = flags;
+
 	/*
 	 * something[idx]
 	 *
@@ -3038,7 +3138,7 @@ eval_index(
 	*arg = skipwhite(*arg + 1);
 	if (**arg == ':')
 	    empty1 = TRUE;
-	else if (eval1(arg, &var1, flags) == FAIL)	// recursive!
+	else if (eval1(arg, &var1, &evalarg) == FAIL)	// recursive!
 	    return FAIL;
 	else if (evaluate && tv_get_string_chk(&var1) == NULL)
 	{
@@ -3056,7 +3156,7 @@ eval_index(
 	    *arg = skipwhite(*arg + 1);
 	    if (**arg == ']')
 		empty2 = TRUE;
-	    else if (eval1(arg, &var2, flags) == FAIL)	// recursive!
+	    else if (eval1(arg, &var2, &evalarg) == FAIL)	// recursive!
 	    {
 		if (!empty1)
 		    clear_tv(&var1);
@@ -4947,6 +5047,10 @@ ex_echo(exarg_T *eap)
     int		atstart = TRUE;
     int		did_emsg_before = did_emsg;
     int		called_emsg_before = called_emsg;
+    evalarg_T	evalarg;
+
+    CLEAR_FIELD(evalarg);
+    evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
 
     if (eap->skip)
 	++emsg_skip;
@@ -4957,7 +5061,7 @@ ex_echo(exarg_T *eap)
 	need_clr_eos = needclr;
 
 	p = arg;
-	if (eval1(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE) == FAIL)
+	if (eval1(&arg, &rettv, &evalarg) == FAIL)
 	{
 	    /*
 	     * Report the invalid expression unless the expression evaluation