mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
Merge pull request #23083 from zeertzjq/vim-8.2.1189
vim-patch:8.2.{1189,1512}
This commit is contained in:
110
src/nvim/eval.c
110
src/nvim/eval.c
@@ -2352,9 +2352,14 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
|
|
||||||
char *p = *arg;
|
char *p = *arg;
|
||||||
if (*p == '?') {
|
if (*p == '?') {
|
||||||
evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
|
evalarg_T *evalarg_used = evalarg;
|
||||||
const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
evalarg_T local_evalarg;
|
||||||
const bool evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
|
if (evalarg == NULL) {
|
||||||
|
local_evalarg = (evalarg_T){ .eval_flags = 0 };
|
||||||
|
evalarg_used = &local_evalarg;
|
||||||
|
}
|
||||||
|
const int orig_flags = evalarg_used->eval_flags;
|
||||||
|
const bool evaluate = evalarg_used->eval_flags & EVAL_EVALUATE;
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
@@ -2371,8 +2376,9 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
|
|
||||||
// Get the second variable. Recursive!
|
// Get the second variable. Recursive!
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
nested_evalarg.eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||||
if (eval1(arg, rettv, &nested_evalarg) == FAIL) {
|
if (eval1(arg, rettv, evalarg_used) == FAIL) {
|
||||||
|
evalarg_used->eval_flags = orig_flags;
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2383,22 +2389,30 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
if (evaluate && result) {
|
if (evaluate && result) {
|
||||||
tv_clear(rettv);
|
tv_clear(rettv);
|
||||||
}
|
}
|
||||||
|
evalarg_used->eval_flags = orig_flags;
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the third variable. Recursive!
|
// Get the third variable. Recursive!
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
|
evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
nested_evalarg.eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
if (eval1(arg, &var2, evalarg_used) == FAIL) {
|
||||||
if (eval1(arg, &var2, &nested_evalarg) == FAIL) {
|
|
||||||
if (evaluate && result) {
|
if (evaluate && result) {
|
||||||
tv_clear(rettv);
|
tv_clear(rettv);
|
||||||
}
|
}
|
||||||
|
evalarg_used->eval_flags = orig_flags;
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (evaluate && !result) {
|
if (evaluate && !result) {
|
||||||
*rettv = var2;
|
*rettv = var2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evalarg == NULL) {
|
||||||
|
clear_evalarg(&local_evalarg, NULL);
|
||||||
|
} else {
|
||||||
|
evalarg->eval_flags = orig_flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -2413,24 +2427,27 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
/// @return OK or FAIL.
|
/// @return OK or FAIL.
|
||||||
static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
// Get the first variable.
|
// Get the first variable.
|
||||||
if (eval3(arg, rettv, evalarg) == FAIL) {
|
if (eval3(arg, rettv, evalarg) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat until there is no following "||".
|
// Handle the "||" operator.
|
||||||
bool first = true;
|
|
||||||
bool result = false;
|
|
||||||
char *p = *arg;
|
char *p = *arg;
|
||||||
while (p[0] == '|' && p[1] == '|') {
|
if (p[0] == '|' && p[1] == '|') {
|
||||||
evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
|
evalarg_T *evalarg_used = evalarg;
|
||||||
const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
evalarg_T local_evalarg;
|
||||||
const bool evaluate = orig_flags & EVAL_EVALUATE;
|
if (evalarg == NULL) {
|
||||||
|
local_evalarg = (evalarg_T){ .eval_flags = 0 };
|
||||||
|
evalarg_used = &local_evalarg;
|
||||||
|
}
|
||||||
|
const int orig_flags = evalarg_used->eval_flags;
|
||||||
|
const bool evaluate = evalarg_used->eval_flags & EVAL_EVALUATE;
|
||||||
|
|
||||||
if (evaluate && first) {
|
bool result = false;
|
||||||
|
|
||||||
|
if (evaluate) {
|
||||||
|
bool error = false;
|
||||||
if (tv_get_number_chk(rettv, &error) != 0) {
|
if (tv_get_number_chk(rettv, &error) != 0) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -2438,18 +2455,21 @@ static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
if (error) {
|
if (error) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repeat until there is no following "||".
|
||||||
|
while (p[0] == '|' && p[1] == '|') {
|
||||||
// Get the second variable.
|
// Get the second variable.
|
||||||
*arg = skipwhite(*arg + 2);
|
*arg = skipwhite(*arg + 2);
|
||||||
nested_evalarg.eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||||
if (eval3(arg, &var2, &nested_evalarg) == FAIL) {
|
typval_T var2;
|
||||||
|
if (eval3(arg, &var2, evalarg_used) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the result.
|
// Compute the result.
|
||||||
if (evaluate && !result) {
|
if (evaluate && !result) {
|
||||||
|
bool error = false;
|
||||||
if (tv_get_number_chk(&var2, &error) != 0) {
|
if (tv_get_number_chk(&var2, &error) != 0) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -2466,6 +2486,13 @@ static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
p = *arg;
|
p = *arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evalarg == NULL) {
|
||||||
|
clear_evalarg(&local_evalarg, NULL);
|
||||||
|
} else {
|
||||||
|
evalarg->eval_flags = orig_flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2478,24 +2505,27 @@ static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
/// @return OK or FAIL.
|
/// @return OK or FAIL.
|
||||||
static int eval3(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
static int eval3(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
// Get the first variable.
|
// Get the first variable.
|
||||||
if (eval4(arg, rettv, evalarg) == FAIL) {
|
if (eval4(arg, rettv, evalarg) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat until there is no following "&&".
|
|
||||||
bool first = true;
|
|
||||||
bool result = true;
|
|
||||||
char *p = *arg;
|
char *p = *arg;
|
||||||
while (p[0] == '&' && p[1] == '&') {
|
// Handle the "&&" operator.
|
||||||
evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
|
if (p[0] == '&' && p[1] == '&') {
|
||||||
const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
evalarg_T *evalarg_used = evalarg;
|
||||||
const bool evaluate = orig_flags & EVAL_EVALUATE;
|
evalarg_T local_evalarg;
|
||||||
|
if (evalarg == NULL) {
|
||||||
|
local_evalarg = (evalarg_T){ .eval_flags = 0 };
|
||||||
|
evalarg_used = &local_evalarg;
|
||||||
|
}
|
||||||
|
const int orig_flags = evalarg_used->eval_flags;
|
||||||
|
const bool evaluate = evalarg_used->eval_flags & EVAL_EVALUATE;
|
||||||
|
|
||||||
if (evaluate && first) {
|
bool result = true;
|
||||||
|
|
||||||
|
if (evaluate) {
|
||||||
|
bool error = false;
|
||||||
if (tv_get_number_chk(rettv, &error) == 0) {
|
if (tv_get_number_chk(rettv, &error) == 0) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@@ -2503,18 +2533,21 @@ static int eval3(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
if (error) {
|
if (error) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repeat until there is no following "&&".
|
||||||
|
while (p[0] == '&' && p[1] == '&') {
|
||||||
// Get the second variable.
|
// Get the second variable.
|
||||||
*arg = skipwhite(*arg + 2);
|
*arg = skipwhite(*arg + 2);
|
||||||
nested_evalarg.eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||||
if (eval4(arg, &var2, &nested_evalarg) == FAIL) {
|
typval_T var2;
|
||||||
|
if (eval4(arg, &var2, evalarg_used) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the result.
|
// Compute the result.
|
||||||
if (evaluate && result) {
|
if (evaluate && result) {
|
||||||
|
bool error = false;
|
||||||
if (tv_get_number_chk(&var2, &error) == 0) {
|
if (tv_get_number_chk(&var2, &error) == 0) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
@@ -2531,6 +2564,13 @@ static int eval3(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
|||||||
p = *arg;
|
p = *arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evalarg == NULL) {
|
||||||
|
clear_evalarg(&local_evalarg, NULL);
|
||||||
|
} else {
|
||||||
|
evalarg->eval_flags = orig_flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7258,6 +7258,30 @@ func Test_typed_script_var()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for issue6776 {{{1
|
||||||
|
func Test_trinary_expression()
|
||||||
|
try
|
||||||
|
call eval('0 ? 0')
|
||||||
|
catch
|
||||||
|
endtry
|
||||||
|
" previous failure should not cause next expression to fail
|
||||||
|
call assert_equal(v:false, eval(string(v:false)))
|
||||||
|
|
||||||
|
try
|
||||||
|
call eval('0 ? "burp')
|
||||||
|
catch
|
||||||
|
endtry
|
||||||
|
" previous failure should not cause next expression to fail
|
||||||
|
call assert_equal(v:false, eval(string(v:false)))
|
||||||
|
|
||||||
|
try
|
||||||
|
call eval('1 ? 0 : "burp')
|
||||||
|
catch
|
||||||
|
endtry
|
||||||
|
" previous failure should not cause next expression to fail
|
||||||
|
call assert_equal(v:false, eval(string(v:false)))
|
||||||
|
endfunction
|
||||||
|
|
||||||
func Test_for_over_string()
|
func Test_for_over_string()
|
||||||
let res = ''
|
let res = ''
|
||||||
for c in 'aéc̀d'
|
for c in 'aéc̀d'
|
||||||
|
Reference in New Issue
Block a user