diff src/evalvars.c @ 28560:060fc3b69697 v8.2.4804

patch 8.2.4804: expression in heredoc doesn't work for compiled function Commit: https://github.com/vim/vim/commit/1fc6ea9bf3548b578676331f5eac1f7e0611c268 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Apr 21 23:30:15 2022 +0100 patch 8.2.4804: expression in heredoc doesn't work for compiled function Problem: Expression in heredoc doesn't work for compiled function. Solution: Implement compiling the heredoc expressions. (Yegappan Lakshmanan, closes #10232)
author Bram Moolenaar <Bram@vim.org>
date Fri, 22 Apr 2022 00:45:04 +0200
parents 1a2643893aa4
children 7a39c20a42fa
line wrap: on
line diff
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -673,16 +673,21 @@ eval_all_expr_in_str(char_u *str)
  *
  * The {marker} is a string. If the optional 'trim' word is supplied before the
  * marker, then the leading indentation before the lines (matching the
- * indentation in the 'cmd' line) is stripped.
+ * indentation in the "cmd" line) is stripped.
  *
  * When getting lines for an embedded script (e.g. python, lua, perl, ruby,
- * tcl, mzscheme), script_get is set to TRUE. In this case, if the marker is
+ * tcl, mzscheme), "script_get" is set to TRUE. In this case, if the marker is
  * missing, then '.' is accepted as a marker.
  *
+ * When compiling a heredoc assignment to a variable in a Vim9 def function,
+ * "vim9compile" is set to TRUE. In this case, instead of generating a list of
+ * string values from the heredoc, vim9 instructions are generated.  On success
+ * the returned list will be empty.
+ *
  * Returns a List with {lines} or NULL on failure.
  */
     list_T *
-heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
+heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile)
 {
     char_u	*theline = NULL;
     char_u	*marker;
@@ -696,6 +701,8 @@ heredoc_get(exarg_T *eap, char_u *cmd, i
     int		comment_char = in_vim9script() ? '#' : '"';
     int		evalstr = FALSE;
     int		eval_failed = FALSE;
+    cctx_T	*cctx = vim9compile ? eap->cookie : NULL;
+    int		count = 0;
 
     if (eap->getline == NULL)
     {
@@ -816,25 +823,41 @@ heredoc_get(exarg_T *eap, char_u *cmd, i
 		    break;
 
 	str = theline + ti;
-	if (evalstr)
+	if (vim9compile)
 	{
-	    str = eval_all_expr_in_str(str);
-	    if (str == NULL)
+	    if (compile_heredoc_string(str, evalstr, cctx) == FAIL)
+	    {
+		vim_free(theline);
+		vim_free(text_indent);
+		return FAIL;
+	    }
+	    count++;
+	}
+	else
+	{
+	    if (evalstr)
 	    {
-		// expression evaluation failed
-		eval_failed = TRUE;
-		continue;
+		str = eval_all_expr_in_str(str);
+		if (str == NULL)
+		{
+		    // expression evaluation failed
+		    eval_failed = TRUE;
+		    continue;
+		}
+		vim_free(theline);
+		theline = str;
 	    }
-	    vim_free(theline);
-	    theline = str;
+
+	    if (list_append_string(l, str, -1) == FAIL)
+		break;
 	}
-
-	if (list_append_string(l, str, -1) == FAIL)
-	    break;
     }
     vim_free(theline);
     vim_free(text_indent);
 
+    if (vim9compile && cctx->ctx_skip != SKIP_YES && !eval_failed)
+	generate_NEWLIST(cctx, count, FALSE);
+
     if (eval_failed)
     {
 	// expression evaluation in the heredoc failed
@@ -986,7 +1009,7 @@ ex_let(exarg_T *eap)
 	long	cur_lnum = SOURCING_LNUM;
 
 	// HERE document
-	l = heredoc_get(eap, expr + 3, FALSE);
+	l = heredoc_get(eap, expr + 3, FALSE, FALSE);
 	if (l != NULL)
 	{
 	    rettv_list_set(&rettv, l);