mirror of
https://github.com/vim/vim.git
synced 2025-07-24 10:45:12 -04:00
patch 8.2.1647: Vim9: result of expression with && and || is not a bool
Problem: Vim9: result of expression with && and || cannot be assigned to a bool variable. Solution: Add the TTFLAG_BOOL_OK flag and convert the value if needed.
This commit is contained in:
parent
33e3346322
commit
4ed124cc6c
@ -1199,6 +1199,29 @@ def Test_disassemble_invert_bool()
|
||||
assert_equal(true, InvertBool())
|
||||
enddef
|
||||
|
||||
def ReturnBool(): bool
|
||||
let var: bool = "no" && [] || 123
|
||||
return var
|
||||
enddef
|
||||
|
||||
def Test_disassemble_return_bool()
|
||||
let instr = execute('disassemble ReturnBool')
|
||||
assert_match('ReturnBool\_s*' ..
|
||||
'let var: bool = "no" && \[\] || 123\_s*' ..
|
||||
'0 PUSHS "no"\_s*' ..
|
||||
'1 JUMP_AND_KEEP_IF_FALSE -> 3\_s*' ..
|
||||
'2 NEWLIST size 0\_s*' ..
|
||||
'3 JUMP_AND_KEEP_IF_TRUE -> 5\_s*' ..
|
||||
'4 PUSHNR 123\_s*' ..
|
||||
'5 2BOOL (!!val)\_s*' ..
|
||||
'\d STORE $0\_s*' ..
|
||||
'return var\_s*' ..
|
||||
'\d LOAD $0\_s*' ..
|
||||
'\d RETURN',
|
||||
instr)
|
||||
assert_equal(true, InvertBool())
|
||||
enddef
|
||||
|
||||
def Test_disassemble_compare()
|
||||
let cases = [
|
||||
['true == isFalse', 'COMPAREBOOL =='],
|
||||
|
@ -46,9 +46,16 @@ def Test_assignment_bool()
|
||||
assert_equal(v:false, bool2)
|
||||
|
||||
let bool3: bool = 0
|
||||
assert_equal(0, bool3)
|
||||
assert_equal(false, bool3)
|
||||
let bool4: bool = 1
|
||||
assert_equal(1, bool4)
|
||||
assert_equal(true, bool4)
|
||||
|
||||
let bool5: bool = 'yes' && 'no'
|
||||
assert_equal(true, bool5)
|
||||
let bool6: bool = [] && 99
|
||||
assert_equal(false, bool6)
|
||||
let bool7: bool = [] || #{a: 1} && 99
|
||||
assert_equal(true, bool7)
|
||||
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
@ -57,8 +64,15 @@ def Test_assignment_bool()
|
||||
return flag
|
||||
enddef
|
||||
let flag: bool = GetFlag()
|
||||
assert_equal(true, flag)
|
||||
flag = 0
|
||||
# assert_equal(false, flag)
|
||||
flag = 1
|
||||
# assert_equal(true, flag)
|
||||
# flag = 99 || 123
|
||||
# assert_equal(true, flag)
|
||||
# flag = 'yes' && []
|
||||
# assert_equal(false, flag)
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
CheckDefAndScriptFailure(['let x: bool = 2'], 'E1012:')
|
||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1647,
|
||||
/**/
|
||||
1646,
|
||||
/**/
|
||||
|
@ -729,6 +729,15 @@ need_type(
|
||||
cctx_T *cctx,
|
||||
int silent)
|
||||
{
|
||||
if (expected == &t_bool && actual != &t_bool
|
||||
&& (actual->tt_flags & TTFLAG_BOOL_OK))
|
||||
{
|
||||
// Using "0", "1" or the result of an expression with "&&" or "||" as a
|
||||
// boolean is OK but requires a conversion.
|
||||
generate_2BOOL(cctx, FALSE);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (check_type(expected, actual, FALSE, 0) == OK)
|
||||
return OK;
|
||||
if (actual->tt_type != VAR_ANY
|
||||
@ -3926,6 +3935,8 @@ compile_and_or(
|
||||
{
|
||||
garray_T *instr = &cctx->ctx_instr;
|
||||
garray_T end_ga;
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
type_T **typep;
|
||||
|
||||
/*
|
||||
* Repeat until there is no following "||" or "&&"
|
||||
@ -3985,6 +3996,20 @@ compile_and_or(
|
||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||
}
|
||||
ga_clear(&end_ga);
|
||||
|
||||
// The resulting type can be used as a bool.
|
||||
typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
|
||||
if (*typep != &t_bool)
|
||||
{
|
||||
type_T *type = alloc_type(cctx->ctx_type_list);
|
||||
|
||||
if (type != NULL)
|
||||
{
|
||||
*type = **typep;
|
||||
type->tt_flags |= TTFLAG_BOOL_OK;
|
||||
*typep = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
Loading…
x
Reference in New Issue
Block a user