mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.1890: Vim9: strange error for subtracting from a list
Problem: Vim9: strange error for subtracting from a list.
Solution: Check getting a number, not a string. (closes vim/vim#7167)
081db1a66d
Cherry-pick eval_addblob() and eval_addlist() from patch 8.2.0149.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
befb47f2e1
commit
99faac8644
@ -2556,6 +2556,39 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make a copy of blob "tv1" and append blob "tv2".
|
||||||
|
static void eval_addblob(typval_T *tv1, typval_T *tv2)
|
||||||
|
{
|
||||||
|
const blob_T *const b1 = tv1->vval.v_blob;
|
||||||
|
const blob_T *const b2 = tv2->vval.v_blob;
|
||||||
|
blob_T *const b = tv_blob_alloc();
|
||||||
|
|
||||||
|
for (int i = 0; i < tv_blob_len(b1); i++) {
|
||||||
|
ga_append(&b->bv_ga, tv_blob_get(b1, i));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < tv_blob_len(b2); i++) {
|
||||||
|
ga_append(&b->bv_ga, tv_blob_get(b2, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
tv_clear(tv1);
|
||||||
|
tv_blob_set_ret(tv1, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make a copy of list "tv1" and append list "tv2".
|
||||||
|
static int eval_addlist(typval_T *tv1, typval_T *tv2)
|
||||||
|
{
|
||||||
|
typval_T var3;
|
||||||
|
// Concatenate Lists.
|
||||||
|
if (tv_list_concat(tv1->vval.v_list, tv2->vval.v_list, &var3) == FAIL) {
|
||||||
|
tv_clear(tv1);
|
||||||
|
tv_clear(tv2);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
tv_clear(tv1);
|
||||||
|
*tv1 = var3;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle fourth level expression:
|
/// Handle fourth level expression:
|
||||||
/// + number addition, concatenation of list or blob
|
/// + number addition, concatenation of list or blob
|
||||||
/// - number subtraction
|
/// - number subtraction
|
||||||
@ -2569,7 +2602,6 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
|
|||||||
static int eval5(char **arg, typval_T *rettv, int evaluate)
|
static int eval5(char **arg, typval_T *rettv, int evaluate)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
typval_T var3;
|
|
||||||
varnumber_T n1, n2;
|
varnumber_T n1, n2;
|
||||||
float_T f1 = 0, f2 = 0;
|
float_T f1 = 0, f2 = 0;
|
||||||
char *p;
|
char *p;
|
||||||
@ -2587,7 +2619,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB))
|
if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB))
|
||||||
&& (op == '.' || rettv->v_type != VAR_FLOAT)) {
|
&& (op == '.' || rettv->v_type != VAR_FLOAT) && evaluate) {
|
||||||
// For "list + ...", an illegal use of the first operand as
|
// For "list + ...", an illegal use of the first operand as
|
||||||
// a number cannot be determined before evaluating the 2nd
|
// a number cannot be determined before evaluating the 2nd
|
||||||
// operand: if this is also a list, all is ok.
|
// operand: if this is also a list, all is ok.
|
||||||
@ -2595,7 +2627,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
|
|||||||
// we know that the first operand needs to be a string or number
|
// we know that the first operand needs to be a string or number
|
||||||
// without evaluating the 2nd operand. So check before to avoid
|
// without evaluating the 2nd operand. So check before to avoid
|
||||||
// side effects after an error.
|
// side effects after an error.
|
||||||
if (evaluate && !tv_check_str(rettv)) {
|
if ((op == '.' && !tv_check_str(rettv)) || (op != '.' && !tv_check_num(rettv))) {
|
||||||
tv_clear(rettv);
|
tv_clear(rettv);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@ -2628,32 +2660,12 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
|
|||||||
tv_clear(rettv);
|
tv_clear(rettv);
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = p;
|
rettv->vval.v_string = p;
|
||||||
} else if (op == '+' && rettv->v_type == VAR_BLOB
|
} else if (op == '+' && rettv->v_type == VAR_BLOB && var2.v_type == VAR_BLOB) {
|
||||||
&& var2.v_type == VAR_BLOB) {
|
eval_addblob(rettv, &var2);
|
||||||
const blob_T *const b1 = rettv->vval.v_blob;
|
} else if (op == '+' && rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST) {
|
||||||
const blob_T *const b2 = var2.vval.v_blob;
|
if (eval_addlist(rettv, &var2) == FAIL) {
|
||||||
blob_T *const b = tv_blob_alloc();
|
|
||||||
|
|
||||||
for (int i = 0; i < tv_blob_len(b1); i++) {
|
|
||||||
ga_append(&b->bv_ga, tv_blob_get(b1, i));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < tv_blob_len(b2); i++) {
|
|
||||||
ga_append(&b->bv_ga, tv_blob_get(b2, i));
|
|
||||||
}
|
|
||||||
|
|
||||||
tv_clear(rettv);
|
|
||||||
tv_blob_set_ret(rettv, b);
|
|
||||||
} else if (op == '+' && rettv->v_type == VAR_LIST
|
|
||||||
&& var2.v_type == VAR_LIST) {
|
|
||||||
// Concatenate Lists.
|
|
||||||
if (tv_list_concat(rettv->vval.v_list, var2.vval.v_list, &var3)
|
|
||||||
== FAIL) {
|
|
||||||
tv_clear(rettv);
|
|
||||||
tv_clear(&var2);
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
tv_clear(rettv);
|
|
||||||
*rettv = var3;
|
|
||||||
} else {
|
} else {
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user