patch 9.1.1232: Vim script is missing the tuple data type
Problem: Vim script is missing the tuple data type
Solution: Add support for the tuple data type
(Yegappan Lakshmanan)
closes: #16776
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/typval.c b/src/typval.c
index cd39a0d..59ac611 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -72,6 +72,9 @@
case VAR_LIST:
list_unref(varp->vval.v_list);
break;
+ case VAR_TUPLE:
+ tuple_unref(varp->vval.v_tuple);
+ break;
case VAR_DICT:
dict_unref(varp->vval.v_dict);
break;
@@ -138,6 +141,10 @@
list_unref(varp->vval.v_list);
varp->vval.v_list = NULL;
break;
+ case VAR_TUPLE:
+ tuple_unref(varp->vval.v_tuple);
+ varp->vval.v_tuple = NULL;
+ break;
case VAR_DICT:
dict_unref(varp->vval.v_dict);
varp->vval.v_dict = NULL;
@@ -234,6 +241,9 @@
case VAR_LIST:
emsg(_(e_using_list_as_number));
break;
+ case VAR_TUPLE:
+ emsg(_(e_using_tuple_as_number));
+ break;
case VAR_DICT:
emsg(_(e_using_dictionary_as_number));
break;
@@ -368,6 +378,9 @@
case VAR_LIST:
emsg(_(e_using_list_as_float));
break;
+ case VAR_TUPLE:
+ emsg(_(e_using_tuple_as_float));
+ break;
case VAR_DICT:
emsg(_(e_using_dictionary_as_float));
break;
@@ -529,7 +542,7 @@
/*
* Give an error and return FAIL unless "args[idx]" is a bool or a number.
*/
- int
+ static int
check_for_bool_or_number_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_BOOL && args[idx].v_type != VAR_NUMBER)
@@ -620,6 +633,20 @@
}
/*
+ * Give an error and return FAIL unless "args[idx]" is a tuple.
+ */
+ int
+check_for_tuple_arg(typval_T *args, int idx)
+{
+ if (args[idx].v_type != VAR_TUPLE)
+ {
+ semsg(_(e_tuple_required_for_argument_nr), idx + 1);
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
* Give an error and return FAIL unless "args[idx]" is a dict.
*/
int
@@ -827,17 +854,18 @@
}
/*
- * Give an error and return FAIL unless "args[idx]" is a string, a list or a
- * blob.
+ * Give an error and return FAIL unless "args[idx]" is a string, a list, a
+ * tuple or a blob.
*/
int
-check_for_string_or_list_or_blob_arg(typval_T *args, int idx)
+check_for_string_or_list_or_tuple_or_blob_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_STRING
&& args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
&& args[idx].v_type != VAR_BLOB)
{
- semsg(_(e_string_list_or_blob_required_for_argument_nr), idx + 1);
+ semsg(_(e_string_list_tuple_or_blob_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
@@ -897,35 +925,37 @@
}
/*
- * Give an error and return FAIL unless "args[idx]" is a string or a number
- * or a list or a blob.
+ * Give an error and return FAIL unless "args[idx]" is a string, a number, a
+ * list, a tuple or a blob.
*/
int
-check_for_string_or_number_or_list_or_blob_arg(typval_T *args, int idx)
+check_for_repeat_func_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_STRING
&& args[idx].v_type != VAR_NUMBER
&& args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
&& args[idx].v_type != VAR_BLOB)
{
- semsg(_(e_string_number_list_or_blob_required_for_argument_nr), idx + 1);
+ semsg(_(e_repeatable_type_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
/*
- * Give an error and return FAIL unless "args[idx]" is a string or a list
- * or a dict.
+ * Give an error and return FAIL unless "args[idx]" is a string, a list, a
+ * tuple or a dict.
*/
int
-check_for_string_or_list_or_dict_arg(typval_T *args, int idx)
+check_for_string_list_tuple_or_dict_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_STRING
&& args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
&& args[idx].v_type != VAR_DICT)
{
- semsg(_(e_string_list_or_dict_required_for_argument_nr), idx + 1);
+ semsg(_(e_string_list_tuple_or_dict_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
@@ -963,15 +993,48 @@
}
/*
- * Give an error and return FAIL unless "args[idx]" is a list or dict
+ * Give an error and return FAIL unless "args[idx]" is a list or a tuple.
*/
int
-check_for_list_or_dict_arg(typval_T *args, int idx)
+check_for_list_or_tuple_arg(typval_T *args, int idx)
+{
+ if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_TUPLE)
+ {
+ semsg(_(e_list_or_tuple_required_for_argument_nr), idx + 1);
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Give an error and return FAIL unless "args[idx]" is a list, a tuple or a
+ * blob.
+ */
+ int
+check_for_list_or_tuple_or_blob_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
+ && args[idx].v_type != VAR_BLOB)
+ {
+ semsg(_(e_list_or_tuple_or_blob_required_for_argument_nr), idx + 1);
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Give an error and return FAIL unless "args[idx]" is a list, a tuple or a
+ * dict
+ */
+ int
+check_for_list_or_tuple_or_dict_arg(typval_T *args, int idx)
+{
+ if (args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
&& args[idx].v_type != VAR_DICT)
{
- semsg(_(e_list_or_dict_required_for_argument_nr), idx + 1);
+ semsg(_(e_list_or_tuple_or_dict_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
@@ -995,18 +1058,19 @@
}
/*
- * Give an error and return FAIL unless "args[idx]" is a list or dict or a
- * blob or a string.
+ * Give an error and return FAIL unless "args[idx]" is a list, a tuple, a dict,
+ * a blob or a string.
*/
int
-check_for_list_or_dict_or_blob_or_string_arg(typval_T *args, int idx)
+check_for_list_tuple_dict_blob_or_string_arg(typval_T *args, int idx)
{
if (args[idx].v_type != VAR_LIST
+ && args[idx].v_type != VAR_TUPLE
&& args[idx].v_type != VAR_DICT
&& args[idx].v_type != VAR_BLOB
&& args[idx].v_type != VAR_STRING)
{
- semsg(_(e_list_dict_blob_or_string_required_for_argument_nr), idx + 1);
+ semsg(_(e_list_tuple_dict_blob_or_string_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
@@ -1149,6 +1213,9 @@
case VAR_LIST:
emsg(_(e_using_list_as_string));
break;
+ case VAR_TUPLE:
+ emsg(_(e_using_tuple_as_string));
+ break;
case VAR_DICT:
emsg(_(e_using_dictionary_as_string));
break;
@@ -1267,6 +1334,10 @@
if (tv->vval.v_list != NULL)
lock = tv->vval.v_list->lv_lock;
break;
+ case VAR_TUPLE:
+ if (tv->vval.v_tuple != NULL)
+ lock = tv->vval.v_tuple->tv_lock;
+ break;
case VAR_DICT:
if (tv->vval.v_dict != NULL)
lock = tv->vval.v_dict->dv_lock;
@@ -1364,6 +1435,15 @@
++to->vval.v_list->lv_refcount;
}
break;
+ case VAR_TUPLE:
+ if (from->vval.v_tuple == NULL)
+ to->vval.v_tuple = NULL;
+ else
+ {
+ to->vval.v_tuple = from->vval.v_tuple;
+ ++to->vval.v_tuple->tv_refcount;
+ }
+ break;
case VAR_DICT:
if (from->vval.v_dict == NULL)
to->vval.v_dict = NULL;
@@ -1452,6 +1532,15 @@
}
n1 = res;
}
+ else if (tv1->v_type == VAR_TUPLE || tv2->v_type == VAR_TUPLE)
+ {
+ if (typval_compare_tuple(tv1, tv2, type, ic, &res) == FAIL)
+ {
+ clear_tv(tv1);
+ return FAIL;
+ }
+ n1 = res;
+ }
else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
{
if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
@@ -1650,6 +1739,47 @@
}
/*
+ * Compare "tv1" to "tv2" as tuples according to "type" and "ic".
+ * Put the result, false or true, in "res".
+ * Return FAIL and give an error message when the comparison can't be done.
+ */
+ int
+typval_compare_tuple(
+ typval_T *tv1,
+ typval_T *tv2,
+ exprtype_T type,
+ int ic,
+ int *res)
+{
+ int val = 0;
+
+ if (type == EXPR_IS || type == EXPR_ISNOT)
+ {
+ val = (tv1->v_type == tv2->v_type
+ && tv1->vval.v_tuple == tv2->vval.v_tuple);
+ if (type == EXPR_ISNOT)
+ val = !val;
+ }
+ else if (tv1->v_type != tv2->v_type
+ || (type != EXPR_EQUAL && type != EXPR_NEQUAL))
+ {
+ if (tv1->v_type != tv2->v_type)
+ emsg(_(e_can_only_compare_tuple_with_tuple));
+ else
+ emsg(_(e_invalid_operation_for_tuple));
+ return FAIL;
+ }
+ else
+ {
+ val = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
+ if (type == EXPR_NEQUAL)
+ val = !val;
+ }
+ *res = val;
+ return OK;
+}
+
+/*
* Compare v:null with another type. Return TRUE if the value is NULL.
*/
int
@@ -1674,6 +1804,7 @@
case VAR_JOB: return tv->vval.v_job == NULL;
#endif
case VAR_LIST: return tv->vval.v_list == NULL;
+ case VAR_TUPLE: return tv->vval.v_tuple == NULL;
case VAR_OBJECT: return tv->vval.v_object == NULL;
case VAR_PARTIAL: return tv->vval.v_partial == NULL;
case VAR_STRING: return tv->vval.v_string == NULL;
@@ -2078,6 +2209,12 @@
--recursive_cnt;
return r;
+ case VAR_TUPLE:
+ ++recursive_cnt;
+ r = tuple_equal(tv1->vval.v_tuple, tv2->vval.v_tuple, ic);
+ --recursive_cnt;
+ return r;
+
case VAR_DICT:
++recursive_cnt;
r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);