diff src/vim9execute.c @ 23982:9fcd71d0db89 v8.2.2533

patch 8.2.2533: Vim9: cannot use a range with :unlet Commit: https://github.com/vim/vim/commit/5b5ae29bd3d7b832b6f15320430f7f191e0abd1f Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 20 17:04:02 2021 +0100 patch 8.2.2533: Vim9: cannot use a range with :unlet Problem: Vim9: cannot use a range with :unlet. Solution: Implement ISN_UNLETRANGE.
author Bram Moolenaar <Bram@vim.org>
date Sat, 20 Feb 2021 17:15:03 +0100
parents 03819ebd3e6d
children 3daeb2060f25
line wrap: on
line diff
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -879,6 +879,21 @@ error_if_locked(int lock, char *error)
 }
 
 /*
+ * Give an error if "tv" is not a number and return FAIL.
+ */
+    static int
+check_for_number(typval_T *tv)
+{
+    if (tv->v_type != VAR_NUMBER)
+    {
+	semsg(_(e_expected_str_but_got_str),
+		vartype_name(VAR_NUMBER), vartype_name(tv->v_type));
+	return FAIL;
+    }
+    return OK;
+}
+
+/*
  * Store "tv" in variable "name".
  * This is for s: and g: variables.
  */
@@ -2178,12 +2193,9 @@ call_def_function(
 		    else if (tv_dest->v_type == VAR_LIST)
 		    {
 			// unlet a List item, index must be a number
-			if (tv_idx->v_type != VAR_NUMBER)
+			SOURCING_LNUM = iptr->isn_lnum;
+			if (check_for_number(tv_idx) == FAIL)
 			{
-			    SOURCING_LNUM = iptr->isn_lnum;
-			    semsg(_(e_expected_str_but_got_str),
-					vartype_name(VAR_NUMBER),
-					vartype_name(tv_idx->v_type));
 			    status = FAIL;
 			}
 			else
@@ -2219,6 +2231,58 @@ call_def_function(
 		}
 		break;
 
+	    // unlet range of items in list variable
+	    case ISN_UNLETRANGE:
+		{
+		    // Stack contains:
+		    // -3 index1
+		    // -2 index2
+		    // -1 dict or list
+		    typval_T	*tv_idx1 = STACK_TV_BOT(-3);
+		    typval_T	*tv_idx2 = STACK_TV_BOT(-2);
+		    typval_T	*tv_dest = STACK_TV_BOT(-1);
+		    int		status = OK;
+
+		    if (tv_dest->v_type == VAR_LIST)
+		    {
+			// indexes must be a number
+			SOURCING_LNUM = iptr->isn_lnum;
+			if (check_for_number(tv_idx1) == FAIL
+				|| check_for_number(tv_idx2) == FAIL)
+			{
+			    status = FAIL;
+			}
+			else
+			{
+			    list_T	*l = tv_dest->vval.v_list;
+			    long	n1 = (long)tv_idx1->vval.v_number;
+			    long	n2 = (long)tv_idx2->vval.v_number;
+			    listitem_T	*li;
+
+			    li = list_find_index(l, &n1);
+			    if (li == NULL
+				     || list_unlet_range(l, li, NULL, n1,
+							    TRUE, n2) == FAIL)
+				status = FAIL;
+			}
+		    }
+		    else
+		    {
+			status = FAIL;
+			SOURCING_LNUM = iptr->isn_lnum;
+			semsg(_(e_cannot_index_str),
+						vartype_name(tv_dest->v_type));
+		    }
+
+		    clear_tv(tv_idx1);
+		    clear_tv(tv_idx2);
+		    clear_tv(tv_dest);
+		    ectx.ec_stack.ga_len -= 3;
+		    if (status == FAIL)
+			goto on_error;
+		}
+		break;
+
 	    // push constant
 	    case ISN_PUSHNR:
 	    case ISN_PUSHBOOL:
@@ -4151,6 +4215,9 @@ ex_disassemble(exarg_T *eap)
 	    case ISN_UNLETINDEX:
 		smsg("%4d UNLETINDEX", current);
 		break;
+	    case ISN_UNLETRANGE:
+		smsg("%4d UNLETRANGE", current);
+		break;
 	    case ISN_LOCKCONST:
 		smsg("%4d LOCKCONST", current);
 		break;