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/proto/eval.pro b/src/proto/eval.pro
index e945a28..df59383 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -45,6 +45,7 @@
 int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
 void eval_addblob(typval_T *tv1, typval_T *tv2);
 int eval_addlist(typval_T *tv1, typval_T *tv2);
+int eval_addtuple(typval_T *tv1, typval_T *tv2);
 int eval_leader(char_u **arg, int vim9);
 int handle_predefined(char_u *s, int len, typval_T *rettv);
 int check_can_index(typval_T *rettv, int evaluate, int verbose);
diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro
index a720b64..627af17 100644
--- a/src/proto/evalfunc.pro
+++ b/src/proto/evalfunc.pro
@@ -23,6 +23,7 @@
 void f_exists(typval_T *argvars, typval_T *rettv);
 void f_has(typval_T *argvars, typval_T *rettv);
 int dynamic_feature(char_u *feature);
+int indexof_eval_expr(typval_T *expr);
 void f_len(typval_T *argvars, typval_T *rettv);
 void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 void range_list_materialize(list_T *list);
diff --git a/src/proto/gc.pro b/src/proto/gc.pro
index e13dbda..8b55030 100644
--- a/src/proto/gc.pro
+++ b/src/proto/gc.pro
@@ -1,12 +1,12 @@
 /* gc.c */
 int get_copyID(void);
 int garbage_collect(int testing);
-int set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack);
+int set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack, tuple_stack_T **tuple_stack);
 int set_ref_in_dict(dict_T *d, int copyID);
 int set_ref_in_list(list_T *ll, int copyID);
-int set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack);
+int set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack, tuple_stack_T **tuple_stack);
+int set_ref_in_tuple_items(tuple_T *tuple, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack);
 int set_ref_in_callback(callback_T *cb, int copyID);
-int set_ref_in_item_class(class_T *cl, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack);
-int set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack);
+int set_ref_in_item_class(class_T *cl, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack, tuple_stack_T **tuple_stack);
+int set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack, tuple_stack_T **tuple_stack);
 /* vim: set ft=c : */
-
diff --git a/src/proto/list.pro b/src/proto/list.pro
index 27bea5e..cb05203 100644
--- a/src/proto/list.pro
+++ b/src/proto/list.pro
@@ -50,6 +50,8 @@
 int write_list(FILE *fd, list_T *list, int binary);
 void init_static_list(staticList10_T *sl);
 void f_list2str(typval_T *argvars, typval_T *rettv);
+void f_list2tuple(typval_T *argvars, typval_T *rettv);
+void f_tuple2list(typval_T *argvars, typval_T *rettv);
 void f_sort(typval_T *argvars, typval_T *rettv);
 void f_uniq(typval_T *argvars, typval_T *rettv);
 int filter_map_one(typval_T *tv, typval_T *expr, filtermap_T filtermap, funccall_T *fc, typval_T *newtv, int *remp);
diff --git a/src/proto/testing.pro b/src/proto/testing.pro
index dea4f75..1c93f8c 100644
--- a/src/proto/testing.pro
+++ b/src/proto/testing.pro
@@ -30,6 +30,7 @@
 void f_test_null_function(typval_T *argvars, typval_T *rettv);
 void f_test_null_partial(typval_T *argvars, typval_T *rettv);
 void f_test_null_string(typval_T *argvars, typval_T *rettv);
+void f_test_null_tuple(typval_T *argvars, typval_T *rettv);
 void f_test_unknown(typval_T *argvars, typval_T *rettv);
 void f_test_void(typval_T *argvars, typval_T *rettv);
 void f_test_setmouse(typval_T *argvars, typval_T *rettv);
