@@ -2110,6 +2110,7 @@ eval0(
21102110/*
21112111 * Handle top level expression:
21122112 * expr2 ? expr1 : expr1
2113+ * expr2 ?? expr1
21132114 *
21142115 * "arg" must point to the first non-white of the expression.
21152116 * "arg" is advanced to just after the recognized expression.
@@ -2135,6 +2136,7 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
21352136 p = eval_next_non_blank (* arg , evalarg , & getnext );
21362137 if (* p == '?' )
21372138 {
2139+ int op_falsy = p [1 ] == '?' ;
21382140 int result ;
21392141 typval_T var2 ;
21402142 evalarg_T * evalarg_used = evalarg ;
@@ -2168,81 +2170,89 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
21682170 {
21692171 int error = FALSE;
21702172
2171- if (in_vim9script ())
2173+ if (in_vim9script () || op_falsy )
21722174 result = tv2bool (rettv );
21732175 else if (tv_get_number_chk (rettv , & error ) != 0 )
21742176 result = TRUE;
2175- clear_tv (rettv );
2177+ if (error || !op_falsy || !result )
2178+ clear_tv (rettv );
21762179 if (error )
21772180 return FAIL ;
21782181 }
21792182
21802183 /*
21812184 * Get the second variable. Recursive!
21822185 */
2186+ if (op_falsy )
2187+ ++ * arg ;
21832188 if (evaluate && in_vim9script () && !IS_WHITE_OR_NUL ((* arg )[1 ]))
21842189 {
21852190 error_white_both (p , 1 );
21862191 clear_tv (rettv );
21872192 return FAIL ;
21882193 }
21892194 * arg = skipwhite_and_linebreak (* arg + 1 , evalarg_used );
2190- evalarg_used -> eval_flags = result ? orig_flags
2191- : orig_flags & ~EVAL_EVALUATE ;
2192- if (eval1 (arg , rettv , evalarg_used ) == FAIL )
2195+ evalarg_used -> eval_flags = ( op_falsy ? ! result : result )
2196+ ? orig_flags : orig_flags & ~EVAL_EVALUATE ;
2197+ if (eval1 (arg , & var2 , evalarg_used ) == FAIL )
21932198 {
21942199 evalarg_used -> eval_flags = orig_flags ;
21952200 return FAIL ;
21962201 }
2202+ if (!op_falsy || !result )
2203+ * rettv = var2 ;
21972204
2198- /*
2199- * Check for the ":".
2200- */
2201- p = eval_next_non_blank (* arg , evalarg_used , & getnext );
2202- if (* p != ':' )
2203- {
2204- emsg (_ (e_missing_colon ));
2205- if (evaluate && result )
2206- clear_tv (rettv );
2207- evalarg_used -> eval_flags = orig_flags ;
2208- return FAIL ;
2209- }
2210- if (getnext )
2211- * arg = eval_next_line (evalarg_used );
2212- else
2205+ if (!op_falsy )
22132206 {
2214- if (evaluate && in_vim9script () && !VIM_ISWHITE (p [-1 ]))
2207+ /*
2208+ * Check for the ":".
2209+ */
2210+ p = eval_next_non_blank (* arg , evalarg_used , & getnext );
2211+ if (* p != ':' )
2212+ {
2213+ emsg (_ (e_missing_colon ));
2214+ if (evaluate && result )
2215+ clear_tv (rettv );
2216+ evalarg_used -> eval_flags = orig_flags ;
2217+ return FAIL ;
2218+ }
2219+ if (getnext )
2220+ * arg = eval_next_line (evalarg_used );
2221+ else
2222+ {
2223+ if (evaluate && in_vim9script () && !VIM_ISWHITE (p [-1 ]))
2224+ {
2225+ error_white_both (p , 1 );
2226+ clear_tv (rettv );
2227+ evalarg_used -> eval_flags = orig_flags ;
2228+ return FAIL ;
2229+ }
2230+ * arg = p ;
2231+ }
2232+
2233+ /*
2234+ * Get the third variable. Recursive!
2235+ */
2236+ if (evaluate && in_vim9script () && !IS_WHITE_OR_NUL ((* arg )[1 ]))
22152237 {
22162238 error_white_both (p , 1 );
22172239 clear_tv (rettv );
22182240 evalarg_used -> eval_flags = orig_flags ;
22192241 return FAIL ;
22202242 }
2221- * arg = p ;
2222- }
2223-
2224- /*
2225- * Get the third variable. Recursive!
2226- */
2227- if (evaluate && in_vim9script () && !IS_WHITE_OR_NUL ((* arg )[1 ]))
2228- {
2229- error_white_both (p , 1 );
2230- clear_tv (rettv );
2231- evalarg_used -> eval_flags = orig_flags ;
2232- return FAIL ;
2233- }
2234- * arg = skipwhite_and_linebreak (* arg + 1 , evalarg_used );
2235- evalarg_used -> eval_flags = !result ? orig_flags
2243+ * arg = skipwhite_and_linebreak (* arg + 1 , evalarg_used );
2244+ evalarg_used -> eval_flags = !result ? orig_flags
22362245 : orig_flags & ~EVAL_EVALUATE ;
2237- if (eval1 (arg , & var2 , evalarg_used ) == FAIL )
2238- {
2239- if (evaluate && result )
2240- clear_tv (rettv );
2241- evalarg_used -> eval_flags = orig_flags ;
2242- return FAIL ;
2246+ if (eval1 (arg , & var2 , evalarg_used ) == FAIL )
2247+ {
2248+ if (evaluate && result )
2249+ clear_tv (rettv );
2250+ evalarg_used -> eval_flags = orig_flags ;
2251+ return FAIL ;
2252+ }
2253+ if (evaluate && !result )
2254+ * rettv = var2 ;
22432255 }
2244- if (evaluate && !result )
2245- * rettv = var2 ;
22462256
22472257 if (evalarg == NULL )
22482258 clear_evalarg (& local_evalarg , NULL );
0 commit comments