summaryrefslogtreecommitdiff
path: root/src/list.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-12 20:23:40 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-12 20:23:40 +0100
commitb0e6b513648db7035046613431a4aa9d71ef4653 (patch)
treeed9c3fdd71d7c70c7289f0e48a88296067e21352 /src/list.c
parent7cd24227c02afdb4249db406e2174eda1e6b36b4 (diff)
downloadvim-git-b0e6b513648db7035046613431a4aa9d71ef4653.tar.gz
patch 8.2.2336: Vim9: not possible to extend dictionary with different typev8.2.2336
Problem: Vim9: it is not possible to extend a dictionary with different item types. Solution: Add extendnew(). (closes #7666)
Diffstat (limited to 'src/list.c')
-rw-r--r--src/list.c73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/list.c b/src/list.c
index 2b44ebacb..f7842fa87 100644
--- a/src/list.c
+++ b/src/list.c
@@ -2454,14 +2454,11 @@ f_count(typval_T *argvars, typval_T *rettv)
}
/*
- * "extend(list, list [, idx])" function
- * "extend(dict, dict [, action])" function
+ * "extend()" or "extendnew()" function. "is_new" is TRUE for extendnew().
*/
- void
-f_extend(typval_T *argvars, typval_T *rettv)
+ static void
+extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
{
- char_u *arg_errmsg = (char_u *)N_("extend() argument");
-
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
{
list_T *l1, *l2;
@@ -2476,8 +2473,16 @@ f_extend(typval_T *argvars, typval_T *rettv)
return;
}
l2 = argvars[1].vval.v_list;
- if (!value_check_lock(l1->lv_lock, arg_errmsg, TRUE) && l2 != NULL)
+ if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
+ && l2 != NULL)
{
+ if (is_new)
+ {
+ l1 = list_copy(l1, FALSE, get_copyID());
+ if (l1 == NULL)
+ return;
+ }
+
if (argvars[2].v_type != VAR_UNKNOWN)
{
before = (long)tv_get_number_chk(&argvars[2], &error);
@@ -2500,7 +2505,14 @@ f_extend(typval_T *argvars, typval_T *rettv)
item = NULL;
list_extend(l1, l2, item);
- copy_tv(&argvars[0], rettv);
+ if (is_new)
+ {
+ rettv->v_type = VAR_LIST;
+ rettv->vval.v_list = l1;
+ rettv->v_lock = FALSE;
+ }
+ else
+ copy_tv(&argvars[0], rettv);
}
}
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
@@ -2516,8 +2528,16 @@ f_extend(typval_T *argvars, typval_T *rettv)
return;
}
d2 = argvars[1].vval.v_dict;
- if (!value_check_lock(d1->dv_lock, arg_errmsg, TRUE) && d2 != NULL)
+ if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
+ && d2 != NULL)
{
+ if (is_new)
+ {
+ d1 = dict_copy(d1, FALSE, get_copyID());
+ if (d1 == NULL)
+ return;
+ }
+
// Check the third argument.
if (argvars[2].v_type != VAR_UNKNOWN)
{
@@ -2540,11 +2560,42 @@ f_extend(typval_T *argvars, typval_T *rettv)
dict_extend(d1, d2, action);
- copy_tv(&argvars[0], rettv);
+ if (is_new)
+ {
+ rettv->v_type = VAR_DICT;
+ rettv->vval.v_dict = d1;
+ rettv->v_lock = FALSE;
+ }
+ else
+ copy_tv(&argvars[0], rettv);
}
}
else
- semsg(_(e_listdictarg), "extend()");
+ semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
+}
+
+/*
+ * "extend(list, list [, idx])" function
+ * "extend(dict, dict [, action])" function
+ */
+ void
+f_extend(typval_T *argvars, typval_T *rettv)
+{
+ char_u *errmsg = (char_u *)N_("extend() argument");
+
+ extend(argvars, rettv, errmsg, FALSE);
+}
+
+/*
+ * "extendnew(list, list [, idx])" function
+ * "extendnew(dict, dict [, action])" function
+ */
+ void
+f_extendnew(typval_T *argvars, typval_T *rettv)
+{
+ char_u *errmsg = (char_u *)N_("extendnew() argument");
+
+ extend(argvars, rettv, errmsg, TRUE);
}
/*