patch 8.2.2356: Vim9: ":put =expr" does not handle a list properly

Problem:    Vim9: ":put =expr" does not handle a list properly.
Solution:   Use the same logic as eval_to_string_eap(). (closes #7684)
diff --git a/src/eval.c b/src/eval.c
index 84f6c2b..13ee49a 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -467,6 +467,45 @@
 }
 
 /*
+ * Convert "tv" to a string.
+ * When "convert" is TRUE convert a List into a sequence of lines and convert
+ * a Float to a String.
+ * Returns an allocated string (NULL when out of memory).
+ */
+    char_u *
+typval2string(typval_T *tv, int convert)
+{
+    garray_T	ga;
+    char_u	*retval;
+#ifdef FEAT_FLOAT
+    char_u	numbuf[NUMBUFLEN];
+#endif
+
+    if (convert && tv->v_type == VAR_LIST)
+    {
+	ga_init2(&ga, (int)sizeof(char), 80);
+	if (tv->vval.v_list != NULL)
+	{
+	    list_join(&ga, tv->vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
+	    if (tv->vval.v_list->lv_len > 0)
+		ga_append(&ga, NL);
+	}
+	ga_append(&ga, NUL);
+	retval = (char_u *)ga.ga_data;
+    }
+#ifdef FEAT_FLOAT
+    else if (convert && tv->v_type == VAR_FLOAT)
+    {
+	vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
+	retval = vim_strsave(numbuf);
+    }
+#endif
+    else
+	retval = vim_strsave(tv_get_string(tv));
+    return retval;
+}
+
+/*
  * Top level evaluation function, returning a string.  Does not handle line
  * breaks.
  * When "convert" is TRUE convert a List into a sequence of lines and convert
@@ -481,10 +520,6 @@
 {
     typval_T	tv;
     char_u	*retval;
-    garray_T	ga;
-#ifdef FEAT_FLOAT
-    char_u	numbuf[NUMBUFLEN];
-#endif
     evalarg_T	evalarg;
 
     fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
@@ -492,27 +527,7 @@
 	retval = NULL;
     else
     {
-	if (convert && tv.v_type == VAR_LIST)
-	{
-	    ga_init2(&ga, (int)sizeof(char), 80);
-	    if (tv.vval.v_list != NULL)
-	    {
-		list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
-		if (tv.vval.v_list->lv_len > 0)
-		    ga_append(&ga, NL);
-	    }
-	    ga_append(&ga, NUL);
-	    retval = (char_u *)ga.ga_data;
-	}
-#ifdef FEAT_FLOAT
-	else if (convert && tv.v_type == VAR_FLOAT)
-	{
-	    vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
-	    retval = vim_strsave(numbuf);
-	}
-#endif
-	else
-	    retval = vim_strsave(tv_get_string(&tv));
+	retval = typval2string(&tv, convert);
 	clear_tv(&tv);
     }
     clear_evalarg(&evalarg, NULL);
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index f611a0e..fbae530 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -11,6 +11,7 @@
 char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
 int skip_expr(char_u **pp, evalarg_T *evalarg);
 int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg);
+char_u *typval2string(typval_T *tv, int convert);
 char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap);
 char_u *eval_to_string(char_u *arg, int convert);
 char_u *eval_to_string_safe(char_u *arg, int use_sandbox);
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 5d66966..098cded 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -736,6 +736,9 @@
   assert_equal('above', getline(3))
   assert_equal('below', getline(4))
 
+  :2put =['a', 'b', 'c']
+  assert_equal(['ppp', 'a', 'b', 'c', 'above'], getline(2, 6))
+
   # compute range at runtime
   setline(1, range(1, 8))
   @a = 'aaa'
diff --git a/src/version.c b/src/version.c
index 8285df7..9d217e2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2356,
+/**/
     2355,
 /**/
     2354,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 9c9c273..87a9218 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -3357,7 +3357,7 @@
 			    expr = tv->vval.v_string;
 			else
 			{
-			    expr = typval_tostring(tv);  // allocates value
+			    expr = typval2string(tv, TRUE); // allocates value
 			    clear_tv(tv);
 			}
 			--ectx.ec_stack.ga_len;