mirror of
https://github.com/neovim/neovim.git
synced 2025-09-22 03:08:27 +00:00
vim-patch:8.2.1794: no falsy Coalescing operator
Problem: No falsy Coalescing operator.
Solution: Add the "??" operator. Fix mistake with function argument count.
92f26c256e
Cherry-pick tv2bool() into eval/typval.c.
Cherry-pick *??* tag from Vim runtime.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -2336,6 +2336,7 @@ int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg)
|
||||
|
||||
/// Handle top level expression:
|
||||
/// expr2 ? expr1 : expr1
|
||||
/// expr2 ?? expr1
|
||||
///
|
||||
/// "arg" must point to the first non-white of the expression.
|
||||
/// "arg" is advanced to the next non-white after the recognized expression.
|
||||
@@ -2352,6 +2353,7 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
||||
|
||||
char *p = *arg;
|
||||
if (*p == '?') {
|
||||
const bool op_falsy = p[1] == '?';
|
||||
evalarg_T *evalarg_used = evalarg;
|
||||
evalarg_T local_evalarg;
|
||||
if (evalarg == NULL) {
|
||||
@@ -2365,49 +2367,62 @@ int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
|
||||
if (evaluate) {
|
||||
bool error = false;
|
||||
|
||||
if (tv_get_number_chk(rettv, &error) != 0) {
|
||||
if (op_falsy) {
|
||||
result = tv2bool(rettv);
|
||||
} else if (tv_get_number_chk(rettv, &error) != 0) {
|
||||
result = true;
|
||||
}
|
||||
tv_clear(rettv);
|
||||
if (error || !op_falsy || !result) {
|
||||
tv_clear(rettv);
|
||||
}
|
||||
if (error) {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the second variable. Recursive!
|
||||
*arg = skipwhite(*arg + 1);
|
||||
evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||
if (eval1(arg, rettv, evalarg_used) == FAIL) {
|
||||
evalarg_used->eval_flags = orig_flags;
|
||||
return FAIL;
|
||||
if (op_falsy) {
|
||||
(*arg)++;
|
||||
}
|
||||
|
||||
// Check for the ":".
|
||||
p = *arg;
|
||||
if (*p != ':') {
|
||||
emsg(_("E109: Missing ':' after '?'"));
|
||||
if (evaluate && result) {
|
||||
tv_clear(rettv);
|
||||
}
|
||||
evalarg_used->eval_flags = orig_flags;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// Get the third variable. Recursive!
|
||||
*arg = skipwhite(*arg + 1);
|
||||
evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||
evalarg_used->eval_flags = (op_falsy ? !result : result)
|
||||
? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||
typval_T var2;
|
||||
if (eval1(arg, &var2, evalarg_used) == FAIL) {
|
||||
if (evaluate && result) {
|
||||
tv_clear(rettv);
|
||||
}
|
||||
evalarg_used->eval_flags = orig_flags;
|
||||
return FAIL;
|
||||
}
|
||||
if (evaluate && !result) {
|
||||
if (!op_falsy || !result) {
|
||||
*rettv = var2;
|
||||
}
|
||||
|
||||
if (!op_falsy) {
|
||||
// Check for the ":".
|
||||
p = *arg;
|
||||
if (*p != ':') {
|
||||
emsg(_("E109: Missing ':' after '?'"));
|
||||
if (evaluate && result) {
|
||||
tv_clear(rettv);
|
||||
}
|
||||
evalarg_used->eval_flags = orig_flags;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// Get the third variable. Recursive!
|
||||
*arg = skipwhite(*arg + 1);
|
||||
evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
|
||||
if (eval1(arg, &var2, evalarg_used) == FAIL) {
|
||||
if (evaluate && result) {
|
||||
tv_clear(rettv);
|
||||
}
|
||||
evalarg_used->eval_flags = orig_flags;
|
||||
return FAIL;
|
||||
}
|
||||
if (evaluate && !result) {
|
||||
*rettv = var2;
|
||||
}
|
||||
}
|
||||
|
||||
if (evalarg == NULL) {
|
||||
clear_evalarg(&local_evalarg, NULL);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user