patch 8.2.2124: Vim9: a range cannot be computed at runtime
Problem: Vim9: a range cannot be computed at runtime.
Solution: Add the ISN_RANGE instruction.
diff --git a/src/vim9compile.c b/src/vim9compile.c
index da069f4..ac8fb84 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1888,6 +1888,26 @@
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 @@
}
/*
+ * 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 @@
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 @@
case ISN_PUSHEXC:
case ISN_PUSHFUNC:
case ISN_PUSHS:
+ case ISN_RANGE:
case ISN_STOREB:
case ISN_STOREENV:
case ISN_STOREG: