mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.5003: cannot do bitwise shifts
Problem: Cannot do bitwise shifts. Solution: Add the >> and << operators. (Yegappan Lakshmanan, closes #8457)
This commit is contained in:
committed by
Bram Moolenaar
parent
9b2edfd3bf
commit
a061f34191
155
src/vim9expr.c
155
src/vim9expr.c
@@ -1748,7 +1748,7 @@ compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
|
||||
static int compile_expr9(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
|
||||
|
||||
/*
|
||||
* Compile whatever comes after "name" or "name()".
|
||||
@@ -1909,7 +1909,7 @@ compile_subscript(
|
||||
// do not look in the next line
|
||||
cctx->ctx_ufunc->uf_lines.ga_len = 1;
|
||||
|
||||
fail = compile_expr8(arg, cctx, ppconst) == FAIL
|
||||
fail = compile_expr9(arg, cctx, ppconst) == FAIL
|
||||
|| *skipwhite(*arg) != NUL;
|
||||
*paren = '(';
|
||||
--paren_follows_after_expr;
|
||||
@@ -2143,7 +2143,7 @@ compile_subscript(
|
||||
* trailing ->name() method call
|
||||
*/
|
||||
static int
|
||||
compile_expr8(
|
||||
compile_expr9(
|
||||
char_u **arg,
|
||||
cctx_T *cctx,
|
||||
ppconst_T *ppconst)
|
||||
@@ -2389,10 +2389,10 @@ compile_expr8(
|
||||
}
|
||||
|
||||
/*
|
||||
* <type>expr8: runtime type check / conversion
|
||||
* <type>expr9: runtime type check / conversion
|
||||
*/
|
||||
static int
|
||||
compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
type_T *want_type = NULL;
|
||||
|
||||
@@ -2417,7 +2417,7 @@ compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (compile_expr8(arg, cctx, ppconst) == FAIL)
|
||||
if (compile_expr9(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (want_type != NULL)
|
||||
@@ -2444,14 +2444,14 @@ compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
* % number modulo
|
||||
*/
|
||||
static int
|
||||
compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
char_u *op;
|
||||
char_u *next;
|
||||
int ppconst_used = ppconst->pp_used;
|
||||
|
||||
// get the first expression
|
||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
||||
if (compile_expr8(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
@@ -2477,7 +2477,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return FAIL;
|
||||
|
||||
// get the second expression
|
||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
||||
if (compile_expr8(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (ppconst->pp_used == ppconst_used + 2
|
||||
@@ -2522,7 +2522,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
* .. string concatenation
|
||||
*/
|
||||
static int
|
||||
compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
char_u *op;
|
||||
char_u *next;
|
||||
@@ -2530,7 +2530,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
int ppconst_used = ppconst->pp_used;
|
||||
|
||||
// get the first variable
|
||||
if (compile_expr6(arg, cctx, ppconst) == FAIL)
|
||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
@@ -2562,7 +2562,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return FAIL;
|
||||
|
||||
// get the second expression
|
||||
if (compile_expr6(arg, cctx, ppconst) == FAIL)
|
||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (ppconst->pp_used == ppconst_used + 2
|
||||
@@ -2620,6 +2620,136 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* expr6a >> expr6b
|
||||
* expr6a << expr6b
|
||||
*
|
||||
* Produces instructions:
|
||||
* OPNR bitwise left or right shift
|
||||
*/
|
||||
static int
|
||||
compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
exprtype_T type = EXPR_UNKNOWN;
|
||||
char_u *p;
|
||||
char_u *next;
|
||||
int len = 2;
|
||||
int ppconst_used = ppconst->pp_used;
|
||||
typval_T *tv1;
|
||||
typval_T *tv2;
|
||||
isn_T *isn;
|
||||
|
||||
// get the first variable
|
||||
if (compile_expr6(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
* Repeat computing, until no "+", "-" or ".." is following.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
type = EXPR_UNKNOWN;
|
||||
|
||||
p = may_peek_next_line(cctx, *arg, &next);
|
||||
if (p[0] == '<' && p[1] == '<')
|
||||
type = EXPR_LSHIFT;
|
||||
else if (p[0] == '>' && p[1] == '>')
|
||||
type = EXPR_RSHIFT;
|
||||
|
||||
if (type == EXPR_UNKNOWN)
|
||||
return OK;
|
||||
|
||||
// Handle a bitwise left or right shift operator
|
||||
if (ppconst->pp_used == ppconst_used + 1)
|
||||
{
|
||||
tv1 = &ppconst->pp_tv[ppconst->pp_used - 1];
|
||||
if (tv1->v_type != VAR_NUMBER)
|
||||
{
|
||||
// left operand should be a number
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type_T *t = get_type_on_stack(cctx, 0);
|
||||
|
||||
if (need_type(t, &t_number, 0, 0, cctx, FALSE, FALSE) == FAIL)
|
||||
{
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (next != NULL)
|
||||
{
|
||||
*arg = next_line_from_context(cctx, TRUE);
|
||||
p = skipwhite(*arg);
|
||||
}
|
||||
|
||||
if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
|
||||
{
|
||||
error_white_both(p, len);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// get the second variable
|
||||
if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (compile_expr6(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (ppconst->pp_used == ppconst_used + 2)
|
||||
{
|
||||
// Both sides are a constant, compute the result now.
|
||||
tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
|
||||
if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
|
||||
{
|
||||
// right operand should be a positive number
|
||||
if (tv2->v_type != VAR_NUMBER)
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
else
|
||||
emsg(_(e_bitshift_ops_must_be_postive));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (tv2->vval.v_number > MAX_LSHIFT_BITS)
|
||||
tv1->vval.v_number = 0;
|
||||
else if (type == EXPR_LSHIFT)
|
||||
tv1->vval.v_number = tv1->vval.v_number << tv2->vval.v_number;
|
||||
else
|
||||
{
|
||||
tv1->vval.v_number = tv1->vval.v_number >> tv2->vval.v_number;
|
||||
// clear the topmost sign bit
|
||||
tv1->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
|
||||
}
|
||||
clear_tv(tv2);
|
||||
--ppconst->pp_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (need_type(get_type_on_stack(cctx, 0), &t_number, 0, 0, cctx,
|
||||
FALSE, FALSE) == FAIL)
|
||||
{
|
||||
emsg(_(e_bitshift_ops_must_be_number));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
generate_ppconst(cctx, ppconst);
|
||||
|
||||
isn = generate_instr_drop(cctx, ISN_OPNR, 1);
|
||||
if (isn == NULL)
|
||||
return FAIL;
|
||||
|
||||
if (isn != NULL)
|
||||
isn->isn_arg.op.op_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* expr5a == expr5b
|
||||
* expr5a =~ expr5b
|
||||
@@ -2652,6 +2782,7 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
return FAIL;
|
||||
|
||||
p = may_peek_next_line(cctx, *arg, &next);
|
||||
|
||||
type = get_compare_type(p, &len, &type_is);
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user