changeset 32130:ec0d5bd9083c v9.0.1396

patch 9.0.1396: sort(list, 'N') does not work in Vim9 script context Commit: https://github.com/vim/vim/commit/be19d78c3d44221cbc38fbb5bac19302345c1def Author: Bram Moolenaar <Bram@vim.org> Date: Thu Mar 9 22:06:49 2023 +0000 patch 9.0.1396: sort(list, 'N') does not work in Vim9 script context Problem: sort(list, 'N') does not work in Vim9 script context. Solution: Convert string to number without giving an error. (closes https://github.com/vim/vim/issues/12061)
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 Mar 2023 23:15:04 +0100
parents 3de9b899d584
children 8cfe64ee89ba
files runtime/doc/builtin.txt src/list.c src/proto/typval.pro src/testdir/test_sort.vim src/typval.c src/version.c
diffstat 6 files changed, 31 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -8641,8 +8641,9 @@ sort({list} [, {how} [, {dict}]])			*sor
 
 		When {how} is given and it is 'n' then all items will be
 		sorted numerical (Implementation detail: this uses the
-		strtod() function to parse numbers, Strings, Lists, Dicts and
-		Funcrefs will be considered as being 0).
+		strtod() function to parse numbers.  Strings, Lists, Dicts and
+		Funcrefs will be considered as being 0).  Note that this won't
+		sort a list of strings with numbers!
 
 		When {how} is given and it is 'N' then all items will be
 		sorted numerical. This is like 'n' but a string containing
--- a/src/list.c
+++ b/src/list.c
@@ -1910,8 +1910,8 @@ item_compare(const void *s1, const void 
 
     if (sortinfo->item_compare_numbers)
     {
-	varnumber_T	v1 = tv_get_number(tv1);
-	varnumber_T	v2 = tv_get_number(tv2);
+	varnumber_T	v1 = tv_to_number(tv1);
+	varnumber_T	v2 = tv_to_number(tv2);
 
 	return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
     }
@@ -2831,7 +2831,7 @@ extend(typval_T *argvars, typval_T *rett
     }
     else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
     {
-	// Check that extend() does not change the type of the list if it was
+	// Check that extend() does not change the type of the dict if it was
 	// declared.
 	if (!is_new && in_vim9script() && argvars[0].vval.v_dict != NULL)
 	    type = argvars[0].vval.v_dict->dv_type;
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -5,6 +5,7 @@ void free_tv(typval_T *varp);
 void clear_tv(typval_T *varp);
 void init_tv(typval_T *varp);
 varnumber_T tv_get_number(typval_T *varp);
+varnumber_T tv_to_number(typval_T *varp);
 varnumber_T tv_get_number_chk(typval_T *varp, int *denote);
 varnumber_T tv_get_bool(typval_T *varp);
 varnumber_T tv_get_bool_chk(typval_T *varp, int *denote);
--- a/src/testdir/test_sort.vim
+++ b/src/testdir/test_sort.vim
@@ -58,6 +58,7 @@ endfunc
 func Test_sort_numbers()
   call assert_equal([3, 13, 28], sort([13, 28, 3], 'N'))
   call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N'))
+  vim9cmd call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N'))
   call assert_equal([3997, 4996], sort([4996, 3997], 'Compare1'))
 endfunc
 
--- a/src/typval.c
+++ b/src/typval.c
@@ -188,7 +188,11 @@ init_tv(typval_T *varp)
 }
 
     static varnumber_T
-tv_get_bool_or_number_chk(typval_T *varp, int *denote, int want_bool)
+tv_get_bool_or_number_chk(
+	typval_T    *varp,
+	int	    *denote,
+	int	    want_bool,
+	int	    vim9_string_error) // in Vim9 using a string is an error
 {
     varnumber_T	n = 0L;
 
@@ -210,7 +214,7 @@ tv_get_bool_or_number_chk(typval_T *varp
 	    emsg(_(e_using_funcref_as_number));
 	    break;
 	case VAR_STRING:
-	    if (in_vim9script())
+	    if (vim9_string_error && in_vim9script())
 	    {
 		emsg_using_string_as(varp, !want_bool);
 		break;
@@ -287,10 +291,22 @@ tv_get_number(typval_T *varp)
     return tv_get_number_chk(varp, &error);	// return 0L on error
 }
 
+/*
+ * Like tv_get_numbe() but in Vim9 script do convert a number in a string to a
+ * number without giving an error.
+ */
+    varnumber_T
+tv_to_number(typval_T *varp)
+{
+    int		error = FALSE;
+
+    return tv_get_bool_or_number_chk(varp, &error, FALSE, FALSE);
+}
+
     varnumber_T
 tv_get_number_chk(typval_T *varp, int *denote)
 {
-    return tv_get_bool_or_number_chk(varp, denote, FALSE);
+    return tv_get_bool_or_number_chk(varp, denote, FALSE, TRUE);
 }
 
 /*
@@ -300,7 +316,7 @@ tv_get_number_chk(typval_T *varp, int *d
     varnumber_T
 tv_get_bool(typval_T *varp)
 {
-    return tv_get_bool_or_number_chk(varp, NULL, TRUE);
+    return tv_get_bool_or_number_chk(varp, NULL, TRUE, TRUE);
 }
 
 /*
@@ -310,7 +326,7 @@ tv_get_bool(typval_T *varp)
     varnumber_T
 tv_get_bool_chk(typval_T *varp, int *denote)
 {
-    return tv_get_bool_or_number_chk(varp, denote, TRUE);
+    return tv_get_bool_or_number_chk(varp, denote, TRUE, TRUE);
 }
 
     static float_T
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1396,
+/**/
     1395,
 /**/
     1394,