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:
@@ -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);
|
||||
|
Reference in New Issue
Block a user