Skip to content

Commit

Permalink
patch 9.0.2027: Vim9: no support for bitwise operators in lambda funcs
Browse files Browse the repository at this point in the history
Problem:  Vim9: no support for bitwise operators in lambda funcs
Solution: move "evaluate" assignment a bit up in order to decide
          to perform bitwise operations

closes: #13342
closes: #13345

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
  • Loading branch information
yegappan authored and chrisbra committed Oct 15, 2023
1 parent ae3cfa4 commit de3295d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 14 deletions.
28 changes: 14 additions & 14 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -3515,15 +3515,15 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
return OK;

// Handle a bitwise left or right shift operator
if (rettv->v_type != VAR_NUMBER)
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
if (evaluate && rettv->v_type != VAR_NUMBER)
{
// left operand should be a number
emsg(_(e_bitshift_ops_must_be_number));
clear_tv(rettv);
return FAIL;
}

evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
vim9script = in_vim9script();
if (getnext)
{
Expand Down Expand Up @@ -3553,20 +3553,20 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
return FAIL;
}

if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
{
// right operand should be a positive number
if (var2.v_type != VAR_NUMBER)
emsg(_(e_bitshift_ops_must_be_number));
else
emsg(_(e_bitshift_ops_must_be_positive));
clear_tv(rettv);
clear_tv(&var2);
return FAIL;
}

if (evaluate)
{
if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
{
// right operand should be a positive number
if (var2.v_type != VAR_NUMBER)
emsg(_(e_bitshift_ops_must_be_number));
else
emsg(_(e_bitshift_ops_must_be_positive));
clear_tv(rettv);
clear_tv(&var2);
return FAIL;
}

if (var2.vval.v_number > MAX_LSHIFT_BITS)
// shifting more bits than we have always results in zero
rettv->vval.v_number = 0;
Expand Down
44 changes: 44 additions & 0 deletions src/testdir/test_expr.vim
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,50 @@ func Test_bitwise_shift()
assert_equal(16, a)
END
call v9.CheckDefAndScriptSuccess(lines)

let lines =<< trim END
# Use in a lambda function
const DivBy2Ref_A = (n: number): number => n >> 1
assert_equal(16, DivBy2Ref_A(32))
const DivBy2Ref_B = (n: number): number => (<number>n) >> 1
assert_equal(16, DivBy2Ref_B(32))
const MultBy2Ref_A = (n: number): number => n << 1
assert_equal(8, MultBy2Ref_A(4))
const MultBy2Ref_B = (n: number): number => (<number>n) << 1
assert_equal(8, MultBy2Ref_B(4))

def DivBy2_A(): func(number): number
return (n: number): number => n >> 1
enddef
assert_equal(16, DivBy2_A()(32))
def DivBy2_B(): func(number): number
return (n: number): number => (<number>n) >> 1
enddef
assert_equal(16, DivBy2_B()(32))
def MultBy2_A(): func(number): number
return (n: number): number => n << 1
enddef
assert_equal(64, MultBy2_A()(32))
def MultBy2_B(): func(number): number
return (n: number): number => (<number>n) << 1
enddef
assert_equal(64, MultBy2_B()(32))
END
call v9.CheckDefAndScriptSuccess(lines)

" Use in a legacy lambda function
const DivBy2Ref_A = {n -> n >> 1}
call assert_equal(16, DivBy2Ref_A(32))
func DivBy2_A()
return {n -> n >> 1}
endfunc
call assert_equal(16, DivBy2_A()(32))
const MultBy2Ref_A = {n -> n << 1}
call assert_equal(64, MultBy2Ref_A(32))
func MultBy2_A()
return {n -> n << 1}
endfunc
call assert_equal(64, MultBy2_A()(32))
endfunc

" vim: shiftwidth=2 sts=2 expandtab
2 changes: 2 additions & 0 deletions src/version.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2027,
/**/
2026,
/**/
Expand Down

0 comments on commit de3295d

Please sign in to comment.