@@ -2847,7 +2847,7 @@ generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
28472847}
28482848
28492849/*
2850- * Check that the last item of "ppconst" is a bool.
2850+ * Check that the last item of "ppconst" is a bool, if there is an item .
28512851 */
28522852 static int
28532853check_ppconst_bool (ppconst_T * ppconst )
@@ -4845,7 +4845,8 @@ compile_expr7(
48454845 }
48464846 else
48474847 {
4848- if (generate_ppconst (cctx , ppconst ) == FAIL )
4848+ if (cctx -> ctx_skip != SKIP_YES
4849+ && generate_ppconst (cctx , ppconst ) == FAIL )
48494850 return FAIL ;
48504851 r = compile_load (arg , p , cctx , TRUE, TRUE);
48514852 }
@@ -5240,6 +5241,7 @@ compile_and_or(
52405241 {
52415242 garray_T * instr = & cctx -> ctx_instr ;
52425243 garray_T end_ga ;
5244+ int save_skip = cctx -> ctx_skip ;
52435245
52445246 /*
52455247 * Repeat until there is no following "||" or "&&"
@@ -5251,7 +5253,10 @@ compile_and_or(
52515253 long save_sourcing_lnum ;
52525254 int start_ctx_lnum = cctx -> ctx_lnum ;
52535255 int save_lnum ;
5256+ int const_used ;
52545257 int status ;
5258+ jumpwhen_T jump_when = opchar == '|'
5259+ ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE ;
52555260
52565261 if (next != NULL )
52575262 {
@@ -5274,25 +5279,54 @@ compile_and_or(
52745279 status = check_ppconst_bool (ppconst );
52755280 if (status != FAIL )
52765281 {
5277- // TODO: use ppconst if the value is a constant
5278- generate_ppconst (cctx , ppconst );
5282+ // Use the last ppconst if possible.
5283+ if (ppconst -> pp_used > 0 )
5284+ {
5285+ typval_T * tv = & ppconst -> pp_tv [ppconst -> pp_used - 1 ];
5286+ int is_true = tv2bool (tv );
52795287
5280- // Every part must evaluate to a bool.
5281- status = bool_on_stack (cctx );
5282- if (status != FAIL )
5283- status = ga_grow (& end_ga , 1 );
5288+ if ((is_true && opchar == '|' )
5289+ || (!is_true && opchar == '&' ))
5290+ {
5291+ // For "false && expr" and "true || expr" the "expr"
5292+ // does not need to be evaluated.
5293+ cctx -> ctx_skip = SKIP_YES ;
5294+ clear_tv (tv );
5295+ tv -> v_type = VAR_BOOL ;
5296+ tv -> vval .v_number = is_true ? VVAL_TRUE : VVAL_FALSE ;
5297+ }
5298+ else
5299+ {
5300+ // For "true && expr" and "false || expr" only "expr"
5301+ // needs to be evaluated.
5302+ -- ppconst -> pp_used ;
5303+ jump_when = JUMP_NEVER ;
5304+ }
5305+ }
5306+ else
5307+ {
5308+ // Every part must evaluate to a bool.
5309+ status = bool_on_stack (cctx );
5310+ }
52845311 }
5312+ if (status != FAIL )
5313+ status = ga_grow (& end_ga , 1 );
52855314 cctx -> ctx_lnum = save_lnum ;
52865315 if (status == FAIL )
52875316 {
52885317 ga_clear (& end_ga );
52895318 return FAIL ;
52905319 }
52915320
5292- * (((int * )end_ga .ga_data ) + end_ga .ga_len ) = instr -> ga_len ;
5293- ++ end_ga .ga_len ;
5294- generate_JUMP (cctx , opchar == '|'
5295- ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE , 0 );
5321+ if (jump_when != JUMP_NEVER )
5322+ {
5323+ if (cctx -> ctx_skip != SKIP_YES )
5324+ {
5325+ * (((int * )end_ga .ga_data ) + end_ga .ga_len ) = instr -> ga_len ;
5326+ ++ end_ga .ga_len ;
5327+ }
5328+ generate_JUMP (cctx , jump_when , 0 );
5329+ }
52965330
52975331 // eval the next expression
52985332 SOURCING_LNUM = save_sourcing_lnum ;
@@ -5302,13 +5336,28 @@ compile_and_or(
53025336 return FAIL ;
53035337 }
53045338
5339+ const_used = ppconst -> pp_used ;
53055340 if ((opchar == '|' ? compile_expr3 (arg , cctx , ppconst )
53065341 : compile_expr4 (arg , cctx , ppconst )) == FAIL )
53075342 {
53085343 ga_clear (& end_ga );
53095344 return FAIL ;
53105345 }
53115346
5347+ // "0 || 1" results in true, "1 && 0" results in false.
5348+ if (ppconst -> pp_used == const_used + 1 )
5349+ {
5350+ typval_T * tv = & ppconst -> pp_tv [ppconst -> pp_used - 1 ];
5351+
5352+ if (tv -> v_type == VAR_NUMBER
5353+ && (tv -> vval .v_number == 1 || tv -> vval .v_number == 0 ))
5354+ {
5355+ tv -> vval .v_number = tv -> vval .v_number == 1
5356+ ? VVAL_TRUE : VVAL_FALSE ;
5357+ tv -> v_type = VAR_BOOL ;
5358+ }
5359+ }
5360+
53125361 p = may_peek_next_line (cctx , * arg , & next );
53135362 }
53145363
@@ -5317,26 +5366,32 @@ compile_and_or(
53175366 ga_clear (& end_ga );
53185367 return FAIL ;
53195368 }
5320- generate_ppconst (cctx , ppconst );
53215369
5322- // Every part must evaluate to a bool.
5323- if (bool_on_stack (cctx ) == FAIL )
5324- {
5325- ga_clear (& end_ga );
5326- return FAIL ;
5327- }
5370+ if (cctx -> ctx_skip != SKIP_YES && ppconst -> pp_used == 0 )
5371+ // Every part must evaluate to a bool.
5372+ if (bool_on_stack (cctx ) == FAIL )
5373+ {
5374+ ga_clear (& end_ga );
5375+ return FAIL ;
5376+ }
53285377
5329- // Fill in the end label in all jumps.
5330- while (end_ga .ga_len > 0 )
5378+ if (end_ga .ga_len > 0 )
53315379 {
5332- isn_T * isn ;
5380+ // Fill in the end label in all jumps.
5381+ generate_ppconst (cctx , ppconst );
5382+ while (end_ga .ga_len > 0 )
5383+ {
5384+ isn_T * isn ;
53335385
5334- -- end_ga .ga_len ;
5335- isn = ((isn_T * )instr -> ga_data )
5386+ -- end_ga .ga_len ;
5387+ isn = ((isn_T * )instr -> ga_data )
53365388 + * (((int * )end_ga .ga_data ) + end_ga .ga_len );
5337- isn -> isn_arg .jump .jump_where = instr -> ga_len ;
5389+ isn -> isn_arg .jump .jump_where = instr -> ga_len ;
5390+ }
5391+ ga_clear (& end_ga );
53385392 }
5339- ga_clear (& end_ga );
5393+
5394+ cctx -> ctx_skip = save_skip ;
53405395 }
53415396
53425397 return OK ;
0 commit comments