summaryrefslogtreecommitdiff
path: root/src/vim9compile.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-10-19 19:02:42 +0200
committerBram Moolenaar <Bram@vim.org>2020-10-19 19:02:42 +0200
commit1dcae59957301b6b19aef49af648715f911a1378 (patch)
treea4d330ebc6eebc410e845a421844950c2f38d84f /src/vim9compile.c
parent334a8b4bde55e1095533f70616ac1e6ec337c62c (diff)
downloadvim-git-1dcae59957301b6b19aef49af648715f911a1378.tar.gz
patch 8.2.1865: Vim9: add() does not check type of argumentv8.2.1865
Problem: Vim9: add() does not check type of argument. Solution: Inline the add() call. (closes #7160)
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r--src/vim9compile.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c
index a891006f9..bb4807eeb 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1495,6 +1495,32 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
}
/*
+ * Generate an ISN_LISTAPPEND instruction. Works like add().
+ * Argument count is already checked.
+ */
+ static int
+generate_LISTAPPEND(cctx_T *cctx)
+{
+ garray_T *stack = &cctx->ctx_type_stack;
+ type_T *list_type;
+ type_T *item_type;
+ type_T *expected;
+
+ // Caller already checked that list_type is a list.
+ list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
+ item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+ expected = list_type->tt_member;
+ if (need_type(item_type, expected, -1, cctx, FALSE, FALSE) == FAIL)
+ return FAIL;
+
+ if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
+ return FAIL;
+
+ --stack->ga_len; // drop the argument
+ return OK;
+}
+
+/*
* Generate an ISN_DCALL or ISN_UCALL instruction.
* Return FAIL if the number of arguments is wrong.
*/
@@ -2537,7 +2563,25 @@ compile_call(
// builtin function
idx = find_internal_func(name);
if (idx >= 0)
- res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
+ {
+ if (STRCMP(name, "add") == 0 && argcount == 2)
+ {
+ garray_T *stack = &cctx->ctx_type_stack;
+ type_T *type = ((type_T **)stack->ga_data)[
+ stack->ga_len - 2];
+
+ // TODO: also check for VAR_BLOB
+ if (type->tt_type == VAR_LIST)
+ {
+ // inline "add(list, item)" so that the type can be checked
+ res = generate_LISTAPPEND(cctx);
+ idx = -1;
+ }
+ }
+
+ if (idx >= 0)
+ res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
+ }
else
semsg(_(e_unknownfunc), namebuf);
goto theend;
@@ -7656,6 +7700,7 @@ delete_instr(isn_T *isn)
case ISN_FOR:
case ISN_GETITEM:
case ISN_JUMP:
+ case ISN_LISTAPPEND:
case ISN_LISTINDEX:
case ISN_LISTSLICE:
case ISN_LOAD: