aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-04-14 11:00:17 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-04-14 18:04:09 +0800
commitd6e2804ab4f8810293dbcd748bfb938d9e0c3d52 (patch)
treeee140b0eee513de0aad0cf6cbd55d56f4799dd7f /src/nvim/eval.c
parent7caf0eafd83b5a92f2ff219b3a64ffae4174b9af (diff)
downloadrneovim-d6e2804ab4f8810293dbcd748bfb938d9e0c3d52.tar.gz
rneovim-d6e2804ab4f8810293dbcd748bfb938d9e0c3d52.tar.bz2
rneovim-d6e2804ab4f8810293dbcd748bfb938d9e0c3d52.zip
vim-patch:8.2.1794: no falsy Coalescing operator
Problem: No falsy Coalescing operator. Solution: Add the "??" operator. Fix mistake with function argument count. https://github.com/vim/vim/commit/92f26c256e06277ff2ec4ce7adea1eb58c85abe0 Cherry-pick tv2bool() into eval/typval.c. Cherry-pick *??* tag from Vim runtime. Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index dab3afb212..59e998d50f 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -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;
- }
-
- // 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;
+ if (op_falsy) {
+ (*arg)++;
}
-
- // 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 {