summaryrefslogtreecommitdiff
path: root/src/vim9expr.c
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-05-22 19:13:49 +0100
committerBram Moolenaar <Bram@vim.org>2022-05-22 19:13:49 +0100
commita061f34191712df7dde7716705fe0ec074e9758e (patch)
treef8a3bf02c826aeb748d12bfa74ead3e9f74573a2 /src/vim9expr.c
parent9b2edfd3bf2f14a1faaee9b62930598a2e77a798 (diff)
downloadvim-git-a061f34191712df7dde7716705fe0ec074e9758e.tar.gz
patch 8.2.5003: cannot do bitwise shiftsv8.2.5003
Problem: Cannot do bitwise shifts. Solution: Add the >> and << operators. (Yegappan Lakshmanan, closes #8457)
Diffstat (limited to 'src/vim9expr.c')
-rw-r--r--src/vim9expr.c155
1 files changed, 143 insertions, 12 deletions
diff --git a/src/vim9expr.c b/src/vim9expr.c
index eaea089f9..c84be874a 100644
--- a/src/vim9expr.c
+++ b/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
@@ -2621,6 +2621,136 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
}
/*
+ * 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
* 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);
/*