diff options
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 98 |
1 files changed, 54 insertions, 44 deletions
diff --git a/src/eval.c b/src/eval.c index c8c4f6e5f4..911f0abc67 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2110,6 +2110,7 @@ eval0( /* * Handle top level expression: * expr2 ? expr1 : expr1 + * expr2 ?? expr1 * * "arg" must point to the first non-white of the expression. * "arg" is advanced to just after the recognized expression. @@ -2135,6 +2136,7 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) p = eval_next_non_blank(*arg, evalarg, &getnext); if (*p == '?') { + int op_falsy = p[1] == '?'; int result; typval_T var2; evalarg_T *evalarg_used = evalarg; @@ -2168,11 +2170,12 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { int error = FALSE; - if (in_vim9script()) + if (in_vim9script() || op_falsy) result = tv2bool(rettv); else if (tv_get_number_chk(rettv, &error) != 0) result = TRUE; - clear_tv(rettv); + if (error || !op_falsy || !result) + clear_tv(rettv); if (error) return FAIL; } @@ -2180,6 +2183,8 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. Recursive! */ + if (op_falsy) + ++*arg; if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) { error_white_both(p, 1); @@ -2187,62 +2192,67 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) return FAIL; } *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); - evalarg_used->eval_flags = result ? orig_flags - : orig_flags & ~EVAL_EVALUATE; - if (eval1(arg, rettv, evalarg_used) == FAIL) + evalarg_used->eval_flags = (op_falsy ? !result : result) + ? orig_flags : orig_flags & ~EVAL_EVALUATE; + if (eval1(arg, &var2, evalarg_used) == FAIL) { evalarg_used->eval_flags = orig_flags; return FAIL; } + if (!op_falsy || !result) + *rettv = var2; - /* - * Check for the ":". - */ - p = eval_next_non_blank(*arg, evalarg_used, &getnext); - if (*p != ':') - { - emsg(_(e_missing_colon)); - if (evaluate && result) - clear_tv(rettv); - evalarg_used->eval_flags = orig_flags; - return FAIL; - } - if (getnext) - *arg = eval_next_line(evalarg_used); - else + if (!op_falsy) { - if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + /* + * Check for the ":". + */ + p = eval_next_non_blank(*arg, evalarg_used, &getnext); + if (*p != ':') + { + emsg(_(e_missing_colon)); + if (evaluate && result) + clear_tv(rettv); + evalarg_used->eval_flags = orig_flags; + return FAIL; + } + if (getnext) + *arg = eval_next_line(evalarg_used); + else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + { + error_white_both(p, 1); + clear_tv(rettv); + evalarg_used->eval_flags = orig_flags; + return FAIL; + } + *arg = p; + } + + /* + * Get the third variable. Recursive! + */ + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) { error_white_both(p, 1); clear_tv(rettv); evalarg_used->eval_flags = orig_flags; return FAIL; } - *arg = p; - } - - /* - * Get the third variable. Recursive! - */ - if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) - { - error_white_both(p, 1); - clear_tv(rettv); - evalarg_used->eval_flags = orig_flags; - return FAIL; - } - *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); - evalarg_used->eval_flags = !result ? orig_flags + *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); + evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE; - if (eval1(arg, &var2, evalarg_used) == FAIL) - { - if (evaluate && result) - clear_tv(rettv); - evalarg_used->eval_flags = orig_flags; - return FAIL; + if (eval1(arg, &var2, evalarg_used) == FAIL) + { + if (evaluate && result) + clear_tv(rettv); + evalarg_used->eval_flags = orig_flags; + return FAIL; + } + if (evaluate && !result) + *rettv = var2; } - if (evaluate && !result) - *rettv = var2; if (evalarg == NULL) clear_evalarg(&local_evalarg, NULL); |