forked from aniani/vim
patch 8.2.3332: Vim9: cannot assign to range in list
Problem: Vim9: cannot assign to range in list. Solution: Implement overwriting a list range.
This commit is contained in:
98
src/eval.c
98
src/eval.c
@@ -45,7 +45,6 @@ typedef struct
|
|||||||
int fi_byte_idx; // byte index in fi_string
|
int fi_byte_idx; // byte index in fi_string
|
||||||
} forinfo_T;
|
} forinfo_T;
|
||||||
|
|
||||||
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
|
|
||||||
static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
@@ -827,7 +826,6 @@ get_lval(
|
|||||||
typval_T var1;
|
typval_T var1;
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
int empty1 = FALSE;
|
int empty1 = FALSE;
|
||||||
listitem_T *ni;
|
|
||||||
char_u *key = NULL;
|
char_u *key = NULL;
|
||||||
int len;
|
int len;
|
||||||
hashtab_T *ht = NULL;
|
hashtab_T *ht = NULL;
|
||||||
@@ -1210,23 +1208,11 @@ get_lval(
|
|||||||
|
|
||||||
lp->ll_dict = NULL;
|
lp->ll_dict = NULL;
|
||||||
lp->ll_list = lp->ll_tv->vval.v_list;
|
lp->ll_list = lp->ll_tv->vval.v_list;
|
||||||
lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
|
lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1, quiet);
|
||||||
if (lp->ll_li == NULL)
|
if (lp->ll_li == NULL)
|
||||||
{
|
{
|
||||||
// Vim9: Allow for adding an item at the end.
|
clear_tv(&var2);
|
||||||
if (in_vim9script() && lp->ll_n1 == lp->ll_list->lv_len
|
return NULL;
|
||||||
&& lp->ll_list->lv_lock == 0)
|
|
||||||
{
|
|
||||||
list_append_number(lp->ll_list, 0);
|
|
||||||
lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
|
|
||||||
}
|
|
||||||
if (lp->ll_li == NULL)
|
|
||||||
{
|
|
||||||
clear_tv(&var2);
|
|
||||||
if (!quiet)
|
|
||||||
semsg(_(e_listidx), lp->ll_n1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lp->ll_valtype != NULL)
|
if (lp->ll_valtype != NULL)
|
||||||
@@ -1244,27 +1230,10 @@ get_lval(
|
|||||||
lp->ll_n2 = (long)tv_get_number(&var2);
|
lp->ll_n2 = (long)tv_get_number(&var2);
|
||||||
// is number or string
|
// is number or string
|
||||||
clear_tv(&var2);
|
clear_tv(&var2);
|
||||||
if (lp->ll_n2 < 0)
|
if (check_range_index_two(lp->ll_list,
|
||||||
{
|
&lp->ll_n1, lp->ll_li,
|
||||||
ni = list_find(lp->ll_list, lp->ll_n2);
|
&lp->ll_n2, quiet) == FAIL)
|
||||||
if (ni == NULL)
|
|
||||||
{
|
|
||||||
if (!quiet)
|
|
||||||
semsg(_(e_listidx), lp->ll_n2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that lp->ll_n2 isn't before lp->ll_n1.
|
|
||||||
if (lp->ll_n1 < 0)
|
|
||||||
lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
|
|
||||||
if (lp->ll_n2 < lp->ll_n1)
|
|
||||||
{
|
|
||||||
if (!quiet)
|
|
||||||
semsg(_(e_listidx), lp->ll_n2);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->ll_tv = &lp->ll_li->li_tv;
|
lp->ll_tv = &lp->ll_li->li_tv;
|
||||||
@@ -1303,7 +1272,6 @@ set_var_lval(
|
|||||||
int var_idx) // index for "let [a, b] = list"
|
int var_idx) // index for "let [a, b] = list"
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
listitem_T *ri;
|
|
||||||
dictitem_T *di;
|
dictitem_T *di;
|
||||||
|
|
||||||
if (lp->ll_tv == NULL)
|
if (lp->ll_tv == NULL)
|
||||||
@@ -1383,9 +1351,6 @@ set_var_lval(
|
|||||||
;
|
;
|
||||||
else if (lp->ll_range)
|
else if (lp->ll_range)
|
||||||
{
|
{
|
||||||
listitem_T *ll_li = lp->ll_li;
|
|
||||||
int ll_n1 = lp->ll_n1;
|
|
||||||
|
|
||||||
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
|
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
|
||||||
&& (flags & ASSIGN_FOR_LOOP) == 0)
|
&& (flags & ASSIGN_FOR_LOOP) == 0)
|
||||||
{
|
{
|
||||||
@@ -1393,53 +1358,8 @@ set_var_lval(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
(void)list_assign_range(lp->ll_list, rettv->vval.v_list,
|
||||||
* Check whether any of the list items is locked
|
lp->ll_n1, lp->ll_n2, lp->ll_empty2, op, lp->ll_name);
|
||||||
*/
|
|
||||||
for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; )
|
|
||||||
{
|
|
||||||
if (value_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
|
|
||||||
return;
|
|
||||||
ri = ri->li_next;
|
|
||||||
if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1))
|
|
||||||
break;
|
|
||||||
ll_li = ll_li->li_next;
|
|
||||||
++ll_n1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assign the List values to the list items.
|
|
||||||
*/
|
|
||||||
for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
|
|
||||||
{
|
|
||||||
if (op != NULL && *op != '=')
|
|
||||||
tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear_tv(&lp->ll_li->li_tv);
|
|
||||||
copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
|
|
||||||
}
|
|
||||||
ri = ri->li_next;
|
|
||||||
if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
|
|
||||||
break;
|
|
||||||
if (lp->ll_li->li_next == NULL)
|
|
||||||
{
|
|
||||||
// Need to add an empty item.
|
|
||||||
if (list_append_number(lp->ll_list, 0) == FAIL)
|
|
||||||
{
|
|
||||||
ri = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lp->ll_li = lp->ll_li->li_next;
|
|
||||||
++lp->ll_n1;
|
|
||||||
}
|
|
||||||
if (ri != NULL)
|
|
||||||
emsg(_(e_list_value_has_more_items_than_targets));
|
|
||||||
else if (lp->ll_empty2
|
|
||||||
? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
|
|
||||||
: lp->ll_n1 != lp->ll_n2)
|
|
||||||
emsg(_(e_list_value_does_not_have_enough_items));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1507,7 +1427,7 @@ set_var_lval(
|
|||||||
* and "tv1 .= tv2"
|
* and "tv1 .= tv2"
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||||
{
|
{
|
||||||
varnumber_T n;
|
varnumber_T n;
|
||||||
|
152
src/list.c
152
src/list.c
@@ -761,6 +761,158 @@ list_insert(list_T *l, listitem_T *ni, listitem_T *item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the list item in "l" with index "n1". "n1" is adjusted if needed.
|
||||||
|
* In Vim9, it is at the end of the list, add an item.
|
||||||
|
* Return NULL if there is no such item.
|
||||||
|
*/
|
||||||
|
listitem_T *
|
||||||
|
check_range_index_one(list_T *l, long *n1, int quiet)
|
||||||
|
{
|
||||||
|
listitem_T *li = list_find_index(l, n1);
|
||||||
|
|
||||||
|
if (li == NULL)
|
||||||
|
{
|
||||||
|
// Vim9: Allow for adding an item at the end.
|
||||||
|
if (in_vim9script() && *n1 == l->lv_len && l->lv_lock == 0)
|
||||||
|
{
|
||||||
|
list_append_number(l, 0);
|
||||||
|
li = list_find_index(l, n1);
|
||||||
|
}
|
||||||
|
if (li == NULL)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_listidx), *n1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that "n2" can be used as the second index in a range of list "l".
|
||||||
|
* If "n1" or "n2" is negative it is changed to the positive index.
|
||||||
|
* "li1" is the item for item "n1".
|
||||||
|
* Return OK or FAIL.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_range_index_two(
|
||||||
|
list_T *l,
|
||||||
|
long *n1,
|
||||||
|
listitem_T *li1,
|
||||||
|
long *n2,
|
||||||
|
int quiet)
|
||||||
|
{
|
||||||
|
if (*n2 < 0)
|
||||||
|
{
|
||||||
|
listitem_T *ni = list_find(l, *n2);
|
||||||
|
|
||||||
|
if (ni == NULL)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_listidx), *n2);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
*n2 = list_idx_of_item(l, ni);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that n2 isn't before n1.
|
||||||
|
if (*n1 < 0)
|
||||||
|
*n1 = list_idx_of_item(l, li1);
|
||||||
|
if (*n2 < *n1)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
semsg(_(e_listidx), *n2);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assign values from list "src" into a range of "dest".
|
||||||
|
* "idx1_arg" is the index of the first item in "dest" to be replaced.
|
||||||
|
* "idx2" is the index of last item to be replaced, but when "empty_idx2" is
|
||||||
|
* TRUE then replace all items after "idx1".
|
||||||
|
* "op" is the operator, normally "=" but can be "+=" and the like.
|
||||||
|
* "varname" is used for error messages.
|
||||||
|
* Returns OK or FAIL.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
list_assign_range(
|
||||||
|
list_T *dest,
|
||||||
|
list_T *src,
|
||||||
|
long idx1_arg,
|
||||||
|
long idx2,
|
||||||
|
int empty_idx2,
|
||||||
|
char_u *op,
|
||||||
|
char_u *varname)
|
||||||
|
{
|
||||||
|
listitem_T *src_li;
|
||||||
|
listitem_T *dest_li;
|
||||||
|
long idx1 = idx1_arg;
|
||||||
|
listitem_T *first_li = list_find_index(dest, &idx1);
|
||||||
|
long idx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether any of the list items is locked before making any changes.
|
||||||
|
*/
|
||||||
|
idx = idx1;
|
||||||
|
dest_li = first_li;
|
||||||
|
for (src_li = src->lv_first; src_li != NULL && dest_li != NULL; )
|
||||||
|
{
|
||||||
|
if (value_check_lock(dest_li->li_tv.v_lock, varname, FALSE))
|
||||||
|
return FAIL;
|
||||||
|
src_li = src_li->li_next;
|
||||||
|
if (src_li == NULL || (!empty_idx2 && idx2 == idx))
|
||||||
|
break;
|
||||||
|
dest_li = dest_li->li_next;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assign the List values to the list items.
|
||||||
|
*/
|
||||||
|
idx = idx1;
|
||||||
|
dest_li = first_li;
|
||||||
|
for (src_li = src->lv_first; src_li != NULL; )
|
||||||
|
{
|
||||||
|
if (op != NULL && *op != '=')
|
||||||
|
tv_op(&dest_li->li_tv, &src_li->li_tv, op);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clear_tv(&dest_li->li_tv);
|
||||||
|
copy_tv(&src_li->li_tv, &dest_li->li_tv);
|
||||||
|
}
|
||||||
|
src_li = src_li->li_next;
|
||||||
|
if (src_li == NULL || (!empty_idx2 && idx2 == idx))
|
||||||
|
break;
|
||||||
|
if (dest_li->li_next == NULL)
|
||||||
|
{
|
||||||
|
// Need to add an empty item.
|
||||||
|
if (list_append_number(dest, 0) == FAIL)
|
||||||
|
{
|
||||||
|
src_li = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dest_li = dest_li->li_next;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
if (src_li != NULL)
|
||||||
|
{
|
||||||
|
emsg(_(e_list_value_has_more_items_than_targets));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (empty_idx2
|
||||||
|
? (dest_li != NULL && dest_li->li_next != NULL)
|
||||||
|
: idx != idx2)
|
||||||
|
{
|
||||||
|
emsg(_(e_list_value_does_not_have_enough_items));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flatten "list" to depth "maxdepth".
|
* Flatten "list" to depth "maxdepth".
|
||||||
* It does nothing if "maxdepth" is 0.
|
* It does nothing if "maxdepth" is 0.
|
||||||
|
@@ -26,6 +26,7 @@ int eval_foldexpr(char_u *arg, int *cp);
|
|||||||
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
|
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
|
||||||
void clear_lval(lval_T *lp);
|
void clear_lval(lval_T *lp);
|
||||||
void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op, int var_idx);
|
void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op, int var_idx);
|
||||||
|
int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
|
||||||
void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, evalarg_T *evalarg);
|
void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, evalarg_T *evalarg);
|
||||||
void skip_for_lines(void *fi_void, evalarg_T *evalarg);
|
void skip_for_lines(void *fi_void, evalarg_T *evalarg);
|
||||||
int next_for_item(void *fi_void, char_u *arg);
|
int next_for_item(void *fi_void, char_u *arg);
|
||||||
|
@@ -30,6 +30,9 @@ int list_append_string(list_T *l, char_u *str, int len);
|
|||||||
int list_append_number(list_T *l, varnumber_T n);
|
int list_append_number(list_T *l, varnumber_T n);
|
||||||
int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
|
int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
|
||||||
void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
|
void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
|
||||||
|
listitem_T *check_range_index_one(list_T *l, long *n1, int quiet);
|
||||||
|
int check_range_index_two(list_T *l, long *n1, listitem_T *li1, long *n2, int quiet);
|
||||||
|
int list_assign_range(list_T *dest, list_T *src, long idx1_arg, long idx2, int empty_idx2, char_u *op, char_u *varname);
|
||||||
void f_flatten(typval_T *argvars, typval_T *rettv);
|
void f_flatten(typval_T *argvars, typval_T *rettv);
|
||||||
void f_flattennew(typval_T *argvars, typval_T *rettv);
|
void f_flattennew(typval_T *argvars, typval_T *rettv);
|
||||||
int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
|
int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
|
||||||
|
@@ -164,11 +164,14 @@ endfunc
|
|||||||
|
|
||||||
" test for range assign
|
" test for range assign
|
||||||
func Test_list_range_assign()
|
func Test_list_range_assign()
|
||||||
let l = [0]
|
let lines =<< trim END
|
||||||
let l[:] = [1, 2]
|
VAR l = [0]
|
||||||
call assert_equal([1, 2], l)
|
LET l[:] = [1, 2]
|
||||||
let l[-4:-1] = [5, 6]
|
call assert_equal([1, 2], l)
|
||||||
call assert_equal([5, 6], l)
|
LET l[-4 : -1] = [5, 6]
|
||||||
|
call assert_equal([5, 6], l)
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Success(lines)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test removing items in list
|
" Test removing items in list
|
||||||
|
@@ -1821,7 +1821,7 @@ def Test_unlet()
|
|||||||
CheckDefFailure([
|
CheckDefFailure([
|
||||||
'var ll = [1, 2]',
|
'var ll = [1, 2]',
|
||||||
'll[1 : 2] = 7',
|
'll[1 : 2] = 7',
|
||||||
], 'E1165:', 2)
|
], 'E1012: Type mismatch; expected list<number> but got number', 2)
|
||||||
CheckDefFailure([
|
CheckDefFailure([
|
||||||
'var dd = {a: 1}',
|
'var dd = {a: 1}',
|
||||||
'unlet dd["a" : "a"]',
|
'unlet dd["a" : "a"]',
|
||||||
|
@@ -755,6 +755,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
3332,
|
||||||
/**/
|
/**/
|
||||||
3331,
|
3331,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -6484,6 +6484,29 @@ compile_assign_lhs(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if "lhs" has a range index: "[expr : expr]".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
has_list_index(char_u *idx_start, cctx_T *cctx)
|
||||||
|
{
|
||||||
|
char_u *p = idx_start;
|
||||||
|
int save_skip;
|
||||||
|
|
||||||
|
if (*p != '[')
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
p = skipwhite(p + 1);
|
||||||
|
if (*p == ':')
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
save_skip = cctx->ctx_skip;
|
||||||
|
cctx->ctx_skip = SKIP_YES;
|
||||||
|
(void)compile_expr0(&p, cctx);
|
||||||
|
cctx->ctx_skip = save_skip;
|
||||||
|
return *skipwhite(p) == ':';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For an assignment with an index, compile the "idx" in "var[idx]" or "key" in
|
* For an assignment with an index, compile the "idx" in "var[idx]" or "key" in
|
||||||
* "var.key".
|
* "var.key".
|
||||||
@@ -6652,8 +6675,10 @@ compile_assign_unlet(
|
|||||||
|
|
||||||
if (compile_assign_index(var_start, lhs, &range, cctx) == FAIL)
|
if (compile_assign_index(var_start, lhs, &range, cctx) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (is_assign && range && lhs->lhs_type != &t_blob
|
if (is_assign && range
|
||||||
&& lhs->lhs_type != &t_any)
|
&& lhs->lhs_type->tt_type != VAR_LIST
|
||||||
|
&& lhs->lhs_type != &t_blob
|
||||||
|
&& lhs->lhs_type != &t_any)
|
||||||
{
|
{
|
||||||
semsg(_(e_cannot_use_range_with_assignment_str), var_start);
|
semsg(_(e_cannot_use_range_with_assignment_str), var_start);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -7029,7 +7054,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
SOURCING_LNUM = start_lnum;
|
SOURCING_LNUM = start_lnum;
|
||||||
where.wt_index = var_count > 0 ? var_idx + 1 : 0;
|
where.wt_index = var_count > 0 ? var_idx + 1 : 0;
|
||||||
where.wt_variable = var_count > 0;
|
where.wt_variable = var_count > 0;
|
||||||
if (lhs.lhs_has_index)
|
// If assigning to a list or dict member, use the
|
||||||
|
// member type. Not for "list[:] =".
|
||||||
|
if (lhs.lhs_has_index
|
||||||
|
&& !has_list_index(var_start + lhs.lhs_varlen,
|
||||||
|
cctx))
|
||||||
use_type = lhs.lhs_member_type;
|
use_type = lhs.lhs_member_type;
|
||||||
if (need_type_where(rhs_type, use_type, -1, where,
|
if (need_type_where(rhs_type, use_type, -1, where,
|
||||||
cctx, FALSE, is_const) == FAIL)
|
cctx, FALSE, is_const) == FAIL)
|
||||||
|
@@ -2503,14 +2503,53 @@ exec_instructions(ectx_T *ectx)
|
|||||||
// -4 value to be stored
|
// -4 value to be stored
|
||||||
// -3 first index or "none"
|
// -3 first index or "none"
|
||||||
// -2 second index or "none"
|
// -2 second index or "none"
|
||||||
// -1 destination blob
|
// -1 destination list or blob
|
||||||
tv = STACK_TV_BOT(-4);
|
tv = STACK_TV_BOT(-4);
|
||||||
if (tv_dest->v_type != VAR_BLOB)
|
if (tv_dest->v_type == VAR_LIST)
|
||||||
{
|
{
|
||||||
status = FAIL;
|
long n1;
|
||||||
emsg(_(e_blob_required));
|
long n2;
|
||||||
|
int error = FALSE;
|
||||||
|
|
||||||
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
|
n1 = (long)tv_get_number_chk(tv_idx1, &error);
|
||||||
|
if (error)
|
||||||
|
status = FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tv_idx2->v_type == VAR_SPECIAL
|
||||||
|
&& tv_idx2->vval.v_number == VVAL_NONE)
|
||||||
|
n2 = list_len(tv_dest->vval.v_list) - 1;
|
||||||
|
else
|
||||||
|
n2 = (long)tv_get_number_chk(tv_idx2, &error);
|
||||||
|
if (error)
|
||||||
|
status = FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listitem_T *li1 = check_range_index_one(
|
||||||
|
tv_dest->vval.v_list, &n1, FALSE);
|
||||||
|
|
||||||
|
if (li1 == NULL)
|
||||||
|
status = FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = check_range_index_two(
|
||||||
|
tv_dest->vval.v_list,
|
||||||
|
&n1, li1, &n2, FALSE);
|
||||||
|
if (status != FAIL)
|
||||||
|
status = list_assign_range(
|
||||||
|
tv_dest->vval.v_list,
|
||||||
|
tv->vval.v_list,
|
||||||
|
n1,
|
||||||
|
n2,
|
||||||
|
tv_idx2->v_type == VAR_SPECIAL,
|
||||||
|
(char_u *)"=",
|
||||||
|
(char_u *)"[unknown]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (tv_dest->v_type == VAR_BLOB)
|
||||||
{
|
{
|
||||||
varnumber_T n1;
|
varnumber_T n1;
|
||||||
varnumber_T n2;
|
varnumber_T n2;
|
||||||
@@ -2530,7 +2569,7 @@ exec_instructions(ectx_T *ectx)
|
|||||||
status = FAIL;
|
status = FAIL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long bloblen = blob_len(tv_dest->vval.v_blob);
|
long bloblen = blob_len(tv_dest->vval.v_blob);
|
||||||
|
|
||||||
if (check_blob_index(bloblen,
|
if (check_blob_index(bloblen,
|
||||||
n1, FALSE) == FAIL
|
n1, FALSE) == FAIL
|
||||||
@@ -2543,6 +2582,11 @@ exec_instructions(ectx_T *ectx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = FAIL;
|
||||||
|
emsg(_(e_blob_required));
|
||||||
|
}
|
||||||
|
|
||||||
clear_tv(tv_idx1);
|
clear_tv(tv_idx1);
|
||||||
clear_tv(tv_idx2);
|
clear_tv(tv_idx2);
|
||||||
@@ -5469,7 +5513,7 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
|||||||
case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
|
case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
|
||||||
case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
|
case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
|
||||||
case ISN_SLICE: smsg("%s%4d SLICE %lld",
|
case ISN_SLICE: smsg("%s%4d SLICE %lld",
|
||||||
pfx, current, iptr->isn_arg.number); break;
|
pfx, current, iptr->isn_arg.number); break;
|
||||||
case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
|
case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
|
||||||
iptr->isn_arg.getitem.gi_index,
|
iptr->isn_arg.getitem.gi_index,
|
||||||
iptr->isn_arg.getitem.gi_with_op ?
|
iptr->isn_arg.getitem.gi_with_op ?
|
||||||
@@ -5490,7 +5534,8 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
|||||||
type_name(ct->ct_type, &tofree),
|
type_name(ct->ct_type, &tofree),
|
||||||
(int)ct->ct_off);
|
(int)ct->ct_off);
|
||||||
else
|
else
|
||||||
smsg("%s%4d CHECKTYPE %s stack[%d] arg %d", pfx, current,
|
smsg("%s%4d CHECKTYPE %s stack[%d] arg %d",
|
||||||
|
pfx, current,
|
||||||
type_name(ct->ct_type, &tofree),
|
type_name(ct->ct_type, &tofree),
|
||||||
(int)ct->ct_off,
|
(int)ct->ct_off,
|
||||||
(int)ct->ct_arg_idx);
|
(int)ct->ct_arg_idx);
|
||||||
|
Reference in New Issue
Block a user