diff --git a/src/proto/tuple.pro b/src/proto/tuple.pro
new file mode 100644
index 0000000..138648d
--- /dev/null
+++ b/src/proto/tuple.pro
@@ -0,0 +1,34 @@
+/* tuple.c */
+tuple_T *tuple_alloc(void);
+tuple_T *tuple_alloc_with_items(int count);
+void tuple_set_item(tuple_T *tuple, int idx, typval_T *tv);
+int rettv_tuple_alloc(typval_T *rettv);
+void rettv_tuple_set(typval_T *rettv, tuple_T *tuple);
+int rettv_tuple_set_with_items(typval_T *rettv, int count);
+void tuple_unref(tuple_T *tuple);
+int tuple_free_nonref(int copyID);
+void tuple_free_items(int copyID);
+void tuple_free(tuple_T *tuple);
+long tuple_len(tuple_T *tuple);
+int tuple_equal(tuple_T *t1, tuple_T *t2, int ic);
+typval_T *tuple_find(tuple_T *tuple, long n);
+int tuple_append_tv(tuple_T *tuple, typval_T *tv);
+int tuple_concat(tuple_T *t1, tuple_T *t2, typval_T *tv);
+tuple_T *tuple_slice(tuple_T *tuple, long n1, long n2);
+int tuple_slice_or_index(tuple_T *tuple, int range, varnumber_T n1_arg, varnumber_T n2_arg, int exclusive, typval_T *rettv, int verbose);
+tuple_T *tuple_copy(tuple_T *orig, int deep, int top, int copyID);
+int eval_tuple(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error);
+void tuple_lock(tuple_T *tuple, int deep, int lock, int check_refcount);
+int tuple_join(garray_T *gap, tuple_T *tuple, char_u *sep, int echo_style, int restore_copyID, int copyID);
+char_u *tuple2string(typval_T *tv, int copyID, int restore_copyID);
+void tuple_foreach(tuple_T *tuple, filtermap_T filtermap, typval_T *expr);
+long tuple_count(tuple_T *tuple, typval_T *needle, long idx, int ic);
+void tuple2items(typval_T *argvars, typval_T *rettv);
+int index_tuple(tuple_T *tuple, typval_T *tv, int start_idx, int ic);
+int indexof_tuple(tuple_T *tuple, long startidx, typval_T *expr);
+varnumber_T tuple_max_min(tuple_T *tuple, int domax, int *error);
+void tuple_repeat(tuple_T *tuple, int n, typval_T *rettv);
+void tuple_reverse(tuple_T *tuple, typval_T *rettv);
+void tuple_reduce(typval_T *argvars, typval_T *expr, typval_T *rettv);
+int check_tuples_addable(type_T *type1, type_T *type2);
+/* vim: set ft=c : */
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index 90dcc54..d30cded 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -18,13 +18,13 @@
 int check_for_opt_number_arg(typval_T *args, int idx);
 int check_for_float_or_nr_arg(typval_T *args, int idx);
 int check_for_bool_arg(typval_T *args, int idx);
-int check_for_bool_or_number_arg(typval_T *args, int idx);
 int check_for_opt_bool_arg(typval_T *args, int idx);
 int check_for_opt_bool_or_number_arg(typval_T *args, int idx);
 int check_for_blob_arg(typval_T *args, int idx);
 int check_for_list_arg(typval_T *args, int idx);
 int check_for_nonnull_list_arg(typval_T *args, int idx);
 int check_for_opt_list_arg(typval_T *args, int idx);
+int check_for_tuple_arg(typval_T *args, int idx);
 int check_for_dict_arg(typval_T *args, int idx);
 int check_for_nonnull_dict_arg(typval_T *args, int idx);
 int check_for_opt_dict_arg(typval_T *args, int idx);
@@ -41,18 +41,20 @@
 int check_for_opt_lnum_arg(typval_T *args, int idx);
 int check_for_string_or_blob_arg(typval_T *args, int idx);
 int check_for_string_or_list_arg(typval_T *args, int idx);
-int check_for_string_or_list_or_blob_arg(typval_T *args, int idx);
+int check_for_string_or_list_or_tuple_or_blob_arg(typval_T *args, int idx);
 int check_for_opt_string_or_list_arg(typval_T *args, int idx);
 int check_for_string_or_dict_arg(typval_T *args, int idx);
 int check_for_string_or_number_or_list_arg(typval_T *args, int idx);
 int check_for_opt_string_or_number_or_list_arg(typval_T *args, int idx);
