diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-10-19 19:02:42 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-10-19 19:02:42 +0200 |
commit | 1dcae59957301b6b19aef49af648715f911a1378 (patch) | |
tree | a4d330ebc6eebc410e845a421844950c2f38d84f /src/vim9compile.c | |
parent | 334a8b4bde55e1095533f70616ac1e6ec337c62c (diff) | |
download | vim-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.c | 47 |
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: |