patch 8.2.2034: Vim9: list unpack in for statement not compiled yet
Problem: Vim9: list unpack in for statement not compiled yet.
Solution: Compile list unpack. (closes #7345)
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 8b614bf..323f292 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2877,11 +2877,84 @@
restore_cmdmod = FALSE;
break;
+ case ISN_UNPACK:
+ {
+ int count = iptr->isn_arg.unpack.unp_count;
+ int semicolon = iptr->isn_arg.unpack.unp_semicolon;
+ list_T *l;
+ listitem_T *li;
+ int i;
+
+ // Check there is a valid list to unpack.
+ tv = STACK_TV_BOT(-1);
+ if (tv->v_type != VAR_LIST)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(_(e_for_argument_must_be_sequence_of_lists));
+ goto on_error;
+ }
+ l = tv->vval.v_list;
+ if (l == NULL
+ || l->lv_len < (semicolon ? count - 1 : count))
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(_(e_list_value_does_not_have_enough_items));
+ goto on_error;
+ }
+ else if (!semicolon && l->lv_len > count)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(_(e_list_value_has_more_items_than_targets));
+ goto on_error;
+ }
+
+ CHECK_LIST_MATERIALIZE(l);
+ if (GA_GROW(&ectx.ec_stack, count - 1) == FAIL)
+ goto failed;
+ ectx.ec_stack.ga_len += count - 1;
+
+ // Variable after semicolon gets a list with the remaining
+ // items.
+ if (semicolon)
+ {
+ list_T *rem_list =
+ list_alloc_with_items(l->lv_len - count + 1);
+
+ if (rem_list == NULL)
+ goto failed;
+ tv = STACK_TV_BOT(-count);
+ tv->vval.v_list = rem_list;
+ ++rem_list->lv_refcount;
+ tv->v_lock = 0;
+ li = l->lv_first;
+ for (i = 0; i < count - 1; ++i)
+ li = li->li_next;
+ for (i = 0; li != NULL; ++i)
+ {
+ list_set_item(rem_list, i, &li->li_tv);
+ li = li->li_next;
+ }
+ --count;
+ }
+
+ // Produce the values in reverse order, first item last.
+ li = l->lv_first;
+ for (i = 0; i < count; ++i)
+ {
+ tv = STACK_TV_BOT(-i - 1);
+ copy_tv(&li->li_tv, tv);
+ li = li->li_next;
+ }
+
+ list_unref(l);
+ }
+ break;
+
case ISN_SHUFFLE:
{
- typval_T tmp_tv;
- int item = iptr->isn_arg.shuffle.shfl_item;
- int up = iptr->isn_arg.shuffle.shfl_up;
+ typval_T tmp_tv;
+ int item = iptr->isn_arg.shuffle.shfl_item;
+ int up = iptr->isn_arg.shuffle.shfl_up;
tmp_tv = *STACK_TV_BOT(-item);
for ( ; up > 0 && item > 1; --up)
@@ -3606,6 +3679,10 @@
}
case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break;
+ case ISN_UNPACK: smsg("%4d UNPACK %d%s", current,
+ iptr->isn_arg.unpack.unp_count,
+ iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
+ break;
case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
iptr->isn_arg.shuffle.shfl_item,
iptr->isn_arg.shuffle.shfl_up);