-int check_for_string_or_number_or_list_or_blob_arg(typval_T *args, int idx);
-int check_for_string_or_list_or_dict_arg(typval_T *args, int idx);
+int check_for_repeat_func_arg(typval_T *args, int idx);
+int check_for_string_list_tuple_or_dict_arg(typval_T *args, int idx);
 int check_for_string_or_func_arg(typval_T *args, int idx);
 int check_for_list_or_blob_arg(typval_T *args, int idx);
-int check_for_list_or_dict_arg(typval_T *args, int idx);
+int check_for_list_or_tuple_arg(typval_T *args, int idx);
+int check_for_list_or_tuple_or_blob_arg(typval_T *args, int idx);
+int check_for_list_or_tuple_or_dict_arg(typval_T *args, int idx);
 int check_for_list_or_dict_or_blob_arg(typval_T *args, int idx);
-int check_for_list_or_dict_or_blob_or_string_arg(typval_T *args, int idx);
+int check_for_list_tuple_dict_blob_or_string_arg(typval_T *args, int idx);
 int check_for_opt_buffer_or_dict_arg(typval_T *args, int idx);
 int check_for_object_arg(typval_T *args, int idx);
 int check_for_class_or_typealias_args(typval_T *args, int idx);
@@ -67,6 +69,7 @@
 void copy_tv(typval_T *from, typval_T *to);
 int typval_compare(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic);
 int typval_compare_list(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
+int typval_compare_tuple(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
 int typval_compare_null(typval_T *tv1, typval_T *tv2);
 int typval_compare_blob(typval_T *tv1, typval_T *tv2, exprtype_T type, int *res);
 int typval_compare_object(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro
index 641648f..a4504c5 100644
--- a/src/proto/vim9instr.pro
+++ b/src/proto/vim9instr.pro
@@ -44,6 +44,7 @@
 int generate_OLDSCRIPT(cctx_T *cctx, isntype_T isn_type, char_u *name, int sid, type_T *type);
 int generate_VIM9SCRIPT(cctx_T *cctx, isntype_T isn_type, int sid, int idx, type_T *type);
 int generate_NEWLIST(cctx_T *cctx, int count, int use_null);
+int generate_NEWTUPLE(cctx_T *cctx, int count, int use_null);
 int generate_NEWDICT(cctx_T *cctx, int count, int use_null);
 int generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, class_T *cl, int object_method, int fi, int *isn_idx);
 int generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name);
diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro
index 093a5ec..865a93c 100644
--- a/src/proto/vim9type.pro
+++ b/src/proto/vim9type.pro
@@ -7,6 +7,7 @@
 void free_type(type_T *type);
 void set_tv_type(typval_T *tv, type_T *type);
 type_T *get_list_type(type_T *member_type, garray_T *type_gap);
+type_T *get_tuple_type(garray_T *tuple_types_gap, garray_T *type_gap);
 type_T *get_dict_type(type_T *member_type, garray_T *type_gap);
 type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
 type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
@@ -27,12 +28,14 @@
 type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
 int equal_type(type_T *type1, type_T *type2, int flags);
 void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap);
+type_T *get_item_type(type_T *type);
 int push_type_stack(cctx_T *cctx, type_T *type);
 int push_type_stack2(cctx_T *cctx, type_T *type, type_T *decl_type);
 void set_type_on_stack(cctx_T *cctx, type_T *type, int offset);
 type_T *get_type_on_stack(cctx_T *cctx, int offset);
 type_T *get_decl_type_on_stack(cctx_T *cctx, int offset);
 type_T *get_member_type_from_stack(int count, int skip, cctx_T *cctx);
+int get_tuple_type_from_stack(int count, garray_T *tuple_types_gap, cctx_T *cctx);
 char *vartype_name(vartype_T type);
 char *type_name(type_T *type, char **tofree);
 void f_typename(typval_T *argvars, typval_T *rettv);