diff src/vim9compile.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 bee8c78c0c6a
children 3daeb2060f25
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5865,6 +5865,7 @@ compile_assign_unlet(
     vartype_T	dest_type;
     size_t	varlen = lhs->lhs_varlen;
     garray_T    *stack = &cctx->ctx_type_stack;
+    int		range = FALSE;
 
     // Compile the "idx" in "var[idx]" or "key" in "var.key".
     p = var_start + varlen;
@@ -5872,6 +5873,27 @@ compile_assign_unlet(
     {
 	p = skipwhite(p + 1);
 	r = compile_expr0(&p, cctx);
+
+	if (r == OK && *skipwhite(p) == ':')
+	{
+	    // unlet var[idx : idx]
+	    if (is_assign)
+	    {
+		semsg(_(e_cannot_use_range_with_assignment_str), p);
+		return FAIL;
+	    }
+	    range = TRUE;
+	    p = skipwhite(p);
+	    if (!IS_WHITE_OR_NUL(p[-1]) || !IS_WHITE_OR_NUL(p[1]))
+	    {
+		semsg(_(e_white_space_required_before_and_after_str_at_str),
+								      ":", p);
+		return FAIL;
+	    }
+	    p = skipwhite(p + 1);
+	    r = compile_expr0(&p, cctx);
+	}
+
 	if (r == OK && *skipwhite(p) != ']')
 	{
 	    // this should not happen
@@ -5897,17 +5919,29 @@ compile_assign_unlet(
     else
     {
 	dest_type = lhs->lhs_type->tt_type;
+	if (dest_type == VAR_DICT && range)
+	{
+	    emsg(e_cannot_use_range_with_dictionary);
+	    return FAIL;
+	}
 	if (dest_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL)
 	    return FAIL;
-	if (dest_type == VAR_LIST
-		&& need_type(((type_T **)stack->ga_data)[stack->ga_len - 1],
+	if (dest_type == VAR_LIST)
+	{
+	    if (range
+		  && need_type(((type_T **)stack->ga_data)[stack->ga_len - 2],
 				 &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
-	    return FAIL;
+		return FAIL;
+	    if (need_type(((type_T **)stack->ga_data)[stack->ga_len - 1],
+				 &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
+		return FAIL;
+	}
     }
 
     // Load the dict or list.  On the stack we then have:
     // - value (for assignment, not for :unlet)
     // - index
+    // - for [a : b] second index
     // - variable
     if (lhs->lhs_dest == dest_expr)
     {
@@ -5946,6 +5980,11 @@ compile_assign_unlet(
 		return FAIL;
 	    isn->isn_arg.vartype = dest_type;
 	}
+	else if (range)
+	{
+	    if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
+		return FAIL;
+	}
 	else
 	{
 	    if (generate_instr_drop(cctx, ISN_UNLETINDEX, 2) == NULL)
@@ -8907,6 +8946,7 @@ delete_instr(isn_T *isn)
 	case ISN_TRY:
 	case ISN_TRYCONT:
 	case ISN_UNLETINDEX:
+	case ISN_UNLETRANGE:
 	case ISN_UNPACK:
 	    // nothing allocated
 	    break;