0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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)
This commit is contained in:
Bram Moolenaar
2020-11-23 08:31:18 +01:00
parent 6abdcf8285
commit 792f786aad
8 changed files with 269 additions and 35 deletions

View File

@@ -2877,11 +2877,84 @@ call_def_function(
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 @@ ex_disassemble(exarg_T *eap)
}
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);