Mercurial > vim
diff src/vim9execute.c @ 20349:e29b2ec8d4d2 v8.2.0730
patch 8.2.0730: Vim9: Assignment to dict member does not work
Commit: https://github.com/vim/vim/commit/1cc2a94f80ba982f83d1e2d37c4726867e36bd9f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun May 10 19:10:31 2020 +0200
patch 8.2.0730: Vim9: Assignment to dict member does not work
Problem: Vim9: Assignment to dict member does not work.
Solution: Parse dict assignment. Implement getting dict member.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 10 May 2020 19:15:03 +0200 |
parents | cf2620e7a6aa |
children | a8a76fd967ab |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1252,6 +1252,76 @@ call_def_function( tv->vval.v_number = iptr->isn_arg.storenr.stnr_val; break; + // store value in list variable + case ISN_STORELIST: + { + typval_T *tv_idx = STACK_TV_BOT(-2); + varnumber_T lidx = tv_idx->vval.v_number; + typval_T *tv_list = STACK_TV_BOT(-1); + list_T *list = tv_list->vval.v_list; + + if (lidx < 0 && list->lv_len + lidx >= 0) + // negative index is relative to the end + lidx = list->lv_len + lidx; + if (lidx < 0 || lidx > list->lv_len) + { + semsg(_(e_listidx), lidx); + goto failed; + } + tv = STACK_TV_BOT(-3); + if (lidx < list->lv_len) + { + listitem_T *li = list_find(list, lidx); + + // overwrite existing list item + clear_tv(&li->li_tv); + li->li_tv = *tv; + } + else + { + // append to list + if (list_append_tv(list, tv) == FAIL) + goto failed; + clear_tv(tv); + } + clear_tv(tv_idx); + clear_tv(tv_list); + } + break; + + // store value in dict variable + case ISN_STOREDICT: + { + typval_T *tv_key = STACK_TV_BOT(-2); + char_u *key = tv_key->vval.v_string; + typval_T *tv_dict = STACK_TV_BOT(-1); + dict_T *dict = tv_dict->vval.v_dict; + dictitem_T *di; + + if (key == NULL || *key == NUL) + { + emsg(_(e_emptykey)); + goto failed; + } + tv = STACK_TV_BOT(-3); + di = dict_find(dict, key, -1); + if (di != NULL) + { + clear_tv(&di->di_tv); + di->di_tv = *tv; + } + else + { + // add to dict + if (dict_add_tv(dict, (char *)key, tv) == FAIL) + goto failed; + clear_tv(tv); + } + clear_tv(tv_key); + clear_tv(tv_dict); + } + break; + // push constant case ISN_PUSHNR: case ISN_PUSHBOOL: @@ -2019,8 +2089,42 @@ call_def_function( } break; + case ISN_MEMBER: + { + dict_T *dict; + char_u *key; + dictitem_T *di; + + // dict member: dict is at stack-2, key at stack-1 + tv = STACK_TV_BOT(-2); + if (tv->v_type != VAR_DICT) + { + emsg(_(e_dictreq)); + goto failed; + } + dict = tv->vval.v_dict; + + tv = STACK_TV_BOT(-1); + if (tv->v_type != VAR_STRING) + { + emsg(_(e_stringreq)); + goto failed; + } + key = tv->vval.v_string; + if ((di = dict_find(dict, key, -1)) == NULL) + { + semsg(_(e_dictkey), key); + goto failed; + } + --ectx.ec_stack.ga_len; + clear_tv(tv); + clear_tv(STACK_TV_BOT(-1)); + copy_tv(&di->di_tv, STACK_TV_BOT(-1)); + } + break; + // dict member with string key - case ISN_MEMBER: + case ISN_STRINGMEMBER: { dict_T *dict; dictitem_T *di; @@ -2380,6 +2484,14 @@ ex_disassemble(exarg_T *eap) iptr->isn_arg.storenr.stnr_idx); break; + case ISN_STORELIST: + smsg("%4d STORELIST", current); + break; + + case ISN_STOREDICT: + smsg("%4d STOREDICT", current); + break; + // constants case ISN_PUSHNR: smsg("%4d PUSHNR %lld", current, @@ -2656,7 +2768,8 @@ ex_disassemble(exarg_T *eap) // expression operations case ISN_CONCAT: smsg("%4d CONCAT", current); break; case ISN_INDEX: smsg("%4d INDEX", current); break; - case ISN_MEMBER: smsg("%4d MEMBER %s", current, + case ISN_MEMBER: smsg("%4d MEMBER", current); break; + case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current, iptr->isn_arg.string); break; case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;