Mercurial > vim
diff src/vim9execute.c @ 23517:36bf9a6fbd4c v8.2.2301
patch 8.2.2301: Vim9: cannot unlet a dict or list item
Commit: https://github.com/vim/vim/commit/752fc692ace51459cb407ec117c147b3bbebc071
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Jan 4 21:57:11 2021 +0100
patch 8.2.2301: Vim9: cannot unlet a dict or list item
Problem: Vim9: cannot unlet a dict or list item.
Solution: Add ISN_UNLETINDEX. Refactor assignment code to use for unlet.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 04 Jan 2021 22:00:04 +0100 |
parents | 872239543313 |
children | b0a6e7325169 |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1783,6 +1783,10 @@ call_def_function( typval_T *tv_dest = STACK_TV_BOT(-1); int status = OK; + // Stack contains: + // -3 value to be stored + // -2 index + // -1 dict or list tv = STACK_TV_BOT(-3); SOURCING_LNUM = iptr->isn_lnum; if (dest_type == VAR_ANY) @@ -1898,6 +1902,91 @@ call_def_function( } break; + // unlet item in list or dict variable + case ISN_UNLETINDEX: + { + typval_T *tv_idx = STACK_TV_BOT(-2); + typval_T *tv_dest = STACK_TV_BOT(-1); + int status = OK; + + // Stack contains: + // -2 index + // -1 dict or list + if (tv_dest->v_type == VAR_DICT) + { + // unlet a dict item, index must be a string + if (tv_idx->v_type != VAR_STRING) + { + semsg(_(e_expected_str_but_got_str), + vartype_name(VAR_STRING), + vartype_name(tv_idx->v_type)); + status = FAIL; + } + else + { + dict_T *d = tv_dest->vval.v_dict; + char_u *key = tv_idx->vval.v_string; + dictitem_T *di = NULL; + + if (key == NULL) + key = (char_u *)""; + if (d != NULL) + di = dict_find(d, key, (int)STRLEN(key)); + if (di == NULL) + { + // NULL dict is equivalent to empty dict + semsg(_(e_dictkey), key); + status = FAIL; + } + else + { + // TODO: check for dict or item locked + dictitem_remove(d, di); + } + } + } + else if (tv_dest->v_type == VAR_LIST) + { + // unlet a List item, index must be a number + if (tv_idx->v_type != VAR_NUMBER) + { + semsg(_(e_expected_str_but_got_str), + vartype_name(VAR_NUMBER), + vartype_name(tv_idx->v_type)); + status = FAIL; + } + else + { + list_T *l = tv_dest->vval.v_list; + varnumber_T n = tv_idx->vval.v_number; + listitem_T *li = NULL; + + li = list_find(l, n); + if (li == NULL) + { + semsg(_(e_listidx), n); + status = FAIL; + } + else + // TODO: check for list or item locked + listitem_remove(l, li); + } + } + else + { + status = FAIL; + semsg(_(e_cannot_index_str), + vartype_name(tv_dest->v_type)); + } + + clear_tv(tv_idx); + clear_tv(tv_dest); + ectx.ec_stack.ga_len -= 2; + if (status == FAIL) + goto on_error; + } + break; + // push constant case ISN_PUSHNR: case ISN_PUSHBOOL: @@ -3649,6 +3738,9 @@ ex_disassemble(exarg_T *eap) iptr->isn_arg.unlet.ul_forceit ? "!" : "", iptr->isn_arg.unlet.ul_name); break; + case ISN_UNLETINDEX: + smsg("%4d UNLETINDEX", current); + break; case ISN_LOCKCONST: smsg("%4d LOCKCONST", current); break;