summaryrefslogtreecommitdiff
path: root/src/vim9compile.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-12-10 19:43:40 +0100
committerBram Moolenaar <Bram@vim.org>2020-12-10 19:43:40 +0100
commit08597875b2a1e7d118b0346c652a96e7527e7d8b (patch)
tree0bb1d04eadfe4110a7962e9fcbfd361452677205 /src/vim9compile.c
parentd356fc65d273959efa9b05bfa0f07ce1c9ff85a4 (diff)
downloadvim-git-08597875b2a1e7d118b0346c652a96e7527e7d8b.tar.gz
patch 8.2.2124: Vim9: a range cannot be computed at runtimev8.2.2124
Problem: Vim9: a range cannot be computed at runtime. Solution: Add the ISN_RANGE instruction.
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r--src/vim9compile.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c
index da069f405..ac8fb846a 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1888,6 +1888,26 @@ generate_EXECCONCAT(cctx_T *cctx, int count)
return OK;
}
+/*
+ * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
+ */
+ static int
+generate_RANGE(cctx_T *cctx, char_u *range)
+{
+ isn_T *isn;
+ garray_T *stack = &cctx->ctx_type_stack;
+
+ if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
+ return FAIL;
+ isn->isn_arg.string = range;
+
+ if (ga_grow(stack, 1) == FAIL)
+ return FAIL;
+ ((type_T **)stack->ga_data)[stack->ga_len] = &t_number;
+ ++stack->ga_len;
+ return OK;
+}
+
static int
generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
{
@@ -7099,6 +7119,22 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
}
/*
+ * If "eap" has a range that is not a contstant generate an ISN_RANGE
+ * instruction to compute it and return OK.
+ * Otherwise return FAIL, the caller must deal with any range.
+ */
+ static int
+compile_variable_range(exarg_T *eap, cctx_T *cctx)
+{
+ char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
+ char_u *p = skipdigits(eap->cmd);
+
+ if (p == range_end)
+ return FAIL;
+ return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
+}
+
+/*
* :put r
* :put ={expr}
*/
@@ -7123,17 +7159,23 @@ compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
else if (eap->regname != NUL)
++line;
- // "errormsg" will not be set because the range is ADDR_LINES.
- // TODO: if the range contains something like "$" or "." need to evaluate
- // at runtime
- if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
- return NULL;
- if (eap->addr_count == 0)
- lnum = -1;
+ if (compile_variable_range(eap, cctx) == OK)
+ {
+ lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
+ }
else
- lnum = eap->line2;
- if (above)
- --lnum;
+ {
+ // Either no range or a number.
+ // "errormsg" will not be set because the range is ADDR_LINES.
+ if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
+ return NULL;
+ if (eap->addr_count == 0)
+ lnum = -1;
+ else
+ lnum = eap->line2;
+ if (above)
+ --lnum;
+ }
generate_PUT(cctx, eap->regname, lnum);
return line;
@@ -7960,6 +8002,7 @@ delete_instr(isn_T *isn)
case ISN_PUSHEXC:
case ISN_PUSHFUNC:
case ISN_PUSHS:
+ case ISN_RANGE:
case ISN_STOREB:
case ISN_STOREENV:
case ISN_STOREG: