0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

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.
This commit is contained in:
Bram Moolenaar
2020-05-10 19:10:31 +02:00
parent 89483d4043
commit 1cc2a94f80
8 changed files with 465 additions and 169 deletions

View File

@@ -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;
// dict member with string key
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_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;