mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.3442: Vim9: || and && are not handled at compile time
Problem: Vim9: || and && are not handled at compile time when possible. Solution: When using constants generate fewer instructions.
This commit is contained in:
@@ -2847,7 +2847,7 @@ generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the last item of "ppconst" is a bool.
|
||||
* Check that the last item of "ppconst" is a bool, if there is an item.
|
||||
*/
|
||||
static int
|
||||
check_ppconst_bool(ppconst_T *ppconst)
|
||||
@@ -4845,7 +4845,8 @@ compile_expr7(
|
||||
}
|
||||
else
|
||||
{
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
if (cctx->ctx_skip != SKIP_YES
|
||||
&& generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
r = compile_load(arg, p, cctx, TRUE, TRUE);
|
||||
}
|
||||
@@ -5240,6 +5241,7 @@ compile_and_or(
|
||||
{
|
||||
garray_T *instr = &cctx->ctx_instr;
|
||||
garray_T end_ga;
|
||||
int save_skip = cctx->ctx_skip;
|
||||
|
||||
/*
|
||||
* Repeat until there is no following "||" or "&&"
|
||||
@@ -5251,7 +5253,10 @@ compile_and_or(
|
||||
long save_sourcing_lnum;
|
||||
int start_ctx_lnum = cctx->ctx_lnum;
|
||||
int save_lnum;
|
||||
int const_used;
|
||||
int status;
|
||||
jumpwhen_T jump_when = opchar == '|'
|
||||
? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE;
|
||||
|
||||
if (next != NULL)
|
||||
{
|
||||
@@ -5274,14 +5279,38 @@ compile_and_or(
|
||||
status = check_ppconst_bool(ppconst);
|
||||
if (status != FAIL)
|
||||
{
|
||||
// TODO: use ppconst if the value is a constant
|
||||
generate_ppconst(cctx, ppconst);
|
||||
// Use the last ppconst if possible.
|
||||
if (ppconst->pp_used > 0)
|
||||
{
|
||||
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
|
||||
int is_true = tv2bool(tv);
|
||||
|
||||
// Every part must evaluate to a bool.
|
||||
status = bool_on_stack(cctx);
|
||||
if (status != FAIL)
|
||||
status = ga_grow(&end_ga, 1);
|
||||
if ((is_true && opchar == '|')
|
||||
|| (!is_true && opchar == '&'))
|
||||
{
|
||||
// For "false && expr" and "true || expr" the "expr"
|
||||
// does not need to be evaluated.
|
||||
cctx->ctx_skip = SKIP_YES;
|
||||
clear_tv(tv);
|
||||
tv->v_type = VAR_BOOL;
|
||||
tv->vval.v_number = is_true ? VVAL_TRUE : VVAL_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For "true && expr" and "false || expr" only "expr"
|
||||
// needs to be evaluated.
|
||||
--ppconst->pp_used;
|
||||
jump_when = JUMP_NEVER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Every part must evaluate to a bool.
|
||||
status = bool_on_stack(cctx);
|
||||
}
|
||||
}
|
||||
if (status != FAIL)
|
||||
status = ga_grow(&end_ga, 1);
|
||||
cctx->ctx_lnum = save_lnum;
|
||||
if (status == FAIL)
|
||||
{
|
||||
@@ -5289,10 +5318,15 @@ compile_and_or(
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
*(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
|
||||
++end_ga.ga_len;
|
||||
generate_JUMP(cctx, opchar == '|'
|
||||
? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE, 0);
|
||||
if (jump_when != JUMP_NEVER)
|
||||
{
|
||||
if (cctx->ctx_skip != SKIP_YES)
|
||||
{
|
||||
*(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
|
||||
++end_ga.ga_len;
|
||||
}
|
||||
generate_JUMP(cctx, jump_when, 0);
|
||||
}
|
||||
|
||||
// eval the next expression
|
||||
SOURCING_LNUM = save_sourcing_lnum;
|
||||
@@ -5302,6 +5336,7 @@ compile_and_or(
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
const_used = ppconst->pp_used;
|
||||
if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
|
||||
: compile_expr4(arg, cctx, ppconst)) == FAIL)
|
||||
{
|
||||
@@ -5309,6 +5344,20 @@ compile_and_or(
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// "0 || 1" results in true, "1 && 0" results in false.
|
||||
if (ppconst->pp_used == const_used + 1)
|
||||
{
|
||||
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used - 1];
|
||||
|
||||
if (tv->v_type == VAR_NUMBER
|
||||
&& (tv->vval.v_number == 1 || tv->vval.v_number == 0))
|
||||
{
|
||||
tv->vval.v_number = tv->vval.v_number == 1
|
||||
? VVAL_TRUE : VVAL_FALSE;
|
||||
tv->v_type = VAR_BOOL;
|
||||
}
|
||||
}
|
||||
|
||||
p = may_peek_next_line(cctx, *arg, &next);
|
||||
}
|
||||
|
||||
@@ -5317,26 +5366,32 @@ compile_and_or(
|
||||
ga_clear(&end_ga);
|
||||
return FAIL;
|
||||
}
|
||||
generate_ppconst(cctx, ppconst);
|
||||
|
||||
// Every part must evaluate to a bool.
|
||||
if (bool_on_stack(cctx) == FAIL)
|
||||
if (cctx->ctx_skip != SKIP_YES && ppconst->pp_used == 0)
|
||||
// Every part must evaluate to a bool.
|
||||
if (bool_on_stack(cctx) == FAIL)
|
||||
{
|
||||
ga_clear(&end_ga);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (end_ga.ga_len > 0)
|
||||
{
|
||||
ga_clear(&end_ga);
|
||||
return FAIL;
|
||||
}
|
||||
// Fill in the end label in all jumps.
|
||||
generate_ppconst(cctx, ppconst);
|
||||
while (end_ga.ga_len > 0)
|
||||
{
|
||||
isn_T *isn;
|
||||
|
||||
// Fill in the end label in all jumps.
|
||||
while (end_ga.ga_len > 0)
|
||||
{
|
||||
isn_T *isn;
|
||||
|
||||
--end_ga.ga_len;
|
||||
isn = ((isn_T *)instr->ga_data)
|
||||
--end_ga.ga_len;
|
||||
isn = ((isn_T *)instr->ga_data)
|
||||
+ *(((int *)end_ga.ga_data) + end_ga.ga_len);
|
||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||
}
|
||||
ga_clear(&end_ga);
|
||||
}
|
||||
ga_clear(&end_ga);
|
||||
|
||||
cctx->ctx_skip = save_skip;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
Reference in New Issue
Block